diff --git a/src/components/script/dom/document.rs b/src/components/script/dom/document.rs index 497a739e172..9b4d7aaf55d 100644 --- a/src/components/script/dom/document.rs +++ b/src/components/script/dom/document.rs @@ -12,7 +12,8 @@ use dom::bindings::js::{JS, JSRef, Temporary, OptionalSettable, TemporaryPushabl use dom::bindings::js::OptionalRootable; use dom::bindings::trace::Untraceable; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; -use dom::bindings::error::{ErrorResult, Fallible, NotSupported, InvalidCharacter, HierarchyRequest, NamespaceError}; +use dom::bindings::error::{ErrorResult, Fallible, NotSupported, InvalidCharacter}; +use dom::bindings::error::{HierarchyRequest, NamespaceError}; use dom::bindings::utils::{xml_name_type, InvalidXMLName, Name, QName}; use dom::comment::Comment; use dom::customevent::CustomEvent; @@ -806,13 +807,16 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { window.Location() } + // http://dom.spec.whatwg.org/#dom-parentnode-children fn Children(&self) -> Temporary { let window = self.window.root(); HTMLCollection::children(&*window, NodeCast::from_ref(self)) } + // http://dom.spec.whatwg.org/#dom-parentnode-queryselector fn QuerySelector(&self, selectors: DOMString) -> Fallible>> { - Ok(None) + let root: &JSRef = NodeCast::from_ref(self); + root.query_selector(selectors) } fn GetOnload(&self) -> Option { diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index af0dbd97979..5fa704810b2 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -15,7 +15,7 @@ use dom::bindings::js::{JS, JSRef, RootedReference, Temporary, Root, OptionalUnr use dom::bindings::js::{OptionalSettable, TemporaryPushable, OptionalRootedRootable}; use dom::bindings::js::{ResultRootable, OptionalRootable}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; -use dom::bindings::error::{ErrorResult, Fallible, NotFound, HierarchyRequest}; +use dom::bindings::error::{ErrorResult, Fallible, NotFound, HierarchyRequest, Syntax}; use dom::bindings::utils; use dom::characterdata::{CharacterData, CharacterDataMethods}; use dom::comment::Comment; @@ -36,6 +36,7 @@ use layout_interface::{ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery, C LayoutChan, ReapLayoutDataMsg, TrustedNodeAddress, UntrustedNodeAddress}; use servo_util::geometry::Au; use servo_util::str::{DOMString, null_str_as_empty}; +use style::{parse_selector_list, matches_compound_selector, NamespaceMap}; use js::jsapi::{JSContext, JSObject, JSRuntime}; use js::jsfriendapi; @@ -396,6 +397,8 @@ pub trait NodeHelpers { fn get_bounding_content_box(&self) -> Rect; fn get_content_boxes(&self) -> Vec>; + fn query_selector(&self, selectors: DOMString) -> Fallible>>; + fn remove_self(&self); } @@ -552,6 +555,30 @@ impl<'a> NodeHelpers for JSRef<'a, Node> { rects } + // http://dom.spec.whatwg.org/#dom-parentnode-queryselector + fn query_selector(&self, selectors: DOMString) -> Fallible>> { + // Step 1. + let namespace = NamespaceMap::new(); + match parse_selector_list(tokenize(selectors.as_slice()).map(|(token, _)| token).collect(), &namespace) { + // Step 2. + None => return Err(Syntax), + // Step 3. + Some(ref selectors) => { + for selector in selectors.iter() { + assert!(selector.pseudo_element.is_none()); + for elem in self.child_elements() { + let node: &JSRef = NodeCast::from_ref(&elem); + let mut _shareable: bool = false; + if matches_compound_selector(selector.compound_selectors.deref(), node, &mut _shareable) { + return Ok(Some(Temporary::from_rooted(&elem))); + } + } + } + } + } + Ok(None) + } + fn ancestors(&self) -> AncestorIterator { AncestorIterator { current: self.parent_node.get().map(|node| (*node.root()).clone()), diff --git a/src/components/script/script.rs b/src/components/script/script.rs index f6dd0ba7025..860187dd5d2 100644 --- a/src/components/script/script.rs +++ b/src/components/script/script.rs @@ -17,6 +17,7 @@ extern crate log; extern crate debug; +extern crate cssparser; extern crate collections; extern crate geom; extern crate hubbub; diff --git a/src/components/style/selector_matching.rs b/src/components/style/selector_matching.rs index 66a874ae798..061a8fc76b5 100644 --- a/src/components/style/selector_matching.rs +++ b/src/components/style/selector_matching.rs @@ -521,7 +521,7 @@ impl Ord for MatchedProperty { /// `shareable` to false unless you are willing to update the style sharing logic. Otherwise things /// will almost certainly break as nodes will start mistakenly sharing styles. (See the code in /// `main/css/matching.rs`.) -fn matches_compound_selector>( selector: &CompoundSelector, element: &N, diff --git a/src/components/style/style.rs b/src/components/style/style.rs index e667fa743b3..0368b71c1f6 100644 --- a/src/components/style/style.rs +++ b/src/components/style/style.rs @@ -33,7 +33,7 @@ extern crate servo_util = "util"; // Public API pub use stylesheets::{Stylesheet, CSSRule, StyleRule}; pub use selector_matching::{Stylist, StylesheetOrigin, UserAgentOrigin, AuthorOrigin, UserOrigin}; -pub use selector_matching::{MatchedProperty}; +pub use selector_matching::{MatchedProperty, matches_compound_selector}; pub use properties::{cascade, cascade_anonymous}; pub use properties::{PropertyDeclaration, ComputedValues, computed_values, style_structs}; pub use properties::{PropertyDeclarationBlock, parse_style_attribute}; // Style attributes @@ -43,6 +43,7 @@ pub use errors::with_errors_silenced; pub use node::{TElement, TNode}; pub use selectors::{PseudoElement, Before, After, AttrSelector, SpecificNamespace, AnyNamespace}; pub use selectors::{NamespaceConstraint, Selector, CompoundSelector, SimpleSelector, Combinator}; +pub use selectors::{parse_selector_list}; pub use namespaces::NamespaceMap; pub use media_queries::{MediaRule, MediaQueryList, MediaQuery, Device, MediaType, MediaQueryType};