diff options
Diffstat (limited to 'components/script/dom/document.rs')
-rw-r--r-- | components/script/dom/document.rs | 88 |
1 files changed, 69 insertions, 19 deletions
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index bff8ea0cdba..aa360edd3a3 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -19,6 +19,7 @@ use dom::bindings::codegen::InheritTypes::{HTMLAnchorElementDerived, HTMLAppletE use dom::bindings::codegen::InheritTypes::{HTMLAreaElementDerived, HTMLEmbedElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLFormElementDerived, HTMLImageElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLScriptElementDerived, CharacterDataCast}; +use dom::bindings::codegen::UnionTypes::NodeOrString; use dom::bindings::error::{ErrorResult, Fallible}; use dom::bindings::error::Error::{NotSupported, InvalidCharacter, Security}; use dom::bindings::error::Error::HierarchyRequest; @@ -63,7 +64,7 @@ use dom::window::{Window, WindowHelpers, ReflowReason}; use layout_interface::{HitTestResponse, MouseOverResponse}; use msg::compositor_msg::ScriptListener; use msg::constellation_msg::Msg as ConstellationMsg; -use msg::constellation_msg::{ConstellationChan, Key, KeyState, KeyModifiers, MozBrowserEvent}; +use msg::constellation_msg::{ConstellationChan, FocusType, Key, KeyState, KeyModifiers, MozBrowserEvent}; use msg::constellation_msg::{SUPER, ALT, SHIFT, CONTROL}; use net_traits::CookieSource::NonHTTP; use net_traits::ControlMsg::{SetCookiesForUrl, GetCookiesForUrl}; @@ -215,7 +216,7 @@ pub trait DocumentHelpers<'a> { fn is_scripting_enabled(self) -> bool; fn begin_focus_transaction(self); fn request_focus(self, elem: JSRef<Element>); - fn commit_focus_transaction(self); + fn commit_focus_transaction(self, focus_type: FocusType); fn title_changed(self); fn send_title_to_compositor(self); fn dirty_all_nodes(self); @@ -223,12 +224,14 @@ pub trait DocumentHelpers<'a> { button: MouseButton, point: Point2D<f32>); fn dispatch_key_event(self, key: Key, state: KeyState, modifiers: KeyModifiers, compositor: &mut Box<ScriptListener+'static>); + fn node_from_nodes_and_strings(self, nodes: Vec<NodeOrString>) + -> Fallible<Temporary<Node>>; /// Handles a mouse-move event coming from the compositor. fn handle_mouse_move_event(self, js_runtime: *mut JSRuntime, point: Point2D<f32>, - prev_mouse_over_targets: &mut Vec<JS<Node>>); + prev_mouse_over_targets: &mut RootedVec<JS<Node>>); fn set_current_script(self, script: Option<JSRef<HTMLScriptElement>>); fn trigger_mozbrowser_event(self, event: MozBrowserEvent); @@ -457,7 +460,7 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> { /// Reassign the focus context to the element that last requested focus during this /// transaction, or none if no elements requested it. - fn commit_focus_transaction(self) { + fn commit_focus_transaction(self, focus_type: FocusType) { //TODO: dispatch blur, focus, focusout, and focusin events if let Some(ref elem) = self.focused.get().root() { @@ -470,9 +473,16 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> { if let Some(ref elem) = self.focused.get().root() { let node: JSRef<Node> = NodeCast::from_ref(elem.r()); node.set_focus_state(true); + + // Update the focus state for all elements in the focus chain. + // https://html.spec.whatwg.org/multipage/#focus-chain + if focus_type == FocusType::Element { + let window = self.window.root(); + let ConstellationChan(ref chan) = window.r().constellation_chan(); + let event = ConstellationMsg::FocusMsg(window.r().pipeline()); + chan.send(event).unwrap(); + } } - // TODO: Update the focus state for all elements in the focus chain. - // https://html.spec.whatwg.org/multipage/interaction.html#focus-chain } /// Handles any updates when the document's title has changed. @@ -549,27 +559,28 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> { // https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#trusted-events event.set_trusted(true); - // https://html.spec.whatwg.org/multipage/interaction.html#run-authentic-click-activation-steps + // https://html.spec.whatwg.org/multipage/#run-authentic-click-activation-steps el.r().authentic_click_activation(event); - self.commit_focus_transaction(); + self.commit_focus_transaction(FocusType::Element); window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::MouseEvent); } fn handle_mouse_move_event(self, js_runtime: *mut JSRuntime, point: Point2D<f32>, - prev_mouse_over_targets: &mut Vec<JS<Node>>) { + prev_mouse_over_targets: &mut RootedVec<JS<Node>>) { // Build a list of elements that are currently under the mouse. let mouse_over_addresses = self.get_nodes_under_mouse(&point); - let mouse_over_targets: Vec<JS<Node>> = mouse_over_addresses.iter() - .filter_map(|node_address| { + let mut mouse_over_targets: RootedVec<JS<Node>> = RootedVec::new(); + for node_address in mouse_over_addresses.iter() { let node = node::from_untrusted_node_address(js_runtime, *node_address); - node.root().r().inclusive_ancestors() - .map(|node| node.root()) - .find(|node| node.r().is_element()) - .map(|node| JS::from_rooted(node.r())) - }).collect(); + mouse_over_targets.push(node.root().r().inclusive_ancestors() + .map(|node| node.root()) + .find(|node| node.r() + .is_element()) + .map(|node| JS::from_rooted(node.r())).unwrap()); + }; // Remove hover from any elements in the previous list that are no longer // under the mouse. @@ -616,7 +627,8 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> { } // Store the current mouse over targets for next frame - *prev_mouse_over_targets = mouse_over_targets; + prev_mouse_over_targets.clear(); + prev_mouse_over_targets.append(&mut *mouse_over_targets); let window = self.window.root(); window.r().reflow(ReflowGoal::ForDisplay, @@ -702,6 +714,34 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> { window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::KeyEvent); } + fn node_from_nodes_and_strings(self, nodes: Vec<NodeOrString>) + -> Fallible<Temporary<Node>> { + if nodes.len() == 1 { + match nodes.into_iter().next().unwrap() { + NodeOrString::eNode(node) => Ok(Temporary::from_unrooted(node)), + NodeOrString::eString(string) => { + Ok(NodeCast::from_temporary(self.CreateTextNode(string))) + }, + } + } else { + let fragment = NodeCast::from_temporary(self.CreateDocumentFragment()).root(); + for node in nodes.into_iter() { + match node { + NodeOrString::eNode(node) => { + try!(fragment.r().AppendChild(node.root().r())); + }, + NodeOrString::eString(string) => { + let node = NodeCast::from_temporary(self.CreateTextNode(string)).root(); + // No try!() here because appending a text node + // should not fail. + fragment.r().AppendChild(node.r()).unwrap(); + } + } + } + Ok(Temporary::from_rooted(fragment.r())) + } + } + fn set_current_script(self, script: Option<JSRef<HTMLScriptElement>>) { self.current_script.assign(script); } @@ -763,7 +803,7 @@ impl Document { implementation: Default::default(), location: Default::default(), content_type: match content_type { - Some(string) => string.clone(), + Some(string) => string, None => match is_html_document { // https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument IsHTMLDocument::HTMLDocument => "text/html".to_owned(), @@ -877,7 +917,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { self.url().serialize() } - // https://html.spec.whatwg.org/multipage/interaction.html#dom-document-activeelement + // https://html.spec.whatwg.org/multipage/#dom-document-activeelement fn GetActiveElement(self) -> Option<Temporary<Element>> { // TODO: Step 2. @@ -1377,6 +1417,16 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { NodeCast::from_ref(self).child_elements().count() as u32 } + // https://dom.spec.whatwg.org/#dom-parentnode-prepend + fn Prepend(self, nodes: Vec<NodeOrString>) -> ErrorResult { + NodeCast::from_ref(self).prepend(nodes) + } + + // https://dom.spec.whatwg.org/#dom-parentnode-append + fn Append(self, nodes: Vec<NodeOrString>) -> ErrorResult { + NodeCast::from_ref(self).append(nodes) + } + // https://dom.spec.whatwg.org/#dom-parentnode-queryselector fn QuerySelector(self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>> { let root: JSRef<Node> = NodeCast::from_ref(self); |