Enable to update id attribute for Document.getElementById(). (#740)

This commit is contained in:
Tetsuharu OHZEKI 2013-11-12 23:04:05 +09:00
parent 072ff20140
commit aa72c413ed
3 changed files with 48 additions and 6 deletions

View file

@ -340,6 +340,28 @@ impl Document {
self.idmap.pop(id);
});
}
pub fn update_idmap(&mut self,
abstract_self: AbstractNode<ScriptView>,
new_id: DOMString,
old_id: Option<DOMString>) {
// remove old ids if the old ones are not same as the new one.
match old_id {
Some(ref old_id) if new_id != *old_id => {
self.idmap.remove(old_id);
}
_ => ()
}
// TODO: support the case if multiple elements which haves same id are in the same document.
self.idmap.mangle(new_id, abstract_self,
|_, new_node: AbstractNode<ScriptView>| -> AbstractNode<ScriptView> {
new_node
},
|_, old_node: &mut AbstractNode<ScriptView>, new_node: AbstractNode<ScriptView>| {
*old_node = new_node;
});
}
}
#[inline(always)]

View file

@ -216,6 +216,7 @@ impl<'self> Element {
let win = self.node.owner_doc().document().window;
let new_attr = Attr::new_ns(win, local_name.clone(), value.clone(),
name.clone(), namespace.clone(), prefix);
let mut old_raw_value: Option<DOMString> = None;
self.attrs.mangle(local_name.clone(), new_attr,
|new_name: &~str, new_value: @mut Attr| {
// register to the ordered list.
@ -229,6 +230,7 @@ impl<'self> Element {
for attr in old_value.mut_iter() {
if eq_slice(attr.local_name, *name) &&
attr.namespace == new_value.namespace {
old_raw_value = Some(attr.Value());
*attr = new_value;
found = true;
break;
@ -242,7 +244,7 @@ impl<'self> Element {
}
});
self.after_set_attr(abstract_self, &namespace, local_name, value);
self.after_set_attr(abstract_self, &namespace, local_name, value, old_raw_value);
Ok(())
}
@ -250,18 +252,21 @@ impl<'self> Element {
abstract_self: AbstractNode<ScriptView>,
namespace: &Namespace,
local_name: DOMString,
value: DOMString) {
value: DOMString,
old_value: Option<DOMString>) {
match local_name.as_slice() {
"style" if *namespace == namespace::Null => {
self.style_attribute = Some(style::parse_style_attribute(value))
}
"id" => {
let doc = self.node.owner_doc();
let doc = doc.mut_document();
doc.update_idmap(abstract_self, value.clone(), old_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() {

View file

@ -43,8 +43,23 @@
is(removed, null, "test2-3, removed element");
}
// TODO:
// test3: update `id` attribute
{
// setup fixtures.
let TEST_ID = "test3";
let test = document.createElement("div");
test.setAttribute("id", TEST_ID);
gBody.appendChild(test);
// update id
let UPDATED_ID = "test3-updated";
test.setAttribute("id", UPDATED_ID);
let e = document.getElementById(UPDATED_ID);
is(e, test, "test3-0, update 'id' attribute.");
let old = document.getElementById(TEST_ID);
is(old, null, "test3-1, the method shouldn't get the element by the old id.");
}
// TODO:
// test4: "in tree order, within the context object's tree"