mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
commit
da668f53d9
11 changed files with 269 additions and 47 deletions
|
@ -6,13 +6,13 @@ use dom::bindings::codegen::Bindings::AttrBinding;
|
||||||
use dom::bindings::codegen::InheritTypes::NodeCast;
|
use dom::bindings::codegen::InheritTypes::NodeCast;
|
||||||
use dom::bindings::js::{JS, JSRef, Temporary};
|
use dom::bindings::js::{JS, JSRef, Temporary};
|
||||||
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
|
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
|
||||||
use dom::element::Element;
|
use dom::element::{Element, AttributeHandlers};
|
||||||
use dom::node::Node;
|
use dom::node::Node;
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
use dom::virtualmethods::vtable_for;
|
use dom::virtualmethods::vtable_for;
|
||||||
use servo_util::namespace;
|
use servo_util::namespace;
|
||||||
use servo_util::namespace::Namespace;
|
use servo_util::namespace::Namespace;
|
||||||
use servo_util::str::DOMString;
|
use servo_util::str::{DOMString, HTML_SPACE_CHARACTERS};
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
pub enum AttrSettingType {
|
pub enum AttrSettingType {
|
||||||
|
@ -20,11 +20,45 @@ pub enum AttrSettingType {
|
||||||
ReplacedAttr,
|
ReplacedAttr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deriving(Eq, Clone, Encodable)]
|
||||||
|
pub enum AttrValue {
|
||||||
|
StringAttrValue(DOMString),
|
||||||
|
TokenListAttrValue(DOMString, Vec<(uint, uint)>),
|
||||||
|
UIntAttrValue(DOMString, u32),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AttrValue {
|
||||||
|
pub fn from_tokenlist(list: DOMString) -> AttrValue {
|
||||||
|
let mut indexes = vec![];
|
||||||
|
let mut last_index: uint = 0;
|
||||||
|
for (index, ch) in list.as_slice().char_indices() {
|
||||||
|
if HTML_SPACE_CHARACTERS.iter().any(|&space| space == ch) {
|
||||||
|
indexes.push((last_index, index));
|
||||||
|
last_index = index + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TokenListAttrValue(list, indexes);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_u32(string: DOMString, default: u32) -> AttrValue {
|
||||||
|
let result: u32 = from_str(string.as_slice()).unwrap_or(default);
|
||||||
|
UIntAttrValue(string, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_slice<'a>(&'a self) -> &'a str {
|
||||||
|
match *self {
|
||||||
|
StringAttrValue(ref value) |
|
||||||
|
TokenListAttrValue(ref value, _) |
|
||||||
|
UIntAttrValue(ref value, _) => value.as_slice(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[deriving(Encodable)]
|
#[deriving(Encodable)]
|
||||||
pub struct Attr {
|
pub struct Attr {
|
||||||
pub reflector_: Reflector,
|
pub reflector_: Reflector,
|
||||||
pub local_name: DOMString,
|
pub local_name: DOMString,
|
||||||
pub value: DOMString,
|
value: AttrValue,
|
||||||
pub name: DOMString,
|
pub name: DOMString,
|
||||||
pub namespace: Namespace,
|
pub namespace: Namespace,
|
||||||
pub prefix: Option<DOMString>,
|
pub prefix: Option<DOMString>,
|
||||||
|
@ -44,7 +78,7 @@ impl Reflectable for Attr {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Attr {
|
impl Attr {
|
||||||
fn new_inherited(local_name: DOMString, value: DOMString,
|
fn new_inherited(local_name: DOMString, value: AttrValue,
|
||||||
name: DOMString, namespace: Namespace,
|
name: DOMString, namespace: Namespace,
|
||||||
prefix: Option<DOMString>, owner: &JSRef<Element>) -> Attr {
|
prefix: Option<DOMString>, owner: &JSRef<Element>) -> Attr {
|
||||||
Attr {
|
Attr {
|
||||||
|
@ -58,14 +92,14 @@ impl Attr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(window: &JSRef<Window>, local_name: DOMString, value: DOMString,
|
pub fn new(window: &JSRef<Window>, local_name: DOMString, value: AttrValue,
|
||||||
name: DOMString, namespace: Namespace,
|
name: DOMString, namespace: Namespace,
|
||||||
prefix: Option<DOMString>, owner: &JSRef<Element>) -> Temporary<Attr> {
|
prefix: Option<DOMString>, owner: &JSRef<Element>) -> Temporary<Attr> {
|
||||||
let attr = Attr::new_inherited(local_name, value, name, namespace, prefix, owner);
|
let attr = Attr::new_inherited(local_name, value, name, namespace, prefix, owner);
|
||||||
reflect_dom_object(box attr, window, AttrBinding::Wrap)
|
reflect_dom_object(box attr, window, AttrBinding::Wrap)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_value(&mut self, set_type: AttrSettingType, value: DOMString) {
|
pub fn set_value(&mut self, set_type: AttrSettingType, value: AttrValue) {
|
||||||
let owner = self.owner.get().root();
|
let owner = self.owner.get().root();
|
||||||
let node: &JSRef<Node> = NodeCast::from_ref(&*owner);
|
let node: &JSRef<Node> = NodeCast::from_ref(&*owner);
|
||||||
let namespace_is_null = self.namespace == namespace::Null;
|
let namespace_is_null = self.namespace == namespace::Null;
|
||||||
|
@ -73,7 +107,7 @@ impl Attr {
|
||||||
match set_type {
|
match set_type {
|
||||||
ReplacedAttr => {
|
ReplacedAttr => {
|
||||||
if namespace_is_null {
|
if namespace_is_null {
|
||||||
vtable_for(node).before_remove_attr(self.local_name.clone(), self.value.clone());
|
vtable_for(node).before_remove_attr(self.local_name.clone(), self.value.as_slice().to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FirstSetAttr => {}
|
FirstSetAttr => {}
|
||||||
|
@ -82,10 +116,14 @@ impl Attr {
|
||||||
self.value = value;
|
self.value = value;
|
||||||
|
|
||||||
if namespace_is_null {
|
if namespace_is_null {
|
||||||
vtable_for(node).after_set_attr(self.local_name.clone(), self.value.clone());
|
vtable_for(node).after_set_attr(self.local_name.clone(), self.value.as_slice().to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn value<'a>(&'a self) -> &'a AttrValue {
|
||||||
|
&self.value
|
||||||
|
}
|
||||||
|
|
||||||
pub fn value_ref<'a>(&'a self) -> &'a str {
|
pub fn value_ref<'a>(&'a self) -> &'a str {
|
||||||
self.value.as_slice()
|
self.value.as_slice()
|
||||||
}
|
}
|
||||||
|
@ -106,10 +144,13 @@ impl<'a> AttrMethods for JSRef<'a, Attr> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Value(&self) -> DOMString {
|
fn Value(&self) -> DOMString {
|
||||||
self.value.clone()
|
self.value.as_slice().to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn SetValue(&mut self, value: DOMString) {
|
fn SetValue(&mut self, value: DOMString) {
|
||||||
|
let owner = self.owner.get().root();
|
||||||
|
let value = owner.deref().parse_attribute(
|
||||||
|
&self.namespace, self.deref().local_name.as_slice(), value);
|
||||||
self.set_value(ReplacedAttr, value);
|
self.set_value(ReplacedAttr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ DOMInterfaces = {
|
||||||
'DOMException': {},
|
'DOMException': {},
|
||||||
'DOMImplementation': {},
|
'DOMImplementation': {},
|
||||||
'DOMParser': {},
|
'DOMParser': {},
|
||||||
|
'DOMTokenList': {},
|
||||||
'Element': {},
|
'Element': {},
|
||||||
'Event': {},
|
'Event': {},
|
||||||
'EventHandler': {},
|
'EventHandler': {},
|
||||||
|
|
103
src/components/script/dom/domtokenlist.rs
Normal file
103
src/components/script/dom/domtokenlist.rs
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
/* 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, TokenListAttrValue};
|
||||||
|
use dom::bindings::codegen::Bindings::DOMTokenListBinding;
|
||||||
|
use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable};
|
||||||
|
use dom::bindings::utils::{Reflector, Reflectable, reflect_dom_object};
|
||||||
|
use dom::element::{Element, AttributeHandlers};
|
||||||
|
use dom::node::window_from_node;
|
||||||
|
|
||||||
|
use servo_util::namespace::Null;
|
||||||
|
use servo_util::str::DOMString;
|
||||||
|
|
||||||
|
#[deriving(Encodable)]
|
||||||
|
pub struct DOMTokenList {
|
||||||
|
reflector_: Reflector,
|
||||||
|
element: JS<Element>,
|
||||||
|
local_name: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DOMTokenList {
|
||||||
|
pub fn new_inherited(element: &JSRef<Element>,
|
||||||
|
local_name: &'static str) -> DOMTokenList {
|
||||||
|
DOMTokenList {
|
||||||
|
reflector_: Reflector::new(),
|
||||||
|
element: JS::from_rooted(element.clone()),
|
||||||
|
local_name: local_name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(element: &JSRef<Element>,
|
||||||
|
local_name: &'static str) -> Temporary<DOMTokenList> {
|
||||||
|
let window = window_from_node(element).root();
|
||||||
|
reflect_dom_object(box DOMTokenList::new_inherited(element, local_name),
|
||||||
|
&*window, DOMTokenListBinding::Wrap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Reflectable for DOMTokenList {
|
||||||
|
fn reflector<'a>(&'a self) -> &'a Reflector {
|
||||||
|
&self.reflector_
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
|
||||||
|
&mut self.reflector_
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait PrivateDOMTokenListHelpers {
|
||||||
|
fn attribute(&self) -> Option<Temporary<Attr>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> PrivateDOMTokenListHelpers for JSRef<'a, DOMTokenList> {
|
||||||
|
fn attribute(&self) -> Option<Temporary<Attr>> {
|
||||||
|
let element = self.element.root();
|
||||||
|
element.deref().get_attribute(Null, self.local_name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait DOMTokenListMethods {
|
||||||
|
fn Length(&self) -> u32;
|
||||||
|
fn Item(&self, index: u32) -> Option<DOMString>;
|
||||||
|
fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<DOMString>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://dom.spec.whatwg.org/#domtokenlist
|
||||||
|
impl<'a> DOMTokenListMethods for JSRef<'a, DOMTokenList> {
|
||||||
|
// http://dom.spec.whatwg.org/#dom-domtokenlist-length
|
||||||
|
fn Length(&self) -> u32 {
|
||||||
|
let attribute = self.attribute().root();
|
||||||
|
match attribute {
|
||||||
|
Some(attribute) => {
|
||||||
|
match *attribute.deref().value() {
|
||||||
|
TokenListAttrValue(_, ref indexes) => indexes.len() as u32,
|
||||||
|
_ => fail!("Expected a TokenListAttrValue"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://dom.spec.whatwg.org/#dom-domtokenlist-item
|
||||||
|
fn Item(&self, index: u32) -> Option<DOMString> {
|
||||||
|
let attribute = self.attribute().root();
|
||||||
|
attribute.and_then(|attribute| {
|
||||||
|
match *attribute.deref().value() {
|
||||||
|
TokenListAttrValue(ref value, ref indexes) => {
|
||||||
|
indexes.as_slice().get(index as uint).map(|&(start, end)| {
|
||||||
|
value.as_slice().slice(start, end).to_string()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
_ => fail!("Expected a TokenListAttrValue"),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<DOMString> {
|
||||||
|
let item = self.Item(index);
|
||||||
|
*found = item.is_some();
|
||||||
|
item
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
//! Element nodes.
|
//! Element nodes.
|
||||||
|
|
||||||
use dom::attr::{Attr, ReplacedAttr, FirstSetAttr, AttrMethods};
|
use dom::attr::{Attr, ReplacedAttr, FirstSetAttr, AttrMethods};
|
||||||
|
use dom::attr::{AttrValue, StringAttrValue, UIntAttrValue};
|
||||||
use dom::attrlist::AttrList;
|
use dom::attrlist::AttrList;
|
||||||
use dom::bindings::codegen::Bindings::ElementBinding;
|
use dom::bindings::codegen::Bindings::ElementBinding;
|
||||||
use dom::bindings::codegen::InheritTypes::{ElementDerived, NodeCast};
|
use dom::bindings::codegen::InheritTypes::{ElementDerived, NodeCast};
|
||||||
|
@ -17,6 +18,7 @@ use dom::bindings::utils::{QName, Name, InvalidXMLName, xml_name_type};
|
||||||
use dom::clientrect::ClientRect;
|
use dom::clientrect::ClientRect;
|
||||||
use dom::clientrectlist::ClientRectList;
|
use dom::clientrectlist::ClientRectList;
|
||||||
use dom::document::{Document, DocumentHelpers};
|
use dom::document::{Document, DocumentHelpers};
|
||||||
|
use dom::domtokenlist::DOMTokenList;
|
||||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||||
use dom::htmlcollection::HTMLCollection;
|
use dom::htmlcollection::HTMLCollection;
|
||||||
use dom::htmlserializer::serialize;
|
use dom::htmlserializer::serialize;
|
||||||
|
@ -43,7 +45,8 @@ pub struct Element {
|
||||||
pub prefix: Option<DOMString>,
|
pub prefix: Option<DOMString>,
|
||||||
pub attrs: RefCell<Vec<JS<Attr>>>,
|
pub attrs: RefCell<Vec<JS<Attr>>>,
|
||||||
pub style_attribute: Traceable<RefCell<Option<style::PropertyDeclarationBlock>>>,
|
pub style_attribute: Traceable<RefCell<Option<style::PropertyDeclarationBlock>>>,
|
||||||
pub attr_list: Cell<Option<JS<AttrList>>>
|
pub attr_list: Cell<Option<JS<AttrList>>>,
|
||||||
|
class_list: Cell<Option<JS<DOMTokenList>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ElementDerived for EventTarget {
|
impl ElementDerived for EventTarget {
|
||||||
|
@ -151,6 +154,7 @@ impl Element {
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
attrs: RefCell::new(vec!()),
|
attrs: RefCell::new(vec!()),
|
||||||
attr_list: Cell::new(None),
|
attr_list: Cell::new(None),
|
||||||
|
class_list: Cell::new(None),
|
||||||
style_attribute: Traceable::new(RefCell::new(None)),
|
style_attribute: Traceable::new(RefCell::new(None)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,7 +180,7 @@ impl RawLayoutElementHelpers for Element {
|
||||||
name == (*attr).local_name.as_slice() && (*attr).namespace == *namespace
|
name == (*attr).local_name.as_slice() && (*attr).namespace == *namespace
|
||||||
}).map(|attr| {
|
}).map(|attr| {
|
||||||
let attr = attr.unsafe_get();
|
let attr = attr.unsafe_get();
|
||||||
mem::transmute((*attr).value.as_slice())
|
mem::transmute((*attr).value_ref())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -223,11 +227,12 @@ pub trait AttributeHandlers {
|
||||||
fn set_attribute_from_parser(&self, local_name: DOMString,
|
fn set_attribute_from_parser(&self, local_name: DOMString,
|
||||||
value: DOMString, namespace: Namespace,
|
value: DOMString, namespace: Namespace,
|
||||||
prefix: Option<DOMString>);
|
prefix: Option<DOMString>);
|
||||||
fn set_attribute(&self, namespace: Namespace, name: DOMString,
|
fn set_attribute(&self, name: &str, value: AttrValue);
|
||||||
value: DOMString) -> ErrorResult;
|
fn do_set_attribute(&self, local_name: DOMString, value: AttrValue,
|
||||||
fn do_set_attribute(&self, local_name: DOMString, value: DOMString,
|
|
||||||
name: DOMString, namespace: Namespace,
|
name: DOMString, namespace: Namespace,
|
||||||
prefix: Option<DOMString>, cb: |&JSRef<Attr>| -> bool);
|
prefix: Option<DOMString>, cb: |&JSRef<Attr>| -> bool);
|
||||||
|
fn parse_attribute(&self, namespace: &Namespace, local_name: &str,
|
||||||
|
value: DOMString) -> AttrValue;
|
||||||
|
|
||||||
fn remove_attribute(&self, namespace: Namespace, name: DOMString) -> ErrorResult;
|
fn remove_attribute(&self, namespace: Namespace, name: DOMString) -> ErrorResult;
|
||||||
fn notify_attribute_changed(&self, local_name: DOMString);
|
fn notify_attribute_changed(&self, local_name: DOMString);
|
||||||
|
@ -238,6 +243,8 @@ pub trait AttributeHandlers {
|
||||||
fn set_url_attribute(&self, name: &str, value: DOMString);
|
fn set_url_attribute(&self, name: &str, value: DOMString);
|
||||||
fn get_string_attribute(&self, name: &str) -> DOMString;
|
fn get_string_attribute(&self, name: &str) -> DOMString;
|
||||||
fn set_string_attribute(&self, name: &str, value: 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);
|
fn set_uint_attribute(&self, name: &str, value: u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,37 +271,23 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
|
||||||
None => local_name.clone(),
|
None => local_name.clone(),
|
||||||
Some(ref prefix) => format!("{:s}:{:s}", *prefix, local_name),
|
Some(ref prefix) => format!("{:s}:{:s}", *prefix, local_name),
|
||||||
};
|
};
|
||||||
|
let value = self.parse_attribute(&namespace, local_name.as_slice(), value);
|
||||||
self.do_set_attribute(local_name, value, name, namespace, prefix, |_| false)
|
self.do_set_attribute(local_name, value, name, namespace, prefix, |_| false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_attribute(&self, namespace: Namespace, name: DOMString,
|
fn set_attribute(&self, name: &str, value: AttrValue) {
|
||||||
value: DOMString) -> ErrorResult {
|
assert!(name == name.to_ascii_lower().as_slice());
|
||||||
let (prefix, local_name) = get_attribute_parts(name.clone());
|
assert!(!name.contains(":"));
|
||||||
match prefix {
|
|
||||||
Some(ref prefix_str) => {
|
|
||||||
if namespace == namespace::Null ||
|
|
||||||
("xml" == prefix_str.as_slice() && namespace != namespace::XML) ||
|
|
||||||
("xmlns" == prefix_str.as_slice() && namespace != namespace::XMLNS) {
|
|
||||||
return Err(NamespaceError);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||||
node.wait_until_safe_to_modify_dom();
|
node.wait_until_safe_to_modify_dom();
|
||||||
|
|
||||||
let position: |&JSRef<Attr>| -> bool =
|
self.do_set_attribute(name.to_string(), value, name.to_string(),
|
||||||
if self.html_element_in_html_document() {
|
namespace::Null, None,
|
||||||
|attr| attr.deref().local_name.as_slice().eq_ignore_ascii_case(local_name.as_slice())
|
|attr| attr.deref().local_name.as_slice() == name);
|
||||||
} else {
|
|
||||||
|attr| attr.deref().local_name == local_name
|
|
||||||
};
|
|
||||||
self.do_set_attribute(name.clone(), value, name.clone(), namespace::Null, None, position);
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_set_attribute(&self, local_name: DOMString, value: DOMString,
|
fn do_set_attribute(&self, local_name: DOMString, value: AttrValue,
|
||||||
name: DOMString, namespace: Namespace,
|
name: DOMString, namespace: Namespace,
|
||||||
prefix: Option<DOMString>, cb: |&JSRef<Attr>| -> bool) {
|
prefix: Option<DOMString>, cb: |&JSRef<Attr>| -> bool) {
|
||||||
let idx = self.deref().attrs.borrow().iter()
|
let idx = self.deref().attrs.borrow().iter()
|
||||||
|
@ -314,6 +307,16 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
|
||||||
self.deref().attrs.borrow().get(idx).root().set_value(set_type, value);
|
self.deref().attrs.borrow().get(idx).root().set_value(set_type, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_attribute(&self, namespace: &Namespace, local_name: &str,
|
||||||
|
value: DOMString) -> AttrValue {
|
||||||
|
if *namespace == namespace::Null {
|
||||||
|
vtable_for(NodeCast::from_ref(self))
|
||||||
|
.parse_plain_attribute(local_name, value)
|
||||||
|
} else {
|
||||||
|
StringAttrValue(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn remove_attribute(&self, namespace: Namespace, name: DOMString) -> ErrorResult {
|
fn remove_attribute(&self, namespace: Namespace, name: DOMString) -> ErrorResult {
|
||||||
let (_, local_name) = get_attribute_parts(name.clone());
|
let (_, local_name) = get_attribute_parts(name.clone());
|
||||||
|
|
||||||
|
@ -379,12 +382,30 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
|
||||||
}
|
}
|
||||||
fn set_string_attribute(&self, name: &str, value: DOMString) {
|
fn set_string_attribute(&self, name: &str, value: DOMString) {
|
||||||
assert!(name == name.to_ascii_lower().as_slice());
|
assert!(name == name.to_ascii_lower().as_slice());
|
||||||
assert!(self.set_attribute(Null, name.to_string(), value).is_ok());
|
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) {
|
fn set_uint_attribute(&self, name: &str, value: u32) {
|
||||||
assert!(name == name.to_ascii_lower().as_slice());
|
assert!(name == name.to_ascii_lower().as_slice());
|
||||||
assert!(self.set_attribute(Null, name.to_string(), value.to_str()).is_ok());
|
self.set_attribute(name, UIntAttrValue(value.to_str(), value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,6 +434,7 @@ pub trait ElementMethods {
|
||||||
fn SetId(&self, id: DOMString);
|
fn SetId(&self, id: DOMString);
|
||||||
fn ClassName(&self) -> DOMString;
|
fn ClassName(&self) -> DOMString;
|
||||||
fn SetClassName(&self, class: DOMString);
|
fn SetClassName(&self, class: DOMString);
|
||||||
|
fn ClassList(&self) -> Temporary<DOMTokenList>;
|
||||||
fn Attributes(&self) -> Temporary<AttrList>;
|
fn Attributes(&self) -> Temporary<AttrList>;
|
||||||
fn GetAttribute(&self, name: DOMString) -> Option<DOMString>;
|
fn GetAttribute(&self, name: DOMString) -> Option<DOMString>;
|
||||||
fn GetAttributeNS(&self, namespace: Option<DOMString>, local_name: DOMString) -> Option<DOMString>;
|
fn GetAttributeNS(&self, namespace: Option<DOMString>, local_name: DOMString) -> Option<DOMString>;
|
||||||
|
@ -480,7 +502,19 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
|
||||||
|
|
||||||
// http://dom.spec.whatwg.org/#dom-element-classname
|
// http://dom.spec.whatwg.org/#dom-element-classname
|
||||||
fn SetClassName(&self, class: DOMString) {
|
fn SetClassName(&self, class: DOMString) {
|
||||||
self.set_string_attribute("class", class);
|
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
|
// http://dom.spec.whatwg.org/#dom-element-attributes
|
||||||
|
@ -543,6 +577,7 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Step 3-5.
|
// Step 3-5.
|
||||||
|
let value = self.parse_attribute(&namespace::Null, name.as_slice(), value);
|
||||||
self.do_set_attribute(name.clone(), value, name.clone(), namespace::Null, None, |attr| {
|
self.do_set_attribute(name.clone(), value, name.clone(), namespace::Null, None, |attr| {
|
||||||
attr.deref().name == name
|
attr.deref().name == name
|
||||||
});
|
});
|
||||||
|
@ -604,6 +639,7 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 9.
|
// Step 9.
|
||||||
|
let value = self.parse_attribute(&namespace, local_name.as_slice(), value);
|
||||||
self.do_set_attribute(local_name.clone(), value, name, namespace.clone(), prefix, |attr| {
|
self.do_set_attribute(local_name.clone(), value, name, namespace.clone(), prefix, |attr| {
|
||||||
attr.deref().local_name == local_name &&
|
attr.deref().local_name == local_name &&
|
||||||
attr.deref().namespace == namespace
|
attr.deref().namespace == namespace
|
||||||
|
@ -795,6 +831,13 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
|
||||||
self.notify_attribute_changed(name);
|
self.notify_attribute_changed(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_plain_attribute(&self, name: &str, value: DOMString) -> AttrValue {
|
||||||
|
match name {
|
||||||
|
"class" => AttrValue::from_tokenlist(value),
|
||||||
|
_ => self.super_type().unwrap().parse_plain_attribute(name, value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn bind_to_tree(&self) {
|
fn bind_to_tree(&self) {
|
||||||
match self.super_type() {
|
match self.super_type() {
|
||||||
Some(ref s) => s.bind_to_tree(),
|
Some(ref s) => s.bind_to_tree(),
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use dom::attr::AttrValue;
|
||||||
use dom::bindings::codegen::Bindings::HTMLImageElementBinding;
|
use dom::bindings::codegen::Bindings::HTMLImageElementBinding;
|
||||||
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, HTMLElementCast, HTMLImageElementDerived};
|
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, HTMLElementCast, HTMLImageElementDerived};
|
||||||
use dom::bindings::js::{JS, JSRef, Temporary};
|
use dom::bindings::js::{JS, JSRef, Temporary};
|
||||||
|
@ -199,7 +200,7 @@ impl<'a> HTMLImageElementMethods for JSRef<'a, HTMLImageElement> {
|
||||||
|
|
||||||
fn Hspace(&self) -> u32 {
|
fn Hspace(&self) -> u32 {
|
||||||
let element: &JSRef<Element> = ElementCast::from_ref(self);
|
let element: &JSRef<Element> = ElementCast::from_ref(self);
|
||||||
from_str::<u32>(element.get_string_attribute("hspace").as_slice()).unwrap()
|
element.get_uint_attribute("hspace")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn SetHspace(&self, hspace: u32) {
|
fn SetHspace(&self, hspace: u32) {
|
||||||
|
@ -209,7 +210,7 @@ impl<'a> HTMLImageElementMethods for JSRef<'a, HTMLImageElement> {
|
||||||
|
|
||||||
fn Vspace(&self) -> u32 {
|
fn Vspace(&self) -> u32 {
|
||||||
let element: &JSRef<Element> = ElementCast::from_ref(self);
|
let element: &JSRef<Element> = ElementCast::from_ref(self);
|
||||||
from_str::<u32>(element.get_string_attribute("vspace").as_slice()).unwrap()
|
element.get_uint_attribute("vspace")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn SetVspace(&self, vspace: u32) {
|
fn SetVspace(&self, vspace: u32) {
|
||||||
|
@ -267,4 +268,11 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLImageElement> {
|
||||||
self.update_image(None, None);
|
self.update_image(None, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_plain_attribute(&self, name: &str, value: DOMString) -> AttrValue {
|
||||||
|
match name {
|
||||||
|
"width" | "height" | "hspace" | "vspace" => AttrValue::from_u32(value, 0),
|
||||||
|
_ => self.super_type().unwrap().parse_plain_attribute(name, value),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,7 +151,7 @@ fn serialize_attr(attr: &JSRef<Attr>, html: &mut String) {
|
||||||
html.push_str(attr.deref().name.as_slice());
|
html.push_str(attr.deref().name.as_slice());
|
||||||
};
|
};
|
||||||
html.push_str("=\"");
|
html.push_str("=\"");
|
||||||
escape(attr.deref().value.as_slice(), true, html);
|
escape(attr.deref().value_ref(), true, html);
|
||||||
html.push_char('"');
|
html.push_char('"');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1327,7 +1327,7 @@ impl Node {
|
||||||
for attr in node_elem.deref().attrs.borrow().iter().map(|attr| attr.root()) {
|
for attr in node_elem.deref().attrs.borrow().iter().map(|attr| attr.root()) {
|
||||||
copy_elem.deref().attrs.borrow_mut().push_unrooted(
|
copy_elem.deref().attrs.borrow_mut().push_unrooted(
|
||||||
&Attr::new(&*window,
|
&Attr::new(&*window,
|
||||||
attr.deref().local_name.clone(), attr.deref().value.clone(),
|
attr.deref().local_name.clone(), attr.deref().value().clone(),
|
||||||
attr.deref().name.clone(), attr.deref().namespace.clone(),
|
attr.deref().name.clone(), attr.deref().namespace.clone(),
|
||||||
attr.deref().prefix.clone(), copy_elem));
|
attr.deref().prefix.clone(), copy_elem));
|
||||||
}
|
}
|
||||||
|
@ -1815,7 +1815,7 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
|
||||||
other_element.attrs.borrow().iter().map(|attr| attr.root()).any(|other_attr| {
|
other_element.attrs.borrow().iter().map(|attr| attr.root()).any(|other_attr| {
|
||||||
(attr.namespace == other_attr.namespace) &&
|
(attr.namespace == other_attr.namespace) &&
|
||||||
(attr.local_name == other_attr.local_name) &&
|
(attr.local_name == other_attr.local_name) &&
|
||||||
(attr.value == other_attr.value)
|
(attr.deref().value_ref() == other_attr.deref().value_ref())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use dom::attr::{AttrValue, StringAttrValue};
|
||||||
use dom::bindings::codegen::InheritTypes::ElementCast;
|
use dom::bindings::codegen::InheritTypes::ElementCast;
|
||||||
use dom::bindings::codegen::InheritTypes::HTMLAnchorElementCast;
|
use dom::bindings::codegen::InheritTypes::HTMLAnchorElementCast;
|
||||||
use dom::bindings::codegen::InheritTypes::HTMLBodyElementCast;
|
use dom::bindings::codegen::InheritTypes::HTMLBodyElementCast;
|
||||||
|
@ -50,6 +51,15 @@ pub trait VirtualMethods {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the right AttrValue variant for the attribute with name `name`
|
||||||
|
/// on this element.
|
||||||
|
fn parse_plain_attribute(&self, name: &str, value: DOMString) -> AttrValue {
|
||||||
|
match self.super_type() {
|
||||||
|
Some(ref s) => s.parse_plain_attribute(name, value),
|
||||||
|
_ => StringAttrValue(value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Called when a Node is appended to a tree that is part of a Document.
|
/// Called when a Node is appended to a tree that is part of a Document.
|
||||||
fn bind_to_tree(&self) {
|
fn bind_to_tree(&self) {
|
||||||
match self.super_type() {
|
match self.super_type() {
|
||||||
|
|
15
src/components/script/dom/webidls/DOMTokenList.webidl
Normal file
15
src/components/script/dom/webidls/DOMTokenList.webidl
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
// http://dom.spec.whatwg.org/#domtokenlist
|
||||||
|
interface DOMTokenList {
|
||||||
|
readonly attribute unsigned long length;
|
||||||
|
getter DOMString? item(unsigned long index);
|
||||||
|
//boolean contains(DOMString token);
|
||||||
|
//void add(DOMString... tokens);
|
||||||
|
//void remove(DOMString... tokens);
|
||||||
|
//boolean toggle(DOMString token, optional boolean force);
|
||||||
|
//stringifier;
|
||||||
|
};
|
|
@ -28,8 +28,8 @@ interface Element : Node {
|
||||||
attribute DOMString id;
|
attribute DOMString id;
|
||||||
[Pure]
|
[Pure]
|
||||||
attribute DOMString className;
|
attribute DOMString className;
|
||||||
/*[Constant]
|
[Constant]
|
||||||
readonly attribute DOMTokenList? classList;*/
|
readonly attribute DOMTokenList classList;
|
||||||
|
|
||||||
[Constant]
|
[Constant]
|
||||||
readonly attribute AttrList attributes;
|
readonly attribute AttrList attributes;
|
||||||
|
|
|
@ -78,6 +78,7 @@ pub mod dom {
|
||||||
pub mod domexception;
|
pub mod domexception;
|
||||||
pub mod domimplementation;
|
pub mod domimplementation;
|
||||||
pub mod domparser;
|
pub mod domparser;
|
||||||
|
pub mod domtokenlist;
|
||||||
pub mod element;
|
pub mod element;
|
||||||
pub mod event;
|
pub mod event;
|
||||||
pub mod eventdispatcher;
|
pub mod eventdispatcher;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue