diff --git a/src/components/script/dom/attrlist.rs b/src/components/script/dom/attrlist.rs new file mode 100644 index 00000000000..48f74be69d5 --- /dev/null +++ b/src/components/script/dom/attrlist.rs @@ -0,0 +1,66 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use dom::attr::Attr; +use dom::bindings::codegen::AttrListBinding; +use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; +use dom::node::{AbstractNode, ScriptView}; +use dom::window::Window; + +pub struct AttrList { + reflector_: Reflector, + window: @mut Window, + owner: AbstractNode +} + +impl AttrList { + pub fn new_inherited(window: @mut Window, + elem: AbstractNode) -> AttrList { + AttrList { + reflector_: Reflector::new(), + window: window, + owner: elem + } + } + + pub fn new(window: @mut Window, elem: AbstractNode) -> @mut AttrList { + reflect_dom_object(@mut AttrList::new_inherited(window, elem), + window, AttrListBinding::Wrap) + } + + pub fn Length(&self) -> u32 { + self.owner.with_imm_element(|elem| elem.attrs_insert_order.len() as u32) + } + + pub fn Item(&self, index: u32) -> Option<@mut Attr> { + if index >= self.Length() { + None + } else { + do self.owner.with_imm_element |elem| { + let insert_order = &elem.attrs_insert_order[index]; + do elem.attrs.find_equiv(&insert_order.first()).and_then |attrs| { + attrs.iter() + .find(|attr| attr.namespace == insert_order.second()) + .map(|attr| *attr) + } + } + } + } + + pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<@mut Attr> { + let item = self.Item(index); + *found = item.is_some(); + item + } +} + +impl Reflectable for AttrList { + fn reflector<'a>(&'a self) -> &'a Reflector { + &self.reflector_ + } + + fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector { + &mut self.reflector_ + } +} diff --git a/src/components/script/dom/bindings/codegen/AttrList.webidl b/src/components/script/dom/bindings/codegen/AttrList.webidl new file mode 100644 index 00000000000..d37bb53a3b8 --- /dev/null +++ b/src/components/script/dom/bindings/codegen/AttrList.webidl @@ -0,0 +1,8 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +interface AttrList { + readonly attribute unsigned long length; + getter Attr? item(unsigned long index); +}; \ No newline at end of file diff --git a/src/components/script/dom/bindings/codegen/Bindings.conf b/src/components/script/dom/bindings/codegen/Bindings.conf index 2c75ed85b8b..4ced1397f02 100644 --- a/src/components/script/dom/bindings/codegen/Bindings.conf +++ b/src/components/script/dom/bindings/codegen/Bindings.conf @@ -72,6 +72,9 @@ DOMInterfaces = { 'AudioBuffer' : { }, +'AttrList': { +}, + 'mozAudioContext': { 'nativeType': 'AudioContext', 'implicitJSContext': [ 'createBuffer' ], @@ -181,7 +184,7 @@ DOMInterfaces = { 'Element': { 'nativeType': 'AbstractNode', 'pointerType': '', - 'needsAbstract': ['getClientRects', 'getBoundingClientRect', 'setAttribute', 'setAttributeNS', 'id'] + 'needsAbstract': ['getClientRects', 'getBoundingClientRect', 'setAttribute', 'setAttributeNS', 'id', 'attributes'] }, 'Event': { diff --git a/src/components/script/dom/bindings/codegen/Element.webidl b/src/components/script/dom/bindings/codegen/Element.webidl index 5f91f86bb72..840e654ce99 100644 --- a/src/components/script/dom/bindings/codegen/Element.webidl +++ b/src/components/script/dom/bindings/codegen/Element.webidl @@ -35,8 +35,8 @@ interface Element : Node { /*[Constant] readonly attribute DOMTokenList? classList;*/ - /*[Constant] - readonly attribute MozNamedAttrMap attributes;*/ + [Constant] + readonly attribute AttrList attributes; DOMString? getAttribute(DOMString name); DOMString? getAttributeNS(DOMString? namespace, DOMString localName); [Throws] diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs index 62a668bfdf3..50dbda3facb 100644 --- a/src/components/script/dom/element.rs +++ b/src/components/script/dom/element.rs @@ -4,6 +4,7 @@ //! Element nodes. +use dom::attrlist::AttrList; use dom::bindings::utils::{Reflectable, DOMString, ErrorResult, Fallible, Reflector}; use dom::bindings::utils::{null_str_as_empty, null_str_as_empty_ref, NamespaceError}; use dom::bindings::utils::{InvalidCharacter, QName, Name, InvalidXMLName, xml_name_type}; @@ -30,8 +31,9 @@ pub struct Element { node: Node, tag_name: ~str, // TODO: This should be an atom, not a ~str. attrs: HashMap<~str, ~[@mut Attr]>, - attrs_list: ~[~str], // store an order of attributes. + attrs_insert_order: ~[(~str, Namespace)], // store an order of attributes. style_attribute: Option, + attr_list: Option<@mut AttrList> } impl Reflectable for Element { @@ -149,7 +151,8 @@ impl<'self> Element { node: Node::new(ElementNodeTypeId(type_id), document), tag_name: tag_name, attrs: HashMap::new(), - attrs_list: ~[], + attrs_insert_order: ~[], + attr_list: None, style_attribute: None, } } @@ -217,7 +220,8 @@ impl<'self> Element { self.attrs.mangle(local_name.clone(), new_attr, |new_name: &~str, new_value: @mut Attr| { // register to the ordered list. - self.attrs_list.push(new_name.clone()); + let order_value = (new_name.clone(), new_value.namespace.clone()); + self.attrs_insert_order.push(order_value); ~[new_value] }, |name, old_value: &mut ~[@mut Attr], new_value: @mut Attr| { @@ -234,7 +238,8 @@ impl<'self> Element { } if !found { old_value.push(new_value); - self.attrs_list.push(name.clone()); + let order_value = (name.clone(), new_value.namespace.clone()); + self.attrs_insert_order.push(order_value); } }); @@ -295,6 +300,18 @@ impl Element { self.set_attribute(abstract_self, namespace::Null, &Some(~"id"), &Some(id.clone())); } + pub fn Attributes(&mut self, abstract_self: AbstractNode) -> @mut AttrList { + match self.attr_list { + None => { + let window = self.node.owner_doc().document().window; + let list = AttrList::new(window, abstract_self); + self.attr_list = Some(list); + list + } + Some(list) => list + } + } + pub fn GetAttribute(&self, name: &DOMString) -> Option { self.get_attr(*name).map(|s| s.to_owned()) } diff --git a/src/components/script/script.rc b/src/components/script/script.rc index a2617f0a9a3..8c24cc5a995 100644 --- a/src/components/script/script.rc +++ b/src/components/script/script.rc @@ -45,6 +45,7 @@ pub mod dom { } pub mod attr; + pub mod attrlist; pub mod blob; pub mod characterdata; pub mod clientrect;