diff options
author | Jack Moffitt <jack@metajack.im> | 2014-08-28 09:34:23 -0600 |
---|---|---|
committer | Jack Moffitt <jack@metajack.im> | 2014-09-08 20:21:42 -0600 |
commit | c6ab60dbfc6da7b4f800c9e40893c8b58413960c (patch) | |
tree | d1d74076cf7fa20e4f77ec7cb82cae98b67362cb /src/components/script/dom/element.rs | |
parent | db2f642c32fc5bed445bb6f2e45b0f6f0b4342cf (diff) | |
download | servo-c6ab60dbfc6da7b4f800c9e40893c8b58413960c.tar.gz servo-c6ab60dbfc6da7b4f800c9e40893c8b58413960c.zip |
Cargoify servo
Diffstat (limited to 'src/components/script/dom/element.rs')
-rw-r--r-- | src/components/script/dom/element.rs | 958 |
1 files changed, 0 insertions, 958 deletions
diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs deleted file mode 100644 index 1fe2c9f80bd..00000000000 --- a/src/components/script/dom/element.rs +++ /dev/null @@ -1,958 +0,0 @@ -/* 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/. */ - -//! Element nodes. - -use dom::attr::{Attr, ReplacedAttr, FirstSetAttr, AttrHelpersForLayout}; -use dom::attr::{AttrValue, StringAttrValue, UIntAttrValue, AtomAttrValue}; -use dom::namednodemap::NamedNodeMap; -use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods; -use dom::bindings::codegen::Bindings::ElementBinding; -use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods; -use dom::bindings::codegen::InheritTypes::{ElementDerived, NodeCast}; -use dom::bindings::js::{JS, JSRef, Temporary, TemporaryPushable}; -use dom::bindings::js::{OptionalSettable, OptionalRootable, Root}; -use dom::bindings::trace::Traceable; -use dom::bindings::utils::{Reflectable, Reflector}; -use dom::bindings::error::{ErrorResult, Fallible, NamespaceError, InvalidCharacter, Syntax}; -use dom::bindings::utils::{QName, Name, InvalidXMLName, xml_name_type}; -use dom::domrect::DOMRect; -use dom::domrectlist::DOMRectList; -use dom::document::{Document, DocumentHelpers}; -use dom::domtokenlist::DOMTokenList; -use dom::eventtarget::{EventTarget, NodeTargetTypeId}; -use dom::htmlcollection::HTMLCollection; -use dom::htmlserializer::serialize; -use dom::node::{ElementNodeTypeId, Node, NodeHelpers, NodeIterator, document_from_node}; -use dom::node::{window_from_node, LayoutNodeHelpers}; -use dom::nodelist::NodeList; -use dom::virtualmethods::{VirtualMethods, vtable_for}; -use layout_interface::ContentChangedDocumentDamage; -use layout_interface::MatchSelectorsDocumentDamage; -use style::{matches, parse_selector_list_from_str}; -use style; -use servo_util::atom::Atom; -use servo_util::namespace; -use servo_util::namespace::{Namespace, Null}; -use servo_util::str::{DOMString, null_str_as_empty_ref}; - -use std::ascii::StrAsciiExt; -use std::cell::{Cell, RefCell}; -use std::mem; - -#[deriving(Encodable)] -pub struct Element { - pub node: Node, - pub local_name: Atom, - pub namespace: Namespace, - pub prefix: Option<DOMString>, - pub attrs: RefCell<Vec<JS<Attr>>>, - pub style_attribute: Traceable<RefCell<Option<style::PropertyDeclarationBlock>>>, - pub attr_list: Cell<Option<JS<NamedNodeMap>>>, - class_list: Cell<Option<JS<DOMTokenList>>>, -} - -impl ElementDerived for EventTarget { - fn is_element(&self) -> bool { - match self.type_id { - NodeTargetTypeId(ElementNodeTypeId(_)) => true, - _ => false - } - } -} - -impl Reflectable for Element { - fn reflector<'a>(&'a self) -> &'a Reflector { - self.node.reflector() - } -} - -#[deriving(PartialEq,Encodable)] -pub enum ElementTypeId { - HTMLElementTypeId, - HTMLAnchorElementTypeId, - HTMLAppletElementTypeId, - HTMLAreaElementTypeId, - HTMLAudioElementTypeId, - HTMLBaseElementTypeId, - HTMLBRElementTypeId, - HTMLBodyElementTypeId, - HTMLButtonElementTypeId, - HTMLCanvasElementTypeId, - HTMLDataElementTypeId, - HTMLDataListElementTypeId, - HTMLDirectoryElementTypeId, - HTMLDListElementTypeId, - HTMLDivElementTypeId, - HTMLEmbedElementTypeId, - HTMLFieldSetElementTypeId, - HTMLFontElementTypeId, - HTMLFormElementTypeId, - HTMLFrameElementTypeId, - HTMLFrameSetElementTypeId, - HTMLHRElementTypeId, - HTMLHeadElementTypeId, - HTMLHeadingElementTypeId, - HTMLHtmlElementTypeId, - HTMLIFrameElementTypeId, - HTMLImageElementTypeId, - HTMLInputElementTypeId, - HTMLLabelElementTypeId, - HTMLLegendElementTypeId, - HTMLLinkElementTypeId, - HTMLLIElementTypeId, - HTMLMapElementTypeId, - HTMLMediaElementTypeId, - HTMLMetaElementTypeId, - HTMLMeterElementTypeId, - HTMLModElementTypeId, - HTMLObjectElementTypeId, - HTMLOListElementTypeId, - HTMLOptGroupElementTypeId, - HTMLOptionElementTypeId, - HTMLOutputElementTypeId, - HTMLParagraphElementTypeId, - HTMLParamElementTypeId, - HTMLPreElementTypeId, - HTMLProgressElementTypeId, - HTMLQuoteElementTypeId, - HTMLScriptElementTypeId, - HTMLSelectElementTypeId, - HTMLSourceElementTypeId, - HTMLSpanElementTypeId, - HTMLStyleElementTypeId, - HTMLTableElementTypeId, - HTMLTableCaptionElementTypeId, - HTMLTableDataCellElementTypeId, - HTMLTableHeaderCellElementTypeId, - HTMLTableColElementTypeId, - HTMLTableRowElementTypeId, - HTMLTableSectionElementTypeId, - HTMLTemplateElementTypeId, - HTMLTextAreaElementTypeId, - HTMLTimeElementTypeId, - HTMLTitleElementTypeId, - HTMLTrackElementTypeId, - HTMLUListElementTypeId, - HTMLVideoElementTypeId, - HTMLUnknownElementTypeId, - - ElementTypeId, -} - -// -// Element methods -// - -impl Element { - pub fn new_inherited(type_id: ElementTypeId, local_name: DOMString, namespace: Namespace, prefix: Option<DOMString>, document: &JSRef<Document>) -> Element { - Element { - node: Node::new_inherited(ElementNodeTypeId(type_id), document), - local_name: Atom::from_slice(local_name.as_slice()), - namespace: namespace, - prefix: prefix, - attrs: RefCell::new(vec!()), - attr_list: Cell::new(None), - class_list: Cell::new(None), - style_attribute: Traceable::new(RefCell::new(None)), - } - } - - pub fn new(local_name: DOMString, namespace: Namespace, prefix: Option<DOMString>, document: &JSRef<Document>) -> Temporary<Element> { - let element = Element::new_inherited(ElementTypeId, local_name, namespace, prefix, document); - Node::reflect_node(box element, document, ElementBinding::Wrap) - } -} - -pub trait RawLayoutElementHelpers { - unsafe fn get_attr_val_for_layout(&self, namespace: &Namespace, name: &str) -> Option<&'static str>; - unsafe fn get_attr_atom_for_layout(&self, namespace: &Namespace, name: &str) -> Option<Atom>; -} - -impl RawLayoutElementHelpers for Element { - #[inline] - unsafe fn get_attr_val_for_layout(&self, namespace: &Namespace, name: &str) - -> Option<&'static str> { - // cast to point to T in RefCell<T> directly - let attrs: *const Vec<JS<Attr>> = mem::transmute(&self.attrs); - (*attrs).iter().find(|attr: & &JS<Attr>| { - let attr = attr.unsafe_get(); - name == (*attr).local_name().as_slice() && - (*attr).namespace == *namespace - }).map(|attr| { - let attr = attr.unsafe_get(); - (*attr).value_ref_forever() - }) - } - - #[inline] - unsafe fn get_attr_atom_for_layout(&self, namespace: &Namespace, name: &str) - -> Option<Atom> { - // cast to point to T in RefCell<T> directly - let attrs: *const Vec<JS<Attr>> = mem::transmute(&self.attrs); - (*attrs).iter().find(|attr: & &JS<Attr>| { - let attr = attr.unsafe_get(); - name == (*attr).local_name().as_slice() && - (*attr).namespace == *namespace - }).and_then(|attr| { - let attr = attr.unsafe_get(); - (*attr).value_atom_forever() - }) - } -} - -pub trait LayoutElementHelpers { - unsafe fn html_element_in_html_document_for_layout(&self) -> bool; -} - -impl LayoutElementHelpers for JS<Element> { - unsafe fn html_element_in_html_document_for_layout(&self) -> bool { - if (*self.unsafe_get()).namespace != namespace::HTML { - return false - } - let node: JS<Node> = self.transmute_copy(); - let owner_doc = node.owner_doc_for_layout().unsafe_get(); - (*owner_doc).is_html_document - } -} - -pub trait ElementHelpers { - fn html_element_in_html_document(&self) -> bool; - fn get_local_name<'a>(&'a self) -> &'a Atom; - fn get_namespace<'a>(&'a self) -> &'a Namespace; -} - -impl<'a> ElementHelpers for JSRef<'a, Element> { - fn html_element_in_html_document(&self) -> bool { - let node: &JSRef<Node> = NodeCast::from_ref(self); - self.namespace == namespace::HTML && node.is_in_html_doc() - } - - fn get_local_name<'a>(&'a self) -> &'a Atom { - &self.deref().local_name - } - - fn get_namespace<'a>(&'a self) -> &'a Namespace { - &self.deref().namespace - } -} - -pub trait AttributeHandlers { - fn get_attribute(&self, namespace: Namespace, name: &str) -> Option<Temporary<Attr>>; - fn set_attribute_from_parser(&self, local_name: Atom, - value: DOMString, namespace: Namespace, - prefix: Option<DOMString>); - fn set_attribute(&self, name: &str, value: AttrValue); - fn do_set_attribute(&self, local_name: Atom, value: AttrValue, - name: Atom, namespace: Namespace, - prefix: Option<DOMString>, cb: |&JSRef<Attr>| -> bool); - fn parse_attribute(&self, namespace: &Namespace, local_name: &Atom, - value: DOMString) -> AttrValue; - - fn remove_attribute(&self, namespace: Namespace, name: &str); - fn notify_attribute_changed(&self, local_name: &Atom); - fn has_class(&self, name: &str) -> bool; - - fn set_atomic_attribute(&self, name: &str, value: DOMString); - - // http://www.whatwg.org/html/#reflecting-content-attributes-in-idl-attributes - fn has_attribute(&self, name: &str) -> bool; - fn set_bool_attribute(&self, name: &str, value: bool); - fn get_url_attribute(&self, name: &str) -> DOMString; - fn set_url_attribute(&self, name: &str, value: DOMString); - fn get_string_attribute(&self, name: &str) -> DOMString; - fn set_string_attribute(&self, name: &str, value: DOMString); - fn set_tokenlist_attribute(&self, name: &str, value: DOMString); - fn get_uint_attribute(&self, name: &str) -> u32; - fn set_uint_attribute(&self, name: &str, value: u32); -} - -impl<'a> AttributeHandlers for JSRef<'a, Element> { - fn get_attribute(&self, namespace: Namespace, name: &str) -> Option<Temporary<Attr>> { - let element: &Element = self.deref(); - let local_name = match self.html_element_in_html_document() { - true => Atom::from_slice(name.to_ascii_lower().as_slice()), - false => Atom::from_slice(name) - }; - element.attrs.borrow().iter().map(|attr| attr.root()).find(|attr| { - *attr.local_name() == local_name && attr.namespace == namespace - }).map(|x| Temporary::from_rooted(&*x)) - } - - fn set_attribute_from_parser(&self, local_name: Atom, - value: DOMString, namespace: Namespace, - prefix: Option<DOMString>) { - let name = match prefix { - None => local_name.clone(), - Some(ref prefix) => { - let name = format!("{:s}:{:s}", *prefix, local_name.as_slice()); - Atom::from_slice(name.as_slice()) - }, - }; - let value = self.parse_attribute(&namespace, &local_name, value); - self.do_set_attribute(local_name, value, name, namespace, prefix, |_| false) - } - - fn set_attribute(&self, name: &str, value: AttrValue) { - assert!(name == name.to_ascii_lower().as_slice()); - assert!(!name.contains(":")); - - let node: &JSRef<Node> = NodeCast::from_ref(self); - node.wait_until_safe_to_modify_dom(); - - let name = Atom::from_slice(name); - self.do_set_attribute(name.clone(), value, name.clone(), - namespace::Null, None, |attr| *attr.local_name() == name); - } - - fn do_set_attribute(&self, local_name: Atom, value: AttrValue, - name: Atom, namespace: Namespace, - prefix: Option<DOMString>, cb: |&JSRef<Attr>| -> bool) { - let idx = self.deref().attrs.borrow().iter() - .map(|attr| attr.root()) - .position(|attr| cb(&*attr)); - let (idx, set_type) = match idx { - Some(idx) => (idx, ReplacedAttr), - None => { - let window = window_from_node(self).root(); - let attr = Attr::new(&*window, local_name, value.clone(), - name, namespace.clone(), prefix, self); - self.deref().attrs.borrow_mut().push_unrooted(&attr); - (self.deref().attrs.borrow().len() - 1, FirstSetAttr) - } - }; - - (*self.deref().attrs.borrow())[idx].root().set_value(set_type, value); - } - - fn parse_attribute(&self, namespace: &Namespace, local_name: &Atom, - value: DOMString) -> AttrValue { - if *namespace == namespace::Null { - vtable_for(NodeCast::from_ref(self)) - .parse_plain_attribute(local_name.as_slice(), value) - } else { - StringAttrValue(value) - } - } - - fn remove_attribute(&self, namespace: Namespace, name: &str) { - let (_, local_name) = get_attribute_parts(name); - let local_name = Atom::from_slice(local_name); - - let idx = self.deref().attrs.borrow().iter().map(|attr| attr.root()).position(|attr| { - *attr.local_name() == local_name - }); - - match idx { - None => (), - Some(idx) => { - { - let node: &JSRef<Node> = NodeCast::from_ref(self); - node.wait_until_safe_to_modify_dom(); - } - - if namespace == namespace::Null { - let removed_raw_value = (*self.deref().attrs.borrow())[idx].root().Value(); - vtable_for(NodeCast::from_ref(self)) - .before_remove_attr(&local_name, - removed_raw_value); - } - - self.deref().attrs.borrow_mut().remove(idx); - } - }; - } - - fn notify_attribute_changed(&self, local_name: &Atom) { - let node: &JSRef<Node> = NodeCast::from_ref(self); - if node.is_in_doc() { - let damage = match local_name.as_slice() { - "style" | "id" | "class" => MatchSelectorsDocumentDamage, - _ => ContentChangedDocumentDamage - }; - let document = node.owner_doc().root(); - document.deref().damage_and_reflow(damage); - } - } - - fn has_class(&self, name: &str) -> bool { - self.get_attribute(Null, "class").root().map(|attr| { - attr.deref().value().tokens().map(|mut tokens| { - tokens.any(|atom| atom.as_slice() == name) - }).unwrap_or(false) - }).unwrap_or(false) - } - - fn set_atomic_attribute(&self, name: &str, value: DOMString) { - assert!(name == name.to_ascii_lower().as_slice()); - let value = AttrValue::from_atomic(value); - self.set_attribute(name, value); - } - - fn has_attribute(&self, name: &str) -> bool { - let name = match self.html_element_in_html_document() { - true => Atom::from_slice(name.to_ascii_lower().as_slice()), - false => Atom::from_slice(name) - }; - self.deref().attrs.borrow().iter().map(|attr| attr.root()).any(|attr| { - *attr.local_name() == name && attr.namespace == Null - }) - } - - fn set_bool_attribute(&self, name: &str, value: bool) { - if self.has_attribute(name) == value { return; } - if value { - self.set_string_attribute(name, String::new()); - } else { - self.remove_attribute(Null, name); - } - } - - fn get_url_attribute(&self, name: &str) -> DOMString { - // XXX Resolve URL. - self.get_string_attribute(name) - } - fn set_url_attribute(&self, name: &str, value: DOMString) { - self.set_string_attribute(name, value); - } - - fn get_string_attribute(&self, name: &str) -> DOMString { - match self.get_attribute(Null, name) { - Some(x) => { - let x = x.root(); - x.deref().Value() - } - None => "".to_string() - } - } - fn set_string_attribute(&self, name: &str, value: DOMString) { - assert!(name == name.to_ascii_lower().as_slice()); - self.set_attribute(name, StringAttrValue(value)); - } - - fn set_tokenlist_attribute(&self, name: &str, value: DOMString) { - assert!(name == name.to_ascii_lower().as_slice()); - self.set_attribute(name, AttrValue::from_tokenlist(value)); - } - - fn get_uint_attribute(&self, name: &str) -> u32 { - assert!(name == name.to_ascii_lower().as_slice()); - let attribute = self.get_attribute(Null, name).root(); - match attribute { - Some(attribute) => { - match *attribute.deref().value() { - UIntAttrValue(_, value) => value, - _ => fail!("Expected a UIntAttrValue"), - } - } - None => 0, - } - } - fn set_uint_attribute(&self, name: &str, value: u32) { - assert!(name == name.to_ascii_lower().as_slice()); - self.set_attribute(name, UIntAttrValue(value.to_string(), value)); - } -} - -impl Element { - pub fn is_void(&self) -> bool { - if self.namespace != namespace::HTML { - return false - } - match self.local_name.as_slice() { - /* List of void elements from - http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#html-fragment-serialization-algorithm */ - "area" | "base" | "basefont" | "bgsound" | "br" | "col" | "embed" | - "frame" | "hr" | "img" | "input" | "keygen" | "link" | "menuitem" | - "meta" | "param" | "source" | "track" | "wbr" => true, - _ => false - } - } -} - -impl<'a> ElementMethods for JSRef<'a, Element> { - // http://dom.spec.whatwg.org/#dom-element-namespaceuri - fn GetNamespaceURI(&self) -> Option<DOMString> { - match self.namespace { - Null => None, - ref ns => Some(ns.to_str().to_string()) - } - } - - fn LocalName(&self) -> DOMString { - self.local_name.as_slice().to_string() - } - - // http://dom.spec.whatwg.org/#dom-element-prefix - fn GetPrefix(&self) -> Option<DOMString> { - self.prefix.clone() - } - - // http://dom.spec.whatwg.org/#dom-element-tagname - fn TagName(&self) -> DOMString { - let qualified_name = match self.prefix { - Some(ref prefix) => format!("{}:{}", prefix, self.local_name).into_maybe_owned(), - None => self.local_name.as_slice().into_maybe_owned() - }; - if self.html_element_in_html_document() { - qualified_name.as_slice().to_ascii_upper() - } else { - qualified_name.into_string() - } - } - - // http://dom.spec.whatwg.org/#dom-element-id - fn Id(&self) -> DOMString { - self.get_string_attribute("id") - } - - // http://dom.spec.whatwg.org/#dom-element-id - fn SetId(&self, id: DOMString) { - self.set_atomic_attribute("id", id); - } - - // http://dom.spec.whatwg.org/#dom-element-classname - fn ClassName(&self) -> DOMString { - self.get_string_attribute("class") - } - - // http://dom.spec.whatwg.org/#dom-element-classname - fn SetClassName(&self, class: DOMString) { - self.set_tokenlist_attribute("class", class); - } - - // http://dom.spec.whatwg.org/#dom-element-classlist - fn ClassList(&self) -> Temporary<DOMTokenList> { - match self.class_list.get() { - Some(class_list) => Temporary::new(class_list), - None => { - let class_list = DOMTokenList::new(self, "class").root(); - self.class_list.assign(Some(class_list.deref().clone())); - Temporary::from_rooted(&*class_list) - } - } - } - - // http://dom.spec.whatwg.org/#dom-element-attributes - fn Attributes(&self) -> Temporary<NamedNodeMap> { - match self.attr_list.get() { - None => (), - Some(ref list) => return Temporary::new(list.clone()), - } - - let doc = { - let node: &JSRef<Node> = NodeCast::from_ref(self); - node.owner_doc().root() - }; - let window = doc.deref().window.root(); - let list = NamedNodeMap::new(&*window, self); - self.attr_list.assign(Some(list)); - Temporary::new(self.attr_list.get().get_ref().clone()) - } - - // http://dom.spec.whatwg.org/#dom-element-getattribute - fn GetAttribute(&self, name: DOMString) -> Option<DOMString> { - let name = if self.html_element_in_html_document() { - name.as_slice().to_ascii_lower() - } else { - name - }; - self.get_attribute(Null, name.as_slice()).root() - .map(|s| s.deref().Value()) - } - - // http://dom.spec.whatwg.org/#dom-element-getattributens - fn GetAttributeNS(&self, - namespace: Option<DOMString>, - local_name: DOMString) -> Option<DOMString> { - let namespace = Namespace::from_str(null_str_as_empty_ref(&namespace)); - self.get_attribute(namespace, local_name.as_slice()).root() - .map(|attr| attr.deref().Value()) - } - - // http://dom.spec.whatwg.org/#dom-element-setattribute - fn SetAttribute(&self, - name: DOMString, - value: DOMString) -> ErrorResult { - { - let node: &JSRef<Node> = NodeCast::from_ref(self); - node.wait_until_safe_to_modify_dom(); - } - - // Step 1. - match xml_name_type(name.as_slice()) { - InvalidXMLName => return Err(InvalidCharacter), - _ => {} - } - - // Step 2. - let name = if self.html_element_in_html_document() { - name.as_slice().to_ascii_lower() - } else { - name - }; - - // Step 3-5. - let name = Atom::from_slice(name.as_slice()); - let value = self.parse_attribute(&namespace::Null, &name, value); - self.do_set_attribute(name.clone(), value, name.clone(), namespace::Null, None, |attr| { - attr.deref().name.as_slice() == name.as_slice() - }); - Ok(()) - } - - // http://dom.spec.whatwg.org/#dom-element-setattributens - fn SetAttributeNS(&self, - namespace_url: Option<DOMString>, - name: DOMString, - value: DOMString) -> ErrorResult { - { - let node: &JSRef<Node> = NodeCast::from_ref(self); - node.wait_until_safe_to_modify_dom(); - } - - // Step 1. - let namespace = Namespace::from_str(null_str_as_empty_ref(&namespace_url)); - - let name_type = xml_name_type(name.as_slice()); - match name_type { - // Step 2. - InvalidXMLName => return Err(InvalidCharacter), - // Step 3. - Name => return Err(NamespaceError), - QName => {} - } - - // Step 4. - let (prefix, local_name) = get_attribute_parts(name.as_slice()); - match prefix { - Some(ref prefix_str) => { - // Step 5. - if namespace == namespace::Null { - return Err(NamespaceError); - } - - // Step 6. - if "xml" == prefix_str.as_slice() && namespace != namespace::XML { - return Err(NamespaceError); - } - - // Step 7b. - if "xmlns" == prefix_str.as_slice() && namespace != namespace::XMLNS { - return Err(NamespaceError); - } - }, - None => {} - } - - let name = Atom::from_slice(name.as_slice()); - let local_name = Atom::from_slice(local_name); - let xmlns = Atom::from_slice("xmlns"); // TODO: Make this a static atom type - - // Step 7a. - if xmlns == name && namespace != namespace::XMLNS { - return Err(NamespaceError); - } - - // Step 8. - if namespace == namespace::XMLNS && xmlns != name && Some("xmlns") != prefix { - return Err(NamespaceError); - } - - // Step 9. - let value = self.parse_attribute(&namespace, &local_name, value); - self.do_set_attribute(local_name.clone(), value, name, - namespace.clone(), prefix.map(|s| s.to_string()), - |attr| { - *attr.local_name() == local_name && - attr.namespace == namespace - }); - Ok(()) - } - - // http://dom.spec.whatwg.org/#dom-element-removeattribute - fn RemoveAttribute(&self, name: DOMString) { - let name = if self.html_element_in_html_document() { - name.as_slice().to_ascii_lower() - } else { - name - }; - self.remove_attribute(namespace::Null, name.as_slice()) - } - - // http://dom.spec.whatwg.org/#dom-element-removeattributens - fn RemoveAttributeNS(&self, - namespace: Option<DOMString>, - localname: DOMString) { - let namespace = Namespace::from_str(null_str_as_empty_ref(&namespace)); - self.remove_attribute(namespace, localname.as_slice()) - } - - // http://dom.spec.whatwg.org/#dom-element-hasattribute - fn HasAttribute(&self, - name: DOMString) -> bool { - self.has_attribute(name.as_slice()) - } - - // http://dom.spec.whatwg.org/#dom-element-hasattributens - fn HasAttributeNS(&self, - namespace: Option<DOMString>, - local_name: DOMString) -> bool { - self.GetAttributeNS(namespace, local_name).is_some() - } - - fn GetElementsByTagName(&self, localname: DOMString) -> Temporary<HTMLCollection> { - let window = window_from_node(self).root(); - HTMLCollection::by_tag_name(&*window, NodeCast::from_ref(self), localname) - } - - fn GetElementsByTagNameNS(&self, maybe_ns: Option<DOMString>, - localname: DOMString) -> Temporary<HTMLCollection> { - let window = window_from_node(self).root(); - HTMLCollection::by_tag_name_ns(&*window, NodeCast::from_ref(self), localname, maybe_ns) - } - - fn GetElementsByClassName(&self, classes: DOMString) -> Temporary<HTMLCollection> { - let window = window_from_node(self).root(); - HTMLCollection::by_class_name(&*window, NodeCast::from_ref(self), classes) - } - - // http://dev.w3.org/csswg/cssom-view/#dom-element-getclientrects - fn GetClientRects(&self) -> Temporary<DOMRectList> { - let win = window_from_node(self).root(); - let node: &JSRef<Node> = NodeCast::from_ref(self); - let rects = node.get_content_boxes(); - let rects: Vec<Root<DOMRect>> = rects.iter().map(|r| { - DOMRect::new( - &*win, - r.origin.y, - r.origin.y + r.size.height, - r.origin.x, - r.origin.x + r.size.width).root() - }).collect(); - - DOMRectList::new(&*win, rects.iter().map(|rect| rect.deref().clone()).collect()) - } - - // http://dev.w3.org/csswg/cssom-view/#dom-element-getboundingclientrect - fn GetBoundingClientRect(&self) -> Temporary<DOMRect> { - let win = window_from_node(self).root(); - let node: &JSRef<Node> = NodeCast::from_ref(self); - let rect = node.get_bounding_content_box(); - DOMRect::new( - &*win, - rect.origin.y, - rect.origin.y + rect.size.height, - rect.origin.x, - rect.origin.x + rect.size.width) - } - - fn GetInnerHTML(&self) -> Fallible<DOMString> { - //XXX TODO: XML case - Ok(serialize(&mut NodeIterator::new(NodeCast::from_ref(self), false, false))) - } - - fn GetOuterHTML(&self) -> Fallible<DOMString> { - Ok(serialize(&mut NodeIterator::new(NodeCast::from_ref(self), true, false))) - } - - // http://dom.spec.whatwg.org/#dom-parentnode-children - fn Children(&self) -> Temporary<HTMLCollection> { - let window = window_from_node(self).root(); - HTMLCollection::children(&*window, NodeCast::from_ref(self)) - } - - // http://dom.spec.whatwg.org/#dom-parentnode-queryselector - fn QuerySelector(&self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>> { - let root: &JSRef<Node> = NodeCast::from_ref(self); - root.query_selector(selectors) - } - - // http://dom.spec.whatwg.org/#dom-parentnode-queryselectorall - fn QuerySelectorAll(&self, selectors: DOMString) -> Fallible<Temporary<NodeList>> { - let root: &JSRef<Node> = NodeCast::from_ref(self); - root.query_selector_all(selectors) - } - - // http://dom.spec.whatwg.org/#dom-childnode-remove - fn Remove(&self) { - let node: &JSRef<Node> = NodeCast::from_ref(self); - node.remove_self(); - } - - // http://dom.spec.whatwg.org/#dom-element-matches - fn Matches(&self, selectors: DOMString) -> Fallible<bool> { - match parse_selector_list_from_str(selectors.as_slice()) { - Err(()) => Err(Syntax), - Ok(ref selectors) => { - let root: &JSRef<Node> = NodeCast::from_ref(self); - Ok(matches(selectors, root)) - } - } - } -} - -pub fn get_attribute_parts<'a>(name: &'a str) -> (Option<&'a str>, &'a str) { - //FIXME: Throw for XML-invalid names - //FIXME: Throw for XMLNS-invalid names - let (prefix, local_name) = if name.contains(":") { - let mut parts = name.splitn(':', 1); - (Some(parts.next().unwrap()), parts.next().unwrap()) - } else { - (None, name) - }; - - (prefix, local_name) -} - -impl<'a> VirtualMethods for JSRef<'a, Element> { - fn super_type<'a>(&'a self) -> Option<&'a VirtualMethods> { - let node: &JSRef<Node> = NodeCast::from_ref(self); - Some(node as &VirtualMethods) - } - - fn after_set_attr(&self, name: &Atom, value: DOMString) { - match self.super_type() { - Some(ref s) => s.after_set_attr(name, value.clone()), - _ => (), - } - - match name.as_slice() { - "style" => { - let doc = document_from_node(self).root(); - let base_url = doc.deref().url().clone(); - let style = Some(style::parse_style_attribute(value.as_slice(), &base_url)); - *self.deref().style_attribute.deref().borrow_mut() = style; - } - "id" => { - let node: &JSRef<Node> = NodeCast::from_ref(self); - if node.is_in_doc() && !value.is_empty() { - let doc = document_from_node(self).root(); - doc.register_named_element(self, value.clone()); - } - } - _ => () - } - - self.notify_attribute_changed(name); - } - - fn before_remove_attr(&self, name: &Atom, value: DOMString) { - match self.super_type() { - Some(ref s) => s.before_remove_attr(name, value.clone()), - _ => (), - } - - match name.as_slice() { - "style" => { - *self.deref().style_attribute.deref().borrow_mut() = None; - } - "id" => { - let node: &JSRef<Node> = NodeCast::from_ref(self); - if node.is_in_doc() && !value.is_empty() { - let doc = document_from_node(self).root(); - doc.unregister_named_element(self, value); - } - } - _ => () - } - - self.notify_attribute_changed(name); - } - - fn parse_plain_attribute(&self, name: &str, value: DOMString) -> AttrValue { - match name { - "id" => AttrValue::from_atomic(value), - "class" => AttrValue::from_tokenlist(value), - _ => self.super_type().unwrap().parse_plain_attribute(name, value), - } - } - - fn bind_to_tree(&self, tree_in_doc: bool) { - match self.super_type() { - Some(ref s) => s.bind_to_tree(tree_in_doc), - _ => (), - } - - if !tree_in_doc { return; } - - match self.get_attribute(Null, "id").root() { - Some(attr) => { - let doc = document_from_node(self).root(); - let value = attr.deref().Value(); - if !value.is_empty() { - doc.deref().register_named_element(self, value); - } - } - _ => () - } - } - - fn unbind_from_tree(&self, tree_in_doc: bool) { - match self.super_type() { - Some(ref s) => s.unbind_from_tree(tree_in_doc), - _ => (), - } - - if !tree_in_doc { return; } - - match self.get_attribute(Null, "id").root() { - Some(attr) => { - let doc = document_from_node(self).root(); - let value = attr.deref().Value(); - if !value.is_empty() { - doc.deref().unregister_named_element(self, value); - } - } - _ => () - } - } -} - -impl<'a> style::TElement for JSRef<'a, Element> { - fn get_attr(&self, namespace: &Namespace, attr: &str) -> Option<&'static str> { - self.get_attribute(namespace.clone(), attr).root().map(|attr| { - unsafe { mem::transmute(attr.deref().value().as_slice()) } - }) - } - fn get_link(&self) -> Option<&'static str> { - // FIXME: This is HTML only. - let node: &JSRef<Node> = NodeCast::from_ref(self); - match node.type_id() { - // http://www.whatwg.org/specs/web-apps/current-work/multipage/selectors.html# - // selector-link - ElementNodeTypeId(HTMLAnchorElementTypeId) | - ElementNodeTypeId(HTMLAreaElementTypeId) | - ElementNodeTypeId(HTMLLinkElementTypeId) => self.get_attr(&namespace::Null, "href"), - _ => None, - } - } - fn get_local_name<'a>(&'a self) -> &'a Atom { - (self as &ElementHelpers).get_local_name() - } - fn get_namespace<'a>(&'a self) -> &'a Namespace { - (self as &ElementHelpers).get_namespace() - } - fn get_hover_state(&self) -> bool { - let node: &JSRef<Node> = NodeCast::from_ref(self); - node.get_hover_state() - } - fn get_id<'a>(&self) -> Option<Atom> { - self.get_attribute(namespace::Null, "id").map(|attr| { - let attr = attr.root(); - match *attr.value() { - AtomAttrValue(ref val) => val.clone(), - _ => fail!("`id` attribute should be AtomAttrValue"), - } - }) - } - fn get_disabled_state(&self) -> bool { - let node: &JSRef<Node> = NodeCast::from_ref(self); - node.get_disabled_state() - } - fn get_enabled_state(&self) -> bool { - let node: &JSRef<Node> = NodeCast::from_ref(self); - node.get_enabled_state() - } -} |