diff options
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/element.rs | 10 | ||||
-rw-r--r-- | components/script/dom/node.rs | 41 | ||||
-rw-r--r-- | components/script/dom/webidls/Element.webidl | 3 | ||||
-rw-r--r-- | components/script/dom/window.rs | 8 |
4 files changed, 62 insertions, 0 deletions
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 3eec2575bc3..25d9f0d45b8 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -1421,6 +1421,16 @@ impl ElementMethods for Element { rect.size.height.to_f64_px()) } + // https://drafts.csswg.org/cssom-view/#dom-element-scrollwidth + fn ScrollWidth(&self) -> i32 { + self.upcast::<Node>().get_scroll_area().size.width + } + + // https://drafts.csswg.org/cssom-view/#dom-element-scrollheight + fn ScrollHeight(&self) -> i32 { + self.upcast::<Node>().get_scroll_area().size.height + } + // https://drafts.csswg.org/cssom-view/#dom-element-clienttop fn ClientTop(&self) -> i32 { self.upcast::<Node>().get_client_rect().origin.y diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 717be0331d5..fed47bb7b24 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -18,6 +18,7 @@ use dom::bindings::codegen::Bindings::NamedNodeMapBinding::NamedNodeMapMethods; use dom::bindings::codegen::Bindings::NodeBinding::{NodeConstants, NodeMethods}; use dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods; use dom::bindings::codegen::Bindings::ProcessingInstructionBinding::ProcessingInstructionMethods; +use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::codegen::UnionTypes::NodeOrString; use dom::bindings::conversions::{self, DerivedFrom}; use dom::bindings::error::{Error, ErrorResult, Fallible}; @@ -37,6 +38,7 @@ use dom::documentfragment::DocumentFragment; use dom::documenttype::DocumentType; use dom::element::{Element, ElementCreator}; use dom::eventtarget::EventTarget; +use dom::htmlbodyelement::HTMLBodyElement; use dom::htmlcollection::HTMLCollection; use dom::htmlelement::HTMLElement; use dom::nodelist::NodeList; @@ -45,8 +47,11 @@ use dom::range::WeakRangeVec; use dom::text::Text; use dom::virtualmethods::{VirtualMethods, vtable_for}; use dom::window::Window; +use euclid::point::Point2D; use euclid::rect::Rect; +use euclid::size::Size2D; use heapsize::{HeapSizeOf, heap_size_of}; +use html5ever::tree_builder::QuirksMode; use js::jsapi::{JSContext, JSObject, JSRuntime}; use layout_interface::{LayoutChan, Msg}; use libc::{self, c_void, uintptr_t}; @@ -577,6 +582,42 @@ impl Node { window_from_node(self).client_rect_query(self.to_trusted_node_address()) } + // https://drafts.csswg.org/cssom-view/#dom-element-scrollwidth + // https://drafts.csswg.org/cssom-view/#dom-element-scrollheight + // https://drafts.csswg.org/cssom-view/#dom-element-scrolltop + // https://drafts.csswg.org/cssom-view/#dom-element-scrollleft + pub fn get_scroll_area(&self) -> Rect<i32> { + // Step 1 + let document = self.owner_doc(); + // Step 3 + let window = document.window(); + + let html_element = document.GetDocumentElement(); + + let is_body_element = html_element.r().and_then(|root| { + let node = root.upcast::<Node>(); + node.children().find(|child| { child.is::<HTMLBodyElement>() }).map(|node| { + *node.r() == *self + }) + }).unwrap_or(false); + + let scroll_area = window.scroll_area_query(self.to_trusted_node_address()); + + match (document != window.Document(), is_body_element, document.quirks_mode(), + html_element.r() == self.downcast::<Element>()) { + // Step 2 && Step 5 + (true, _, _, _) | (_, false, QuirksMode::Quirks, true) => Rect::zero(), + // Step 6 && Step 7 + (false, false, _, true) | (false, true, QuirksMode::Quirks, _) => { + Rect::new(Point2D::new(window.ScrollX(), window.ScrollY()), + Size2D::new(max(window.InnerWidth(), scroll_area.size.width), + max(window.InnerHeight(), scroll_area.size.height))) + }, + // Step 9 + _ => scroll_area + } + } + // https://dom.spec.whatwg.org/#dom-childnode-before pub fn before(&self, nodes: Vec<NodeOrString>) -> ErrorResult { // Step 1. diff --git a/components/script/dom/webidls/Element.webidl b/components/script/dom/webidls/Element.webidl index 900c2eb24dc..c5c395536ac 100644 --- a/components/script/dom/webidls/Element.webidl +++ b/components/script/dom/webidls/Element.webidl @@ -77,6 +77,9 @@ partial interface Element { DOMRectList getClientRects(); DOMRect getBoundingClientRect(); + readonly attribute long scrollWidth; + readonly attribute long scrollHeight; + readonly attribute long clientTop; readonly attribute long clientLeft; readonly attribute long clientWidth; diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index eeb62d833c6..df7d1f92de7 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -1110,6 +1110,13 @@ impl Window { self.layout_rpc.hit_test().node_address } + pub fn scroll_area_query(&self, node: TrustedNodeAddress) -> Rect<i32> { + self.reflow(ReflowGoal::ForScriptQuery, + ReflowQueryType::NodeScrollGeometryQuery(node), + ReflowReason::Query); + self.layout_rpc.node_scroll_area().client_rect + } + pub fn resolved_style_query(&self, element: TrustedNodeAddress, pseudo: Option<PseudoElement>, @@ -1463,6 +1470,7 @@ fn debug_reflow_events(id: PipelineId, goal: &ReflowGoal, query_type: &ReflowQue ReflowQueryType::ContentBoxesQuery(_n) => "\tContentBoxesQuery", ReflowQueryType::HitTestQuery(_n, _o) => "\tHitTestQuery", ReflowQueryType::NodeGeometryQuery(_n) => "\tNodeGeometryQuery", + ReflowQueryType::NodeScrollGeometryQuery(_n) => "\tNodeScrollGeometryQuery", ReflowQueryType::ResolvedStyleQuery(_, _, _) => "\tResolvedStyleQuery", ReflowQueryType::OffsetParentQuery(_n) => "\tOffsetParentQuery", ReflowQueryType::MarginStyleQuery(_n) => "\tMarginStyleQuery", |