aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/element.rs10
-rw-r--r--components/script/dom/node.rs41
-rw-r--r--components/script/dom/webidls/Element.webidl3
-rw-r--r--components/script/dom/window.rs8
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",