diff options
author | Glenn Watson <gw@intuitionlibrary.com> | 2015-07-27 15:20:27 +1000 |
---|---|---|
committer | Glenn Watson <gw@intuitionlibrary.com> | 2015-08-03 11:55:38 +1000 |
commit | 9e5687e3e72f2c79bf17bcfb33ea33f0659377ac (patch) | |
tree | 747b19a3de028cebc1dca77f6edd1a38fba1cf33 /components/script/dom | |
parent | 1809748dc12ec63e3179b66109c91983f744c235 (diff) | |
download | servo-9e5687e3e72f2c79bf17bcfb33ea33f0659377ac.tar.gz servo-9e5687e3e72f2c79bf17bcfb33ea33f0659377ac.zip |
Implement offsetParent/Top/Left/Width/Height.
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/htmlelement.rs | 59 | ||||
-rw-r--r-- | components/script/dom/webidls/HTMLElement.webidl | 11 | ||||
-rw-r--r-- | components/script/dom/window.rs | 27 |
3 files changed, 94 insertions, 3 deletions
diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs index 513a9d39775..376bec890cc 100644 --- a/components/script/dom/htmlelement.rs +++ b/components/script/dom/htmlelement.rs @@ -12,7 +12,7 @@ use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementM use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLFrameSetElementDerived}; use dom::bindings::codegen::InheritTypes::{EventTargetCast, HTMLInputElementCast, NodeCast}; -use dom::bindings::codegen::InheritTypes::{HTMLElementDerived, HTMLBodyElementDerived}; +use dom::bindings::codegen::InheritTypes::{HTMLElementDerived, HTMLBodyElementDerived, HTMLHtmlElementDerived}; use dom::bindings::js::{JS, MutNullableHeap, Root}; use dom::bindings::error::ErrorResult; use dom::bindings::error::Error::Syntax; @@ -216,6 +216,63 @@ impl<'a> HTMLElementMethods for &'a HTMLElement { // If `request_focus` is not called, focus will be set to None. document.r().commit_focus_transaction(FocusType::Element); } + + // https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface + fn GetOffsetParent(self) -> Option<Root<Element>> { + if self.is_htmlbodyelement() || self.is_htmlhtmlelement() { + return None; + } + + let node = NodeCast::from_ref(self); + let window = window_from_node(self); + let (element, _) = window.offset_parent_query(node.to_trusted_node_address()); + + element + } + + // https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface + fn OffsetTop(self) -> i32 { + if self.is_htmlbodyelement() { + return 0; + } + + let node = NodeCast::from_ref(self); + let window = window_from_node(self); + let (_, rect) = window.offset_parent_query(node.to_trusted_node_address()); + + rect.origin.y.to_nearest_px() + } + + // https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface + fn OffsetLeft(self) -> i32 { + if self.is_htmlbodyelement() { + return 0; + } + + let node = NodeCast::from_ref(self); + let window = window_from_node(self); + let (_, rect) = window.offset_parent_query(node.to_trusted_node_address()); + + rect.origin.x.to_nearest_px() + } + + // https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface + fn OffsetWidth(self) -> i32 { + let node = NodeCast::from_ref(self); + let window = window_from_node(self); + let (_, rect) = window.offset_parent_query(node.to_trusted_node_address()); + + rect.size.width.to_nearest_px() + } + + // https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface + fn OffsetHeight(self) -> i32 { + let node = NodeCast::from_ref(self); + let window = window_from_node(self); + let (_, rect) = window.offset_parent_query(node.to_trusted_node_address()); + + rect.size.height.to_nearest_px() + } } // https://html.spec.whatwg.org/#attr-data-* diff --git a/components/script/dom/webidls/HTMLElement.webidl b/components/script/dom/webidls/HTMLElement.webidl index f4c0376b618..90b11d85bff 100644 --- a/components/script/dom/webidls/HTMLElement.webidl +++ b/components/script/dom/webidls/HTMLElement.webidl @@ -45,5 +45,16 @@ interface HTMLElement : Element { //readonly attribute boolean? commandDisabled; //readonly attribute boolean? commandChecked; }; + +// http://dev.w3.org/csswg/cssom-view/#extensions-to-the-htmlelement-interface +partial interface HTMLElement { + // CSSOM things are not [Pure] because they can flush + readonly attribute Element? offsetParent; + readonly attribute long offsetTop; + readonly attribute long offsetLeft; + readonly attribute long offsetWidth; + readonly attribute long offsetHeight; +}; + HTMLElement implements GlobalEventHandlers; HTMLElement implements ElementCSSInlineStyle; diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index d7a9e9f243a..1320ca354b9 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::EventHandlerBinding::{OnErrorEventHandlerN use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; use dom::bindings::codegen::Bindings::FunctionBinding::Function; use dom::bindings::codegen::Bindings::WindowBinding::{self, WindowMethods, FrameRequestCallback}; -use dom::bindings::codegen::InheritTypes::{NodeCast, EventTargetCast}; +use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, EventTargetCast}; use dom::bindings::global::global_object_for_js_object; use dom::bindings::error::{report_pending_exception, Fallible}; use dom::bindings::error::Error::InvalidCharacter; @@ -27,7 +27,7 @@ use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId}; use dom::htmlelement::HTMLElement; use dom::location::Location; use dom::navigator::Navigator; -use dom::node::{window_from_node, TrustedNodeAddress, NodeHelpers}; +use dom::node::{window_from_node, TrustedNodeAddress, NodeHelpers, from_untrusted_node_address}; use dom::performance::Performance; use dom::screen::Screen; use dom::storage::Storage; @@ -578,6 +578,7 @@ pub trait WindowHelpers { fn client_rect_query(self, node_geometry_request: TrustedNodeAddress) -> Rect<i32>; fn resolved_style_query(self, element: TrustedNodeAddress, pseudo: Option<PseudoElement>, property: &Atom) -> Option<String>; + fn offset_parent_query(self, node: TrustedNodeAddress) -> (Option<Root<Element>>, Rect<Au>); fn handle_reflow_complete_msg(self, reflow_id: u32); fn set_fragment_name(self, fragment: Option<String>); fn steal_fragment_name(self) -> Option<String>; @@ -827,6 +828,27 @@ impl<'a> WindowHelpers for &'a Window { resolved } + fn offset_parent_query(self, node: TrustedNodeAddress) -> (Option<Root<Element>>, Rect<Au>) { + self.reflow(ReflowGoal::ForScriptQuery, + ReflowQueryType::OffsetParentQuery(node), + ReflowReason::Query); + let response = self.layout_rpc.offset_parent(); + let js_runtime = self.js_runtime.borrow(); + let js_runtime = js_runtime.as_ref().unwrap(); + let element = match response.node_address { + Some(parent_node_address) => { + let node = from_untrusted_node_address(js_runtime.rt(), + parent_node_address); + let element = ElementCast::to_ref(node.r()).unwrap(); + Some(Root::from_ref(element)) + } + None => { + None + } + }; + (element, response.rect) + } + fn handle_reflow_complete_msg(self, reflow_id: u32) { let last_reflow_id = self.last_reflow_id.get(); if last_reflow_id == reflow_id { @@ -1135,6 +1157,7 @@ fn debug_reflow_events(goal: &ReflowGoal, query_type: &ReflowQueryType, reason: ReflowQueryType::ContentBoxesQuery(_n) => "\tContentBoxesQuery", ReflowQueryType::NodeGeometryQuery(_n) => "\tNodeGeometryQuery", ReflowQueryType::ResolvedStyleQuery(_, _, _) => "\tResolvedStyleQuery", + ReflowQueryType::OffsetParentQuery(_n) => "\tOffsetParentQuery", }); debug_msg.push_str(match *reason { |