mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
auto merge of #4363 : Ms2ger/servo/collectionfilter, r=Manishearth
This commit is contained in:
commit
29c9975a83
2 changed files with 28 additions and 42 deletions
|
@ -10,12 +10,13 @@ use dom::bindings::js::{JS, JSRef, Temporary};
|
||||||
use dom::bindings::trace::JSTraceable;
|
use dom::bindings::trace::JSTraceable;
|
||||||
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
|
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
|
||||||
use dom::element::{Element, AttributeHandlers, ElementHelpers};
|
use dom::element::{Element, AttributeHandlers, ElementHelpers};
|
||||||
use dom::node::{Node, NodeHelpers};
|
use dom::node::{Node, NodeHelpers, TreeIterator};
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
use servo_util::namespace;
|
use servo_util::namespace;
|
||||||
use servo_util::str::{DOMString, split_html_space_chars};
|
use servo_util::str::{DOMString, split_html_space_chars};
|
||||||
|
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
|
use std::iter::{FilterMap, Skip};
|
||||||
use string_cache::{Atom, Namespace};
|
use string_cache::{Atom, Namespace};
|
||||||
|
|
||||||
pub trait CollectionFilter : JSTraceable {
|
pub trait CollectionFilter : JSTraceable {
|
||||||
|
@ -62,10 +63,7 @@ impl HTMLCollection {
|
||||||
namespace_filter: Option<Namespace>
|
namespace_filter: Option<Namespace>
|
||||||
}
|
}
|
||||||
impl CollectionFilter for AllElementFilter {
|
impl CollectionFilter for AllElementFilter {
|
||||||
fn filter(&self, elem: JSRef<Element>, root: JSRef<Node>) -> bool {
|
fn filter(&self, elem: JSRef<Element>, _root: JSRef<Node>) -> bool {
|
||||||
if NodeCast::from_ref(elem) == root {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
match self.namespace_filter {
|
match self.namespace_filter {
|
||||||
None => true,
|
None => true,
|
||||||
Some(ref namespace) => *elem.namespace() == *namespace
|
Some(ref namespace) => *elem.namespace() == *namespace
|
||||||
|
@ -88,10 +86,7 @@ impl HTMLCollection {
|
||||||
ascii_lower_tag: Atom,
|
ascii_lower_tag: Atom,
|
||||||
}
|
}
|
||||||
impl CollectionFilter for TagNameFilter {
|
impl CollectionFilter for TagNameFilter {
|
||||||
fn filter(&self, elem: JSRef<Element>, root: JSRef<Node>) -> bool {
|
fn filter(&self, elem: JSRef<Element>, _root: JSRef<Node>) -> bool {
|
||||||
if NodeCast::from_ref(elem) == root {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if elem.html_element_in_html_document() {
|
if elem.html_element_in_html_document() {
|
||||||
*elem.local_name() == self.ascii_lower_tag
|
*elem.local_name() == self.ascii_lower_tag
|
||||||
} else {
|
} else {
|
||||||
|
@ -122,10 +117,7 @@ impl HTMLCollection {
|
||||||
namespace_filter: Option<Namespace>
|
namespace_filter: Option<Namespace>
|
||||||
}
|
}
|
||||||
impl CollectionFilter for TagNameNSFilter {
|
impl CollectionFilter for TagNameNSFilter {
|
||||||
fn filter(&self, elem: JSRef<Element>, root: JSRef<Node>) -> bool {
|
fn filter(&self, elem: JSRef<Element>, _root: JSRef<Node>) -> bool {
|
||||||
if NodeCast::from_ref(elem) == root {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
let ns_match = match self.namespace_filter {
|
let ns_match = match self.namespace_filter {
|
||||||
Some(ref namespace) => {
|
Some(ref namespace) => {
|
||||||
*elem.namespace() == *namespace
|
*elem.namespace() == *namespace
|
||||||
|
@ -149,8 +141,8 @@ impl HTMLCollection {
|
||||||
classes: Vec<Atom>
|
classes: Vec<Atom>
|
||||||
}
|
}
|
||||||
impl CollectionFilter for ClassNameFilter {
|
impl CollectionFilter for ClassNameFilter {
|
||||||
fn filter(&self, elem: JSRef<Element>, root: JSRef<Node>) -> bool {
|
fn filter(&self, elem: JSRef<Element>, _root: JSRef<Node>) -> bool {
|
||||||
(NodeCast::from_ref(elem) != root) && self.classes.iter().all(|class| elem.has_class(class))
|
self.classes.iter().all(|class| elem.has_class(class))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let filter = ClassNameFilter {
|
let filter = ClassNameFilter {
|
||||||
|
@ -171,6 +163,15 @@ impl HTMLCollection {
|
||||||
}
|
}
|
||||||
HTMLCollection::create(window, root, box ElementChildFilter)
|
HTMLCollection::create(window, root, box ElementChildFilter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn traverse<'a>(root: JSRef<'a, Node>)
|
||||||
|
-> FilterMap<'a, JSRef<'a, Node>,
|
||||||
|
JSRef<'a, Element>,
|
||||||
|
Skip<TreeIterator<'a>>> {
|
||||||
|
root.traverse_preorder()
|
||||||
|
.skip(1)
|
||||||
|
.filter_map(ElementCast::to_ref)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> HTMLCollectionMethods for JSRef<'a, HTMLCollection> {
|
impl<'a> HTMLCollectionMethods for JSRef<'a, HTMLCollection> {
|
||||||
|
@ -180,11 +181,9 @@ impl<'a> HTMLCollectionMethods for JSRef<'a, HTMLCollection> {
|
||||||
Static(ref elems) => elems.len() as u32,
|
Static(ref elems) => elems.len() as u32,
|
||||||
Live(ref root, ref filter) => {
|
Live(ref root, ref filter) => {
|
||||||
let root = root.root();
|
let root = root.root();
|
||||||
root.traverse_preorder()
|
HTMLCollection::traverse(*root)
|
||||||
.filter(|&child| {
|
.filter(|element| filter.filter(*element, *root))
|
||||||
let elem: Option<JSRef<Element>> = ElementCast::to_ref(child);
|
.count() as u32
|
||||||
elem.map_or(false, |elem| filter.filter(elem, *root))
|
|
||||||
}).count() as u32
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,17 +197,11 @@ impl<'a> HTMLCollectionMethods for JSRef<'a, HTMLCollection> {
|
||||||
.map(|elem| Temporary::new(elem.clone())),
|
.map(|elem| Temporary::new(elem.clone())),
|
||||||
Live(ref root, ref filter) => {
|
Live(ref root, ref filter) => {
|
||||||
let root = root.root();
|
let root = root.root();
|
||||||
root.traverse_preorder()
|
HTMLCollection::traverse(*root)
|
||||||
.filter_map(|node| {
|
.filter(|element| filter.filter(*element, *root))
|
||||||
let elem: Option<JSRef<Element>> = ElementCast::to_ref(node);
|
|
||||||
match elem {
|
|
||||||
Some(ref elem) if filter.filter(*elem, *root) => Some(elem.clone()),
|
|
||||||
_ => None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.nth(index as uint)
|
.nth(index as uint)
|
||||||
.clone()
|
.clone()
|
||||||
.map(|elem| Temporary::from_rooted(elem))
|
.map(Temporary::from_rooted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -230,18 +223,12 @@ impl<'a> HTMLCollectionMethods for JSRef<'a, HTMLCollection> {
|
||||||
.map(|maybe_elem| Temporary::from_rooted(*maybe_elem)),
|
.map(|maybe_elem| Temporary::from_rooted(*maybe_elem)),
|
||||||
Live(ref root, ref filter) => {
|
Live(ref root, ref filter) => {
|
||||||
let root = root.root();
|
let root = root.root();
|
||||||
root.traverse_preorder()
|
HTMLCollection::traverse(*root)
|
||||||
.filter_map(|node| {
|
.filter(|element| filter.filter(*element, *root))
|
||||||
let elem: Option<JSRef<Element>> = ElementCast::to_ref(node);
|
|
||||||
match elem {
|
|
||||||
Some(ref elem) if filter.filter(*elem, *root) => Some(elem.clone()),
|
|
||||||
_ => None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.find(|elem| {
|
.find(|elem| {
|
||||||
elem.get_string_attribute(&atom!("name")) == key ||
|
elem.get_string_attribute(&atom!("name")) == key ||
|
||||||
elem.get_string_attribute(&atom!("id")) == key })
|
elem.get_string_attribute(&atom!("id")) == key })
|
||||||
.map(|maybe_elem| Temporary::from_rooted(maybe_elem))
|
.map(Temporary::from_rooted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use dom::attr::Attr;
|
||||||
use dom::attr::AttrHelpers;
|
use dom::attr::AttrHelpers;
|
||||||
use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding;
|
use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding;
|
||||||
use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding::HTMLFieldSetElementMethods;
|
use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding::HTMLFieldSetElementMethods;
|
||||||
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLFieldSetElementDerived, NodeCast};
|
use dom::bindings::codegen::InheritTypes::{HTMLFieldSetElementDerived, NodeCast};
|
||||||
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLLegendElementDerived};
|
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLLegendElementDerived};
|
||||||
use dom::bindings::js::{JSRef, Temporary};
|
use dom::bindings::js::{JSRef, Temporary};
|
||||||
use dom::bindings::utils::{Reflectable, Reflector};
|
use dom::bindings::utils::{Reflectable, Reflector};
|
||||||
|
@ -54,11 +54,10 @@ impl<'a> HTMLFieldSetElementMethods for JSRef<'a, HTMLFieldSetElement> {
|
||||||
#[jstraceable]
|
#[jstraceable]
|
||||||
struct ElementsFilter;
|
struct ElementsFilter;
|
||||||
impl CollectionFilter for ElementsFilter {
|
impl CollectionFilter for ElementsFilter {
|
||||||
fn filter<'a>(&self, elem: JSRef<'a, Element>, root: JSRef<'a, Node>) -> bool {
|
fn filter<'a>(&self, elem: JSRef<'a, Element>, _root: JSRef<'a, Node>) -> bool {
|
||||||
static TAG_NAMES: StaticStringVec = &["button", "fieldset", "input",
|
static TAG_NAMES: StaticStringVec = &["button", "fieldset", "input",
|
||||||
"keygen", "object", "output", "select", "textarea"];
|
"keygen", "object", "output", "select", "textarea"];
|
||||||
let root: JSRef<Element> = ElementCast::to_ref(root).unwrap();
|
TAG_NAMES.iter().any(|&tag_name| tag_name == elem.local_name().as_slice())
|
||||||
elem != root && TAG_NAMES.iter().any(|&tag_name| tag_name == elem.local_name().as_slice())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let node: JSRef<Node> = NodeCast::from_ref(self);
|
let node: JSRef<Node> = NodeCast::from_ref(self);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue