diff options
author | Zhen Zhang <izgzhen@gmail.com> | 2016-04-14 15:19:12 +0800 |
---|---|---|
committer | Zhen Zhang <izgzhen@gmail.com> | 2016-04-20 08:29:17 +0800 |
commit | 11b12f677b14516e92b02c0ded30310b6d6a7f96 (patch) | |
tree | 6b7e126a753ced2998ad7728dab06445962480ed /components/script | |
parent | fefdaf76ded7675c0c67fd33f5abfbb5f74ac30f (diff) | |
download | servo-11b12f677b14516e92b02c0ded30310b6d6a7f96.tar.gz servo-11b12f677b14516e92b02c0ded30310b6d6a7f96.zip |
element scroll setters
Diffstat (limited to 'components/script')
-rw-r--r-- | components/script/dom/element.rs | 268 | ||||
-rw-r--r-- | components/script/dom/webidls/Element.webidl | 7 | ||||
-rw-r--r-- | components/script/dom/window.rs | 23 |
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>, |