aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
authorZhen Zhang <izgzhen@gmail.com>2016-04-14 15:19:12 +0800
committerZhen Zhang <izgzhen@gmail.com>2016-04-20 08:29:17 +0800
commit11b12f677b14516e92b02c0ded30310b6d6a7f96 (patch)
tree6b7e126a753ced2998ad7728dab06445962480ed /components/script
parentfefdaf76ded7675c0c67fd33f5abfbb5f74ac30f (diff)
downloadservo-11b12f677b14516e92b02c0ded30310b6d6a7f96.tar.gz
servo-11b12f677b14516e92b02c0ded30310b6d6a7f96.zip
element scroll setters
Diffstat (limited to 'components/script')
-rw-r--r--components/script/dom/element.rs268
-rw-r--r--components/script/dom/webidls/Element.webidl7
-rw-r--r--components/script/dom/window.rs23
3 files changed, 259 insertions, 39 deletions
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index 8fa454c0e73..1844bd3e426 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -20,6 +20,7 @@ use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementM
use dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
+use dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, ScrollToOptions};
use dom::bindings::codegen::UnionTypes::NodeOrString;
use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::global::GlobalRef;
@@ -1227,6 +1228,49 @@ impl Element {
_ => Err(Error::Syntax)
}
}
+
+ // https://drafts.csswg.org/cssom-view/#dom-element-scroll
+ pub fn scroll(&self, x_: f64, y_: f64, behavior: ScrollBehavior) {
+
+ // Step 1.2 or 2.3
+ let x = if x_.is_finite() { x_ } else { 0.0f64 };
+ let y = if y_.is_finite() { y_ } else { 0.0f64 };
+
+ let node = self.upcast::<Node>();
+
+ // Step 3
+ let doc = node.owner_doc();
+
+ // Step 4
+ if !doc.is_fully_active() {
+ return;
+ }
+
+ // Step 5
+ let win = doc.DefaultView();
+
+ // Step 7
+ if *self.root_element() == *self {
+ if doc.quirks_mode() != Quirks {
+ win.scroll(x, y, behavior);
+ }
+
+ return;
+ }
+
+ // Step 9
+ if doc.GetBody().r() == self.downcast::<HTMLElement>() &&
+ doc.quirks_mode() == Quirks &&
+ !self.potentially_scrollable() {
+ win.scroll(x, y, behavior);
+ return;
+ }
+
+ // Step 10 (TODO)
+
+ // Step 11
+ win.scroll_node(node.to_trusted_node_address(), x, y, behavior);
+ }
}
impl ElementMethods for Element {
@@ -1483,66 +1527,218 @@ impl ElementMethods for Element {
rect.size.height.to_f64_px())
}
+ // https://drafts.csswg.org/cssom-view/#dom-element-scroll
+ fn Scroll(&self, options: &ScrollToOptions) {
+ // Step 1
+ let left = options.left.unwrap_or(self.ScrollLeft());
+ let top = options.top.unwrap_or(self.ScrollTop());
+ self.scroll(left, top, options.parent.behavior);
+ }
+
+ // https://drafts.csswg.org/cssom-view/#dom-element-scroll
+ fn Scroll_(&self, x: f64, y: f64) {
+ self.scroll(x, y, ScrollBehavior::Auto);
+ }
+
+ // https://drafts.csswg.org/cssom-view/#dom-element-scrollto
+ fn ScrollTo(&self, options: &ScrollToOptions) {
+ self.Scroll(options);
+ }
+
+ // https://drafts.csswg.org/cssom-view/#dom-element-scrollto
+ fn ScrollTo_(&self, x: f64, y: f64) {
+ self.Scroll_(x, y);
+ }
+
+ // https://drafts.csswg.org/cssom-view/#dom-element-scrollby
+ fn ScrollBy(&self, options: &ScrollToOptions) {
+ // Step 2
+ let delta_left = options.left.unwrap_or(0.0f64);
+ let delta_top = options.top.unwrap_or(0.0f64);
+ let left = self.ScrollLeft();
+ let top = self.ScrollTop();
+ self.scroll(left + delta_left, top + delta_top,
+ options.parent.behavior);
+ }
+
+ // https://drafts.csswg.org/cssom-view/#dom-element-scrollby
+ fn ScrollBy_(&self, x: f64, y: f64) {
+ let left = self.ScrollLeft();
+ let top = self.ScrollTop();
+ self.scroll(left + x, top + y, ScrollBehavior::Auto);
+ }
+
// https://drafts.csswg.org/cssom-view/#dom-element-scrolltop
fn ScrollTop(&self) -> f64 {
let node = self.upcast::<Node>();
- // 1. Let document be the element’s node document.
+ // Step 1
let doc = node.owner_doc();
- // 2. If the document is not the active document, return zero and terminate these steps.
+ // Step 2
if !doc.is_fully_active() {
return 0.0;
- } else {
- // 3. Let window be the value of document’s defaultView attribute.
- let win = doc.DefaultView();
-
- // 5. If the element is the root element and document is in quirks mode,
- // return zero and terminate these steps.
- if *self.root_element() == *self {
- if doc.quirks_mode() == Quirks {
- return 0.0;
- }
+ }
- // 6. If the element is the root element return the value of scrollY on window.
- return (*win).ScrollY() as f64;
- }
+ // Step 3
+ let win = doc.DefaultView();
- // 7. If the element is the HTML body element, document is in quirks mode,
- // and the element is not potentially scrollable, return the value of scrollY on window.
- if doc.GetBody().r() == self.downcast::<HTMLElement>() &&
- doc.quirks_mode() == Quirks &&
- !self.potentially_scrollable() {
- return (*win).ScrollY() as f64;
+ // Step 5
+ if *self.root_element() == *self {
+ if doc.quirks_mode() == Quirks {
+ return 0.0;
}
+ // Step 6
+ return win.ScrollY() as f64;
+ }
- // 8. If the element does not have any associated CSS layout box, return zero and terminate these steps.
- if !self.has_css_layout_box() {
- return 0.0;
- }
+ // Step 7
+ if doc.GetBody().r() == self.downcast::<HTMLElement>() &&
+ doc.quirks_mode() == Quirks &&
+ !self.potentially_scrollable() {
+ return win.ScrollY() as f64;
+ }
- // 9. Return the y-coordinate of the scrolling area at the alignment point
- // with the top of the padding edge of the element.
- let point = node.scroll_offset();
- return -point.y as f64;
+
+ // Step 8
+ if !self.has_css_layout_box() {
+ return 0.0;
}
+
+ // Step 9
+ let point = node.scroll_offset();
+ return point.y.abs() as f64;
}
// https://drafts.csswg.org/cssom-view/#dom-element-scrolltop
- fn SetScrollTop(&self, _scroll_top: f64) {
- unimplemented!()
+ fn SetScrollTop(&self, y_: f64) {
+ let behavior = ScrollBehavior::Auto;
+
+ // Step 1, 2
+ let y = if y_.is_finite() { y_ } else { 0.0f64 };
+
+ let node = self.upcast::<Node>();
+
+ // Step 3
+ let doc = node.owner_doc();
+
+ // Step 4
+ if !doc.is_fully_active() {
+ return;
+ }
+
+ // Step 5
+ let win = doc.DefaultView();
+
+ // Step 7
+ if *self.root_element() == *self {
+ if doc.quirks_mode() != Quirks {
+ win.scroll(win.ScrollX() as f64, y, behavior);
+ }
+
+ return;
+ }
+
+ // Step 9
+ if doc.GetBody().r() == self.downcast::<HTMLElement>() &&
+ doc.quirks_mode() == Quirks &&
+ !self.potentially_scrollable() {
+ win.scroll(win.ScrollX() as f64, y, behavior);
+ return;
+ }
+
+ // Step 10 (TODO)
+
+ // Step 11
+ win.scroll_node(node.to_trusted_node_address(), self.ScrollLeft(), y, behavior);
}
- // https://drafts.csswg.org/cssom-view/#dom-element-scrollleft
+ // https://drafts.csswg.org/cssom-view/#dom-element-scrolltop
fn ScrollLeft(&self) -> f64 {
- let point = self.upcast::<Node>().scroll_offset();
- return -point.x as f64;
+ let node = self.upcast::<Node>();
+
+ // Step 1
+ let doc = node.owner_doc();
+
+ // Step 2
+ if !doc.is_fully_active() {
+ return 0.0;
+ }
+
+ // Step 3
+ let win = doc.DefaultView();
+
+ // Step 5
+ if *self.root_element() == *self {
+ if doc.quirks_mode() != Quirks {
+ // Step 6
+ return win.ScrollX() as f64;
+ }
+
+ return 0.0;
+ }
+
+ // Step 7
+ if doc.GetBody().r() == self.downcast::<HTMLElement>() &&
+ doc.quirks_mode() == Quirks &&
+ !self.potentially_scrollable() {
+ return win.ScrollX() as f64;
+ }
+
+
+ // Step 8
+ if !self.has_css_layout_box() {
+ return 0.0;
+ }
+
+ // Step 9
+ let point = node.scroll_offset();
+ return point.x.abs() as f64;
}
// https://drafts.csswg.org/cssom-view/#dom-element-scrollleft
- fn SetScrollLeft(&self, _scroll_left: f64) {
- unimplemented!()
+ fn SetScrollLeft(&self, x_: f64) {
+ let behavior = ScrollBehavior::Auto;
+
+ // Step 1, 2
+ let x = if x_.is_finite() { x_ } else { 0.0f64 };
+
+ let node = self.upcast::<Node>();
+
+ // Step 3
+ let doc = node.owner_doc();
+
+ // Step 4
+ if !doc.is_fully_active() {
+ return;
+ }
+
+ // Step 5
+ let win = doc.DefaultView();
+
+ // Step 7
+ if *self.root_element() == *self {
+ if doc.quirks_mode() == Quirks {
+ return;
+ }
+
+ win.scroll(x, win.ScrollY() as f64, behavior);
+ return;
+ }
+
+ // Step 9
+ if doc.GetBody().r() == self.downcast::<HTMLElement>() &&
+ doc.quirks_mode() == Quirks &&
+ !self.potentially_scrollable() {
+ win.scroll(x, win.ScrollY() as f64, behavior);
+ return;
+ }
+
+ // Step 10 (TODO)
+
+ // Step 11
+ win.scroll_node(node.to_trusted_node_address(), x, self.ScrollTop(), behavior);
}
// https://drafts.csswg.org/cssom-view/#dom-element-scrollwidth
diff --git a/components/script/dom/webidls/Element.webidl b/components/script/dom/webidls/Element.webidl
index b161a782a55..19cb67e8cb9 100644
--- a/components/script/dom/webidls/Element.webidl
+++ b/components/script/dom/webidls/Element.webidl
@@ -81,6 +81,13 @@ partial interface Element {
DOMRectList getClientRects();
DOMRect getBoundingClientRect();
+ void scroll(optional ScrollToOptions options);
+ void scroll(unrestricted double x, unrestricted double y);
+
+ void scrollTo(optional ScrollToOptions options);
+ void scrollTo(unrestricted double x, unrestricted double y);
+ void scrollBy(optional ScrollToOptions options);
+ void scrollBy(unrestricted double x, unrestricted double y);
attribute unrestricted double scrollTop;
attribute unrestricted double scrollLeft;
readonly attribute long scrollWidth;
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index 75c7089fac3..8f36193c2eb 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -912,11 +912,13 @@ impl Window {
//TODO Step 11
//let document = self.Document();
// Step 12
- self.perform_a_scroll(x.to_f32().unwrap_or(0.0f32), y.to_f32().unwrap_or(0.0f32), behavior, None);
+ self.perform_a_scroll(x.to_f32().unwrap_or(0.0f32), y.to_f32().unwrap_or(0.0f32),
+ LayerId::null(), behavior, None);
}
/// https://drafts.csswg.org/cssom-view/#perform-a-scroll
- pub fn perform_a_scroll(&self, x: f32, y: f32, behavior: ScrollBehavior, element: Option<&Element>) {
+ pub fn perform_a_scroll(&self, x: f32, y: f32, layer_id: LayerId,
+ behavior: ScrollBehavior, element: Option<&Element>) {
//TODO Step 1
let point = Point2D::new(x, y);
let smooth = match behavior {
@@ -935,7 +937,7 @@ impl Window {
self.current_viewport.set(Rect::new(Point2D::new(Au::from_f32_px(x), Au::from_f32_px(y)), size));
self.compositor.send(ScriptToCompositorMsg::ScrollFragmentPoint(
- self.pipeline(), LayerId::null(), point, smooth)).unwrap()
+ self.pipeline(), layer_id, point, smooth)).unwrap()
}
pub fn client_window(&self) -> (Size2D<u32>, Point2D<i32>) {
@@ -1142,6 +1144,21 @@ impl Window {
recv.recv().unwrap_or(Point2D::zero())
}
+ // https://drafts.csswg.org/cssom-view/#dom-element-scroll
+ pub fn scroll_node(&self, node: TrustedNodeAddress,
+ x_: f64, y_: f64, behavior: ScrollBehavior) {
+
+ self.reflow(ReflowGoal::ForScriptQuery,
+ ReflowQueryType::NodeLayerIdQuery(node),
+ ReflowReason::Query);
+
+ let layer_id = self.layout_rpc.node_layer_id().layer_id;
+
+ // Step 12
+ self.perform_a_scroll(x_.to_f32().unwrap_or(0.0f32), y_.to_f32().unwrap_or(0.0f32),
+ layer_id, behavior, None);
+ }
+
pub fn resolved_style_query(&self,
element: TrustedNodeAddress,
pseudo: Option<PseudoElement>,