diff options
Diffstat (limited to 'src/components/script/dom')
-rw-r--r-- | src/components/script/dom/document.rs | 53 | ||||
-rw-r--r-- | src/components/script/dom/element.rs | 3 | ||||
-rw-r--r-- | src/components/script/dom/node.rs | 16 |
3 files changed, 68 insertions, 4 deletions
diff --git a/src/components/script/dom/document.rs b/src/components/script/dom/document.rs index a8c417b986b..99c20d280c8 100644 --- a/src/components/script/dom/document.rs +++ b/src/components/script/dom/document.rs @@ -25,6 +25,8 @@ use js::jsapi::{JSTRACE_OBJECT, JSTracer, JS_CallTracer}; use js::glue::RUST_OBJECT_TO_JSVAL; use servo_util::tree::TreeNodeRef; +use std::hashmap::HashMap; + use std::cast; use std::ptr; use std::str::eq_slice; @@ -92,6 +94,9 @@ impl AbstractDocument { })); self.with_mut_base(|document| { document.root = Some(root); + // Register elements having "id" attribute to the owner doc. + document.register_nodes_with_id(&root); + document.content_changed(); }); } @@ -108,7 +113,8 @@ pub struct Document { reflector_: Reflector, window: Option<@mut Window>, doctype: DocumentType, - title: ~str + title: ~str, + idmap: HashMap<~str, AbstractNode<ScriptView>> } impl Document { @@ -119,7 +125,8 @@ impl Document { reflector_: Reflector::new(), window: window, doctype: doctype, - title: ~"" + title: ~"", + idmap: HashMap::new() } } @@ -265,8 +272,11 @@ impl Document { HTMLCollection::new(~[], cx, scope) } - pub fn GetElementById(&self, _id: &DOMString) -> Option<AbstractNode<ScriptView>> { - None + pub fn GetElementById(&self, id: &DOMString) -> Option<AbstractNode<ScriptView>> { + let key: &~str = &null_str_as_empty(id); + // TODO: "in tree order, within the context object's tree" + // http://dom.spec.whatwg.org/#dom-document-getelementbyid. + self.idmap.find_equiv(key).map(|node| **node) } pub fn CreateElement(&self, abstract_self: AbstractDocument, local_name: &DOMString) -> Fallible<AbstractNode<ScriptView>> { @@ -513,6 +523,41 @@ impl Document { window.wait_until_safe_to_modify_dom(); } } + + pub fn register_nodes_with_id(&mut self, root: &AbstractNode<ScriptView>) { + foreach_ided_elements(root, |id: &~str, abstract_node: &AbstractNode<ScriptView>| { + // TODO: "in tree order, within the context object's tree" + // http://dom.spec.whatwg.org/#dom-document-getelementbyid. + self.idmap.find_or_insert(id.clone(), *abstract_node); + }); + } + + pub fn unregister_nodes_with_id(&mut self, root: &AbstractNode<ScriptView>) { + foreach_ided_elements(root, |id: &~str, _| { + // TODO: "in tree order, within the context object's tree" + // http://dom.spec.whatwg.org/#dom-document-getelementbyid. + self.idmap.pop(id); + }); + } +} + +#[inline(always)] +fn foreach_ided_elements(root: &AbstractNode<ScriptView>, + callback: &fn(&~str, &AbstractNode<ScriptView>)) { + for node in root.traverse_preorder() { + if !node.is_element() { + loop; + } + + do node.with_imm_element |element| { + match element.get_attr("id") { + Some(id) => { + callback(&id.to_str(), &node); + } + None => () + } + } + } } impl Traceable for Document { diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs index 51d7c609c98..4c4238ca5d6 100644 --- a/src/components/script/dom/element.rs +++ b/src/components/script/dom/element.rs @@ -170,6 +170,9 @@ impl<'self> Element { null_str_as_empty_ref(raw_value))); } + // TODO: update owner document's id hashmap for `document.getElementById()` + // if `name` == "id". + //XXXjdm We really need something like a vtable so we can call AfterSetAttr. // This hardcoding is awful. match abstract_self.type_id() { diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index 293da68d0e4..b68f8ffff12 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -473,6 +473,16 @@ impl Node<ScriptView> { cur_node = cur_node.unwrap().next_sibling(); } + // Unregister elements having "id' from the old doc. + do old_doc.with_mut_base |old_doc| { + old_doc.unregister_nodes_with_id(&abstract_self); + } + + // Register elements having "id" attribute to the owner doc. + do doc.with_mut_base |doc| { + doc.register_nodes_with_id(&abstract_self); + } + // Signal the old document that it needs to update its display if old_doc != doc { do old_doc.with_base |old_doc| { @@ -779,6 +789,12 @@ impl Node<ScriptView> { self.wait_until_safe_to_modify_dom(); + // Unregister elements having "id' from the owner doc. + // This need be called before target nodes are removed from tree. + do self.owner_doc.with_mut_base |doc| { + doc.unregister_nodes_with_id(&abstract_self); + } + abstract_self.remove_child(node); // Signal the document that it needs to update its display. do self.owner_doc.with_base |document| { |