mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
Merge pull request #2907 from brunoabinader/css-selectors-disabled-enabled
Implement CSS selectors :enabled & :disabled (incl. HTML Elements support)
This commit is contained in:
commit
b65ed02941
27 changed files with 1131 additions and 40 deletions
|
@ -398,6 +398,18 @@ impl<'le> TElement for LayoutElement<'le> {
|
|||
fn get_id(&self) -> Option<Atom> {
|
||||
unsafe { self.element.get_attr_atom_for_layout(&namespace::Null, "id") }
|
||||
}
|
||||
|
||||
fn get_disabled_state(&self) -> bool {
|
||||
unsafe {
|
||||
self.element.node.get_disabled_state_for_layout()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_enabled_state(&self) -> bool {
|
||||
unsafe {
|
||||
self.element.node.get_enabled_state_for_layout()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_content(content_list: &content::T) -> String {
|
||||
|
|
|
@ -257,6 +257,8 @@ pub trait AttributeHandlers {
|
|||
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;
|
||||
|
@ -385,6 +387,25 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
|
|||
self.set_attribute(name, value);
|
||||
}
|
||||
|
||||
fn has_attribute(&self, name: &str) -> bool {
|
||||
let name = match self.html_element_in_html_document() {
|
||||
true => name.to_ascii_lower(),
|
||||
false => name.to_string()
|
||||
};
|
||||
self.deref().attrs.borrow().iter().map(|attr| attr.root()).any(|attr| {
|
||||
name == attr.local_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)
|
||||
|
@ -664,7 +685,7 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
|
|||
// http://dom.spec.whatwg.org/#dom-element-hasattribute
|
||||
fn HasAttribute(&self,
|
||||
name: DOMString) -> bool {
|
||||
self.GetAttribute(name).is_some()
|
||||
self.has_attribute(name.as_slice())
|
||||
}
|
||||
|
||||
// http://dom.spec.whatwg.org/#dom-element-hasattributens
|
||||
|
@ -925,4 +946,12 @@ impl<'a> style::TElement for JSRef<'a, Element> {
|
|||
}
|
||||
})
|
||||
}
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,6 +72,32 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLAnchorElement> {
|
|||
Some(htmlelement as &VirtualMethods)
|
||||
}
|
||||
|
||||
fn after_set_attr(&self, name: DOMString, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.after_set_attr(name.clone(), value.clone()),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
match name.as_slice() {
|
||||
"href" => node.set_enabled_state(true),
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn before_remove_attr(&self, name: DOMString, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.before_remove_attr(name.clone(), value.clone()),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
match name.as_slice() {
|
||||
"href" => node.set_enabled_state(false),
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_event(&self, event: &JSRef<Event>) {
|
||||
match self.super_type() {
|
||||
Some(s) => {
|
||||
|
|
|
@ -4,13 +4,15 @@
|
|||
|
||||
use dom::bindings::codegen::Bindings::HTMLAreaElementBinding;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLAreaElementDerived;
|
||||
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, NodeCast};
|
||||
use dom::bindings::js::{JSRef, Temporary};
|
||||
use dom::bindings::utils::{Reflectable, Reflector};
|
||||
use dom::document::Document;
|
||||
use dom::element::HTMLAreaElementTypeId;
|
||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||
use dom::htmlelement::HTMLElement;
|
||||
use dom::node::{Node, ElementNodeTypeId};
|
||||
use dom::node::{Node, NodeHelpers, ElementNodeTypeId};
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
use servo_util::str::DOMString;
|
||||
|
||||
#[deriving(Encodable)]
|
||||
|
@ -37,6 +39,39 @@ impl HTMLAreaElement {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> VirtualMethods for JSRef<'a, HTMLAreaElement> {
|
||||
fn super_type<'a>(&'a self) -> Option<&'a VirtualMethods> {
|
||||
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_ref(self);
|
||||
Some(htmlelement as &VirtualMethods)
|
||||
}
|
||||
|
||||
fn after_set_attr(&self, name: DOMString, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.after_set_attr(name.clone(), value.clone()),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
match name.as_slice() {
|
||||
"href" => node.set_enabled_state(true),
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn before_remove_attr(&self, name: DOMString, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.before_remove_attr(name.clone(), value.clone()),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
match name.as_slice() {
|
||||
"href" => node.set_enabled_state(false),
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Reflectable for HTMLAreaElement {
|
||||
fn reflector<'a>(&'a self) -> &'a Reflector {
|
||||
self.htmlelement.reflector()
|
||||
|
|
|
@ -4,15 +4,17 @@
|
|||
|
||||
use dom::bindings::codegen::Bindings::HTMLButtonElementBinding;
|
||||
use dom::bindings::codegen::Bindings::HTMLButtonElementBinding::HTMLButtonElementMethods;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLButtonElementDerived;
|
||||
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast};
|
||||
use dom::bindings::codegen::InheritTypes::{HTMLButtonElementDerived, HTMLFieldSetElementDerived};
|
||||
use dom::bindings::js::{JSRef, Temporary};
|
||||
use dom::bindings::utils::{Reflectable, Reflector};
|
||||
use dom::document::Document;
|
||||
use dom::element::HTMLButtonElementTypeId;
|
||||
use dom::element::{AttributeHandlers, Element, HTMLButtonElementTypeId};
|
||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||
use dom::htmlelement::HTMLElement;
|
||||
use dom::node::{Node, ElementNodeTypeId, window_from_node};
|
||||
use dom::node::{DisabledStateHelpers, Node, NodeHelpers, ElementNodeTypeId, window_from_node};
|
||||
use dom::validitystate::ValidityState;
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
use servo_util::str::DOMString;
|
||||
|
||||
#[deriving(Encodable)]
|
||||
|
@ -44,6 +46,82 @@ impl<'a> HTMLButtonElementMethods for JSRef<'a, HTMLButtonElement> {
|
|||
let window = window_from_node(self).root();
|
||||
ValidityState::new(&*window)
|
||||
}
|
||||
|
||||
// http://www.whatwg.org/html/#dom-fe-disabled
|
||||
fn Disabled(&self) -> bool {
|
||||
let elem: &JSRef<Element> = ElementCast::from_ref(self);
|
||||
elem.has_attribute("disabled")
|
||||
}
|
||||
|
||||
// http://www.whatwg.org/html/#dom-fe-disabled
|
||||
fn SetDisabled(&self, disabled: bool) {
|
||||
let elem: &JSRef<Element> = ElementCast::from_ref(self);
|
||||
elem.set_bool_attribute("disabled", disabled)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> VirtualMethods for JSRef<'a, HTMLButtonElement> {
|
||||
fn super_type<'a>(&'a self) -> Option<&'a VirtualMethods> {
|
||||
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_ref(self);
|
||||
Some(htmlelement as &VirtualMethods)
|
||||
}
|
||||
|
||||
fn after_set_attr(&self, name: DOMString, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.after_set_attr(name.clone(), value.clone()),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
match name.as_slice() {
|
||||
"disabled" => {
|
||||
node.set_disabled_state(true);
|
||||
node.set_enabled_state(false);
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn before_remove_attr(&self, name: DOMString, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.before_remove_attr(name.clone(), value),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
match name.as_slice() {
|
||||
"disabled" => {
|
||||
node.set_disabled_state(false);
|
||||
node.set_enabled_state(true);
|
||||
node.check_ancestors_disabled_state_for_form_control();
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn bind_to_tree(&self, tree_in_doc: bool) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.bind_to_tree(tree_in_doc),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
node.check_ancestors_disabled_state_for_form_control();
|
||||
}
|
||||
|
||||
fn unbind_from_tree(&self, tree_in_doc: bool) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.unbind_from_tree(tree_in_doc),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
if node.ancestors().any(|ancestor| ancestor.is_htmlfieldsetelement()) {
|
||||
node.check_ancestors_disabled_state_for_form_control();
|
||||
} else {
|
||||
node.check_disabled_attribute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Reflectable for HTMLButtonElement {
|
||||
|
|
|
@ -5,15 +5,18 @@
|
|||
use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding;
|
||||
use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding::HTMLFieldSetElementMethods;
|
||||
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLFieldSetElementDerived, NodeCast};
|
||||
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLLegendElementDerived};
|
||||
use dom::bindings::js::{JSRef, Temporary};
|
||||
use dom::bindings::utils::{Reflectable, Reflector};
|
||||
use dom::document::Document;
|
||||
use dom::element::{Element, HTMLFieldSetElementTypeId};
|
||||
use dom::element::{AttributeHandlers, Element, HTMLFieldSetElementTypeId, HTMLButtonElementTypeId};
|
||||
use dom::element::{HTMLInputElementTypeId, HTMLSelectElementTypeId, HTMLTextAreaElementTypeId};
|
||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||
use dom::htmlcollection::{HTMLCollection, CollectionFilter};
|
||||
use dom::htmlelement::HTMLElement;
|
||||
use dom::node::{Node, ElementNodeTypeId, window_from_node};
|
||||
use dom::node::{DisabledStateHelpers, Node, NodeHelpers, ElementNodeTypeId, window_from_node};
|
||||
use dom::validitystate::ValidityState;
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
use servo_util::str::{DOMString, StaticStringVec};
|
||||
|
||||
#[deriving(Encodable)]
|
||||
|
@ -62,6 +65,89 @@ impl<'a> HTMLFieldSetElementMethods for JSRef<'a, HTMLFieldSetElement> {
|
|||
let window = window_from_node(self).root();
|
||||
ValidityState::new(&*window)
|
||||
}
|
||||
|
||||
// http://www.whatwg.org/html/#dom-fieldset-disabled
|
||||
fn Disabled(&self) -> bool {
|
||||
let elem: &JSRef<Element> = ElementCast::from_ref(self);
|
||||
elem.has_attribute("disabled")
|
||||
}
|
||||
|
||||
// http://www.whatwg.org/html/#dom-fieldset-disabled
|
||||
fn SetDisabled(&self, disabled: bool) {
|
||||
let elem: &JSRef<Element> = ElementCast::from_ref(self);
|
||||
elem.set_bool_attribute("disabled", disabled)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> VirtualMethods for JSRef<'a, HTMLFieldSetElement> {
|
||||
fn super_type<'a>(&'a self) -> Option<&'a VirtualMethods> {
|
||||
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_ref(self);
|
||||
Some(htmlelement as &VirtualMethods)
|
||||
}
|
||||
|
||||
fn after_set_attr(&self, name: DOMString, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.after_set_attr(name.clone(), value.clone()),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
match name.as_slice() {
|
||||
"disabled" => {
|
||||
node.set_disabled_state(true);
|
||||
node.set_enabled_state(false);
|
||||
let maybe_legend = node.children().find(|node| node.is_htmllegendelement());
|
||||
let filtered: Vec<JSRef<Node>> = node.children().filter(|child| {
|
||||
maybe_legend.map_or(true, |legend| legend != *child)
|
||||
}).collect();
|
||||
for descendant in filtered.iter().flat_map(|child| child.traverse_preorder()) {
|
||||
match descendant.type_id() {
|
||||
ElementNodeTypeId(HTMLButtonElementTypeId) |
|
||||
ElementNodeTypeId(HTMLInputElementTypeId) |
|
||||
ElementNodeTypeId(HTMLSelectElementTypeId) |
|
||||
ElementNodeTypeId(HTMLTextAreaElementTypeId) => {
|
||||
descendant.set_disabled_state(true);
|
||||
descendant.set_enabled_state(false);
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn before_remove_attr(&self, name: DOMString, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.before_remove_attr(name.clone(), value),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
match name.as_slice() {
|
||||
"disabled" => {
|
||||
node.set_disabled_state(false);
|
||||
node.set_enabled_state(true);
|
||||
let maybe_legend = node.children().find(|node| node.is_htmllegendelement());
|
||||
let filtered: Vec<JSRef<Node>> = node.children().filter(|child| {
|
||||
maybe_legend.map_or(true, |legend| legend != *child)
|
||||
}).collect();
|
||||
for descendant in filtered.iter().flat_map(|child| child.traverse_preorder()) {
|
||||
match descendant.type_id() {
|
||||
ElementNodeTypeId(HTMLButtonElementTypeId) |
|
||||
ElementNodeTypeId(HTMLInputElementTypeId) |
|
||||
ElementNodeTypeId(HTMLSelectElementTypeId) |
|
||||
ElementNodeTypeId(HTMLTextAreaElementTypeId) => {
|
||||
descendant.check_disabled_attribute();
|
||||
descendant.check_ancestors_disabled_state_for_form_control();
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Reflectable for HTMLFieldSetElement {
|
||||
|
|
|
@ -3,14 +3,17 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::bindings::codegen::Bindings::HTMLInputElementBinding;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLInputElementDerived;
|
||||
use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods;
|
||||
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast};
|
||||
use dom::bindings::codegen::InheritTypes::{HTMLInputElementDerived, HTMLFieldSetElementDerived};
|
||||
use dom::bindings::js::{JSRef, Temporary};
|
||||
use dom::bindings::utils::{Reflectable, Reflector};
|
||||
use dom::document::Document;
|
||||
use dom::element::HTMLInputElementTypeId;
|
||||
use dom::element::{AttributeHandlers, Element, HTMLInputElementTypeId};
|
||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||
use dom::htmlelement::HTMLElement;
|
||||
use dom::node::{Node, ElementNodeTypeId};
|
||||
use dom::node::{DisabledStateHelpers, Node, NodeHelpers, ElementNodeTypeId};
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
use servo_util::str::DOMString;
|
||||
|
||||
#[deriving(Encodable)]
|
||||
|
@ -37,6 +40,84 @@ impl HTMLInputElement {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> HTMLInputElementMethods for JSRef<'a, HTMLInputElement> {
|
||||
// http://www.whatwg.org/html/#dom-fe-disabled
|
||||
fn Disabled(&self) -> bool {
|
||||
let elem: &JSRef<Element> = ElementCast::from_ref(self);
|
||||
elem.has_attribute("disabled")
|
||||
}
|
||||
|
||||
// http://www.whatwg.org/html/#dom-fe-disabled
|
||||
fn SetDisabled(&self, disabled: bool) {
|
||||
let elem: &JSRef<Element> = ElementCast::from_ref(self);
|
||||
elem.set_bool_attribute("disabled", disabled)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> VirtualMethods for JSRef<'a, HTMLInputElement> {
|
||||
fn super_type<'a>(&'a self) -> Option<&'a VirtualMethods> {
|
||||
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_ref(self);
|
||||
Some(htmlelement as &VirtualMethods)
|
||||
}
|
||||
|
||||
fn after_set_attr(&self, name: DOMString, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.after_set_attr(name.clone(), value.clone()),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
match name.as_slice() {
|
||||
"disabled" => {
|
||||
node.set_disabled_state(true);
|
||||
node.set_enabled_state(false);
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn before_remove_attr(&self, name: DOMString, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.before_remove_attr(name.clone(), value),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
match name.as_slice() {
|
||||
"disabled" => {
|
||||
node.set_disabled_state(false);
|
||||
node.set_enabled_state(true);
|
||||
node.check_ancestors_disabled_state_for_form_control();
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn bind_to_tree(&self, tree_in_doc: bool) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.bind_to_tree(tree_in_doc),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
node.check_ancestors_disabled_state_for_form_control();
|
||||
}
|
||||
|
||||
fn unbind_from_tree(&self, tree_in_doc: bool) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.unbind_from_tree(tree_in_doc),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
if node.ancestors().any(|ancestor| ancestor.is_htmlfieldsetelement()) {
|
||||
node.check_ancestors_disabled_state_for_form_control();
|
||||
} else {
|
||||
node.check_disabled_attribute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Reflectable for HTMLInputElement {
|
||||
fn reflector<'a>(&'a self) -> &'a Reflector {
|
||||
self.htmlelement.reflector()
|
||||
|
|
|
@ -4,13 +4,15 @@
|
|||
|
||||
use dom::bindings::codegen::Bindings::HTMLLinkElementBinding;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLLinkElementDerived;
|
||||
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, NodeCast};
|
||||
use dom::bindings::js::{JSRef, Temporary};
|
||||
use dom::bindings::utils::{Reflectable, Reflector};
|
||||
use dom::document::Document;
|
||||
use dom::element::HTMLLinkElementTypeId;
|
||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||
use dom::htmlelement::HTMLElement;
|
||||
use dom::node::{Node, ElementNodeTypeId};
|
||||
use dom::node::{Node, NodeHelpers, ElementNodeTypeId};
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
use servo_util::str::DOMString;
|
||||
|
||||
#[deriving(Encodable)]
|
||||
|
@ -37,6 +39,39 @@ impl HTMLLinkElement {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> VirtualMethods for JSRef<'a, HTMLLinkElement> {
|
||||
fn super_type<'a>(&'a self) -> Option<&'a VirtualMethods> {
|
||||
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_ref(self);
|
||||
Some(htmlelement as &VirtualMethods)
|
||||
}
|
||||
|
||||
fn after_set_attr(&self, name: DOMString, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.after_set_attr(name.clone(), value.clone()),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
match name.as_slice() {
|
||||
"href" => node.set_enabled_state(true),
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn before_remove_attr(&self, name: DOMString, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.before_remove_attr(name.clone(), value.clone()),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
match name.as_slice() {
|
||||
"href" => node.set_enabled_state(false),
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Reflectable for HTMLLinkElement {
|
||||
fn reflector<'a>(&'a self) -> &'a Reflector {
|
||||
self.htmlelement.reflector()
|
||||
|
|
|
@ -3,14 +3,17 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::bindings::codegen::Bindings::HTMLOptGroupElementBinding;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLOptGroupElementDerived;
|
||||
use dom::bindings::codegen::Bindings::HTMLOptGroupElementBinding::HTMLOptGroupElementMethods;
|
||||
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast};
|
||||
use dom::bindings::codegen::InheritTypes::{HTMLOptGroupElementDerived, HTMLOptionElementDerived};
|
||||
use dom::bindings::js::{JSRef, Temporary};
|
||||
use dom::bindings::utils::{Reflectable, Reflector};
|
||||
use dom::document::Document;
|
||||
use dom::element::HTMLOptGroupElementTypeId;
|
||||
use dom::element::{AttributeHandlers, Element, HTMLOptGroupElementTypeId};
|
||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||
use dom::htmlelement::HTMLElement;
|
||||
use dom::node::{Node, ElementNodeTypeId};
|
||||
use dom::node::{DisabledStateHelpers, Node, NodeHelpers, ElementNodeTypeId};
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
use servo_util::str::DOMString;
|
||||
|
||||
#[deriving(Encodable)]
|
||||
|
@ -37,6 +40,66 @@ impl HTMLOptGroupElement {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> HTMLOptGroupElementMethods for JSRef<'a, HTMLOptGroupElement> {
|
||||
// http://www.whatwg.org/html#dom-optgroup-disabled
|
||||
fn Disabled(&self) -> bool {
|
||||
let elem: &JSRef<Element> = ElementCast::from_ref(self);
|
||||
elem.has_attribute("disabled")
|
||||
}
|
||||
|
||||
// http://www.whatwg.org/html#dom-optgroup-disabled
|
||||
fn SetDisabled(&self, disabled: bool) {
|
||||
let elem: &JSRef<Element> = ElementCast::from_ref(self);
|
||||
elem.set_bool_attribute("disabled", disabled)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> VirtualMethods for JSRef<'a, HTMLOptGroupElement> {
|
||||
fn super_type<'a>(&'a self) -> Option<&'a VirtualMethods> {
|
||||
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_ref(self);
|
||||
Some(htmlelement as &VirtualMethods)
|
||||
}
|
||||
|
||||
fn after_set_attr(&self, name: DOMString, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.after_set_attr(name.clone(), value.clone()),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
match name.as_slice() {
|
||||
"disabled" => {
|
||||
node.set_disabled_state(true);
|
||||
node.set_enabled_state(false);
|
||||
for child in node.children().filter(|child| child.is_htmloptionelement()) {
|
||||
child.set_disabled_state(true);
|
||||
child.set_enabled_state(false);
|
||||
}
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn before_remove_attr(&self, name: DOMString, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.before_remove_attr(name.clone(), value),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
match name.as_slice() {
|
||||
"disabled" => {
|
||||
node.set_disabled_state(false);
|
||||
node.set_enabled_state(true);
|
||||
for child in node.children().filter(|child| child.is_htmloptionelement()) {
|
||||
child.check_disabled_attribute();
|
||||
}
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Reflectable for HTMLOptGroupElement {
|
||||
fn reflector<'a>(&'a self) -> &'a Reflector {
|
||||
self.htmlelement.reflector()
|
||||
|
|
|
@ -3,14 +3,17 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::bindings::codegen::Bindings::HTMLOptionElementBinding;
|
||||
use dom::bindings::codegen::Bindings::HTMLOptionElementBinding::HTMLOptionElementMethods;
|
||||
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast};
|
||||
use dom::bindings::codegen::InheritTypes::HTMLOptionElementDerived;
|
||||
use dom::bindings::js::{JSRef, Temporary};
|
||||
use dom::bindings::utils::{Reflectable, Reflector};
|
||||
use dom::document::Document;
|
||||
use dom::element::HTMLOptionElementTypeId;
|
||||
use dom::element::{AttributeHandlers, Element, HTMLOptionElementTypeId};
|
||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||
use dom::htmlelement::HTMLElement;
|
||||
use dom::node::{Node, ElementNodeTypeId};
|
||||
use dom::node::{DisabledStateHelpers, Node, NodeHelpers, ElementNodeTypeId};
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
use servo_util::str::DOMString;
|
||||
|
||||
#[deriving(Encodable)]
|
||||
|
@ -37,6 +40,84 @@ impl HTMLOptionElement {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> HTMLOptionElementMethods for JSRef<'a, HTMLOptionElement> {
|
||||
// http://www.whatwg.org/html/#dom-option-disabled
|
||||
fn Disabled(&self) -> bool {
|
||||
let elem: &JSRef<Element> = ElementCast::from_ref(self);
|
||||
elem.has_attribute("disabled")
|
||||
}
|
||||
|
||||
// http://www.whatwg.org/html/#dom-option-disabled
|
||||
fn SetDisabled(&self, disabled: bool) {
|
||||
let elem: &JSRef<Element> = ElementCast::from_ref(self);
|
||||
elem.set_bool_attribute("disabled", disabled)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> VirtualMethods for JSRef<'a, HTMLOptionElement> {
|
||||
fn super_type<'a>(&'a self) -> Option<&'a VirtualMethods> {
|
||||
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_ref(self);
|
||||
Some(htmlelement as &VirtualMethods)
|
||||
}
|
||||
|
||||
fn after_set_attr(&self, name: DOMString, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.after_set_attr(name.clone(), value.clone()),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
match name.as_slice() {
|
||||
"disabled" => {
|
||||
node.set_disabled_state(true);
|
||||
node.set_enabled_state(false);
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn before_remove_attr(&self, name: DOMString, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.before_remove_attr(name.clone(), value),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
match name.as_slice() {
|
||||
"disabled" => {
|
||||
node.set_disabled_state(false);
|
||||
node.set_enabled_state(true);
|
||||
node.check_parent_disabled_state_for_option();
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn bind_to_tree(&self, tree_in_doc: bool) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.bind_to_tree(tree_in_doc),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
node.check_parent_disabled_state_for_option();
|
||||
}
|
||||
|
||||
fn unbind_from_tree(&self, tree_in_doc: bool) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.unbind_from_tree(tree_in_doc),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
if node.parent_node().is_some() {
|
||||
node.check_parent_disabled_state_for_option();
|
||||
} else {
|
||||
node.check_disabled_attribute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Reflectable for HTMLOptionElement {
|
||||
fn reflector<'a>(&'a self) -> &'a Reflector {
|
||||
self.htmlelement.reflector()
|
||||
|
|
|
@ -4,17 +4,19 @@
|
|||
|
||||
use dom::bindings::codegen::Bindings::HTMLSelectElementBinding;
|
||||
use dom::bindings::codegen::Bindings::HTMLSelectElementBinding::HTMLSelectElementMethods;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLSelectElementDerived;
|
||||
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast};
|
||||
use dom::bindings::codegen::InheritTypes::{HTMLSelectElementDerived, HTMLFieldSetElementDerived};
|
||||
use dom::bindings::codegen::UnionTypes::HTMLElementOrLong::HTMLElementOrLong;
|
||||
use dom::bindings::codegen::UnionTypes::HTMLOptionElementOrHTMLOptGroupElement::HTMLOptionElementOrHTMLOptGroupElement;
|
||||
use dom::bindings::js::{JSRef, Temporary};
|
||||
use dom::bindings::utils::{Reflectable, Reflector};
|
||||
use dom::document::Document;
|
||||
use dom::element::HTMLSelectElementTypeId;
|
||||
use dom::element::{AttributeHandlers, Element, HTMLSelectElementTypeId};
|
||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||
use dom::htmlelement::HTMLElement;
|
||||
use dom::node::{Node, ElementNodeTypeId, window_from_node};
|
||||
use dom::node::{DisabledStateHelpers, Node, NodeHelpers, ElementNodeTypeId, window_from_node};
|
||||
use dom::validitystate::ValidityState;
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
use servo_util::str::DOMString;
|
||||
|
||||
#[deriving(Encodable)]
|
||||
|
@ -50,6 +52,82 @@ impl<'a> HTMLSelectElementMethods for JSRef<'a, HTMLSelectElement> {
|
|||
// Note: this function currently only exists for test_union.html.
|
||||
fn Add(&self, _element: HTMLOptionElementOrHTMLOptGroupElement, _before: Option<HTMLElementOrLong>) {
|
||||
}
|
||||
|
||||
// http://www.whatwg.org/html/#dom-fe-disabled
|
||||
fn Disabled(&self) -> bool {
|
||||
let elem: &JSRef<Element> = ElementCast::from_ref(self);
|
||||
elem.has_attribute("disabled")
|
||||
}
|
||||
|
||||
// http://www.whatwg.org/html/#dom-fe-disabled
|
||||
fn SetDisabled(&self, disabled: bool) {
|
||||
let elem: &JSRef<Element> = ElementCast::from_ref(self);
|
||||
elem.set_bool_attribute("disabled", disabled)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> VirtualMethods for JSRef<'a, HTMLSelectElement> {
|
||||
fn super_type<'a>(&'a self) -> Option<&'a VirtualMethods> {
|
||||
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_ref(self);
|
||||
Some(htmlelement as &VirtualMethods)
|
||||
}
|
||||
|
||||
fn after_set_attr(&self, name: DOMString, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.after_set_attr(name.clone(), value.clone()),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
match name.as_slice() {
|
||||
"disabled" => {
|
||||
node.set_disabled_state(true);
|
||||
node.set_enabled_state(false);
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn before_remove_attr(&self, name: DOMString, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.before_remove_attr(name.clone(), value),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
match name.as_slice() {
|
||||
"disabled" => {
|
||||
node.set_disabled_state(false);
|
||||
node.set_enabled_state(true);
|
||||
node.check_ancestors_disabled_state_for_form_control();
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn bind_to_tree(&self, tree_in_doc: bool) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.bind_to_tree(tree_in_doc),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
node.check_ancestors_disabled_state_for_form_control();
|
||||
}
|
||||
|
||||
fn unbind_from_tree(&self, tree_in_doc: bool) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.unbind_from_tree(tree_in_doc),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
if node.ancestors().any(|ancestor| ancestor.is_htmlfieldsetelement()) {
|
||||
node.check_ancestors_disabled_state_for_form_control();
|
||||
} else {
|
||||
node.check_disabled_attribute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Reflectable for HTMLSelectElement {
|
||||
|
|
|
@ -3,14 +3,17 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLTextAreaElementDerived;
|
||||
use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding::HTMLTextAreaElementMethods;
|
||||
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast};
|
||||
use dom::bindings::codegen::InheritTypes::{HTMLTextAreaElementDerived, HTMLFieldSetElementDerived};
|
||||
use dom::bindings::js::{JSRef, Temporary};
|
||||
use dom::bindings::utils::{Reflectable, Reflector};
|
||||
use dom::document::Document;
|
||||
use dom::element::HTMLTextAreaElementTypeId;
|
||||
use dom::element::{AttributeHandlers, Element, HTMLTextAreaElementTypeId};
|
||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||
use dom::htmlelement::HTMLElement;
|
||||
use dom::node::{Node, ElementNodeTypeId};
|
||||
use dom::node::{DisabledStateHelpers, Node, NodeHelpers, ElementNodeTypeId};
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
use servo_util::str::DOMString;
|
||||
|
||||
#[deriving(Encodable)]
|
||||
|
@ -37,6 +40,84 @@ impl HTMLTextAreaElement {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> HTMLTextAreaElementMethods for JSRef<'a, HTMLTextAreaElement> {
|
||||
// http://www.whatwg.org/html/#dom-fe-disabled
|
||||
fn Disabled(&self) -> bool {
|
||||
let elem: &JSRef<Element> = ElementCast::from_ref(self);
|
||||
elem.has_attribute("disabled")
|
||||
}
|
||||
|
||||
// http://www.whatwg.org/html/#dom-fe-disabled
|
||||
fn SetDisabled(&self, disabled: bool) {
|
||||
let elem: &JSRef<Element> = ElementCast::from_ref(self);
|
||||
elem.set_bool_attribute("disabled", disabled)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> VirtualMethods for JSRef<'a, HTMLTextAreaElement> {
|
||||
fn super_type<'a>(&'a self) -> Option<&'a VirtualMethods> {
|
||||
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_ref(self);
|
||||
Some(htmlelement as &VirtualMethods)
|
||||
}
|
||||
|
||||
fn after_set_attr(&self, name: DOMString, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.after_set_attr(name.clone(), value.clone()),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
match name.as_slice() {
|
||||
"disabled" => {
|
||||
node.set_disabled_state(true);
|
||||
node.set_enabled_state(false);
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn before_remove_attr(&self, name: DOMString, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.before_remove_attr(name.clone(), value),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
match name.as_slice() {
|
||||
"disabled" => {
|
||||
node.set_disabled_state(false);
|
||||
node.set_enabled_state(true);
|
||||
node.check_ancestors_disabled_state_for_form_control();
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn bind_to_tree(&self, tree_in_doc: bool) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.bind_to_tree(tree_in_doc),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
node.check_ancestors_disabled_state_for_form_control();
|
||||
}
|
||||
|
||||
fn unbind_from_tree(&self, tree_in_doc: bool) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.unbind_from_tree(tree_in_doc),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||
if node.ancestors().any(|ancestor| ancestor.is_htmlfieldsetelement()) {
|
||||
node.check_ancestors_disabled_state_for_form_control();
|
||||
} else {
|
||||
node.check_disabled_attribute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Reflectable for HTMLTextAreaElement {
|
||||
fn reflector<'a>(&'a self) -> &'a Reflector {
|
||||
self.htmlelement.reflector()
|
||||
|
|
|
@ -16,6 +16,8 @@ use dom::bindings::codegen::InheritTypes::{CommentCast, DocumentCast, DocumentTy
|
|||
use dom::bindings::codegen::InheritTypes::{ElementCast, TextCast, NodeCast, ElementDerived};
|
||||
use dom::bindings::codegen::InheritTypes::{CharacterDataCast, NodeBase, NodeDerived};
|
||||
use dom::bindings::codegen::InheritTypes::{ProcessingInstructionCast, EventTargetCast};
|
||||
use dom::bindings::codegen::InheritTypes::{HTMLLegendElementDerived, HTMLFieldSetElementDerived};
|
||||
use dom::bindings::codegen::InheritTypes::HTMLOptGroupElementDerived;
|
||||
use dom::bindings::error::{ErrorResult, Fallible, NotFound, HierarchyRequest, Syntax};
|
||||
use dom::bindings::global::{GlobalRef, Window};
|
||||
use dom::bindings::js::{JS, JSRef, RootedReference, Temporary, Root, OptionalUnrootable};
|
||||
|
@ -30,7 +32,10 @@ use dom::document::{Document, DocumentHelpers, HTMLDocument, NonHTMLDocument};
|
|||
use dom::documentfragment::DocumentFragment;
|
||||
use dom::documenttype::DocumentType;
|
||||
use dom::element::{AttributeHandlers, Element, ElementTypeId};
|
||||
use dom::element::{HTMLAnchorElementTypeId, ElementHelpers};
|
||||
use dom::element::{HTMLAnchorElementTypeId, HTMLButtonElementTypeId, ElementHelpers};
|
||||
use dom::element::{HTMLInputElementTypeId, HTMLSelectElementTypeId};
|
||||
use dom::element::{HTMLTextAreaElementTypeId, HTMLOptGroupElementTypeId};
|
||||
use dom::element::{HTMLOptionElementTypeId, HTMLFieldSetElementTypeId};
|
||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||
use dom::nodelist::{NodeList};
|
||||
use dom::processinginstruction::ProcessingInstruction;
|
||||
|
@ -123,8 +128,12 @@ bitflags! {
|
|||
flags NodeFlags: u8 {
|
||||
#[doc = "Specifies whether this node is in a document."]
|
||||
static IsInDoc = 0x01,
|
||||
#[doc = "Specifies whether this node is hover state for this node"]
|
||||
static InHoverState = 0x02
|
||||
#[doc = "Specifies whether this node is in hover state."]
|
||||
static InHoverState = 0x02,
|
||||
#[doc = "Specifies whether this node is in disabled state."]
|
||||
static InDisabledState = 0x04,
|
||||
#[doc = "Specifies whether this node is in enabled state."]
|
||||
static InEnabledState = 0x08
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -383,6 +392,12 @@ pub trait NodeHelpers {
|
|||
fn get_hover_state(&self) -> bool;
|
||||
fn set_hover_state(&self, state: bool);
|
||||
|
||||
fn get_disabled_state(&self) -> bool;
|
||||
fn set_disabled_state(&self, state: bool);
|
||||
|
||||
fn get_enabled_state(&self) -> bool;
|
||||
fn set_enabled_state(&self, state: bool);
|
||||
|
||||
fn dump(&self);
|
||||
fn dump_indent(&self, indent: uint);
|
||||
fn debug_str(&self) -> String;
|
||||
|
@ -500,6 +515,30 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_disabled_state(&self) -> bool {
|
||||
self.flags.deref().borrow().contains(InDisabledState)
|
||||
}
|
||||
|
||||
fn set_disabled_state(&self, state: bool) {
|
||||
if state {
|
||||
self.flags.deref().borrow_mut().insert(InDisabledState);
|
||||
} else {
|
||||
self.flags.deref().borrow_mut().remove(InDisabledState);
|
||||
}
|
||||
}
|
||||
|
||||
fn get_enabled_state(&self) -> bool {
|
||||
self.flags.deref().borrow().contains(InEnabledState)
|
||||
}
|
||||
|
||||
fn set_enabled_state(&self, state: bool) {
|
||||
if state {
|
||||
self.flags.deref().borrow_mut().insert(InEnabledState);
|
||||
} else {
|
||||
self.flags.deref().borrow_mut().remove(InEnabledState);
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterates over this node and all its descendants, in preorder.
|
||||
fn traverse_preorder<'a>(&'a self) -> TreeIterator<'a> {
|
||||
let mut nodes = vec!();
|
||||
|
@ -728,12 +767,20 @@ impl LayoutNodeHelpers for JS<Node> {
|
|||
|
||||
pub trait RawLayoutNodeHelpers {
|
||||
unsafe fn get_hover_state_for_layout(&self) -> bool;
|
||||
unsafe fn get_disabled_state_for_layout(&self) -> bool;
|
||||
unsafe fn get_enabled_state_for_layout(&self) -> bool;
|
||||
}
|
||||
|
||||
impl RawLayoutNodeHelpers for Node {
|
||||
unsafe fn get_hover_state_for_layout(&self) -> bool {
|
||||
self.flags.deref().borrow().contains(InHoverState)
|
||||
}
|
||||
unsafe fn get_disabled_state_for_layout(&self) -> bool {
|
||||
self.flags.deref().borrow().contains(InDisabledState)
|
||||
}
|
||||
unsafe fn get_enabled_state_for_layout(&self) -> bool {
|
||||
self.flags.deref().borrow().contains(InEnabledState)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -926,7 +973,7 @@ impl Node {
|
|||
}
|
||||
|
||||
fn new_(type_id: NodeTypeId, doc: Option<JSRef<Document>>) -> Node {
|
||||
Node {
|
||||
let node = Node {
|
||||
eventtarget: EventTarget::new_inherited(NodeTargetTypeId(type_id)),
|
||||
type_id: type_id,
|
||||
|
||||
|
@ -941,7 +988,22 @@ impl Node {
|
|||
flags: Traceable::new(RefCell::new(NodeFlags::new(type_id))),
|
||||
|
||||
layout_data: LayoutDataRef::new(),
|
||||
};
|
||||
match type_id {
|
||||
// The following elements are enabled by default.
|
||||
ElementNodeTypeId(HTMLButtonElementTypeId) |
|
||||
ElementNodeTypeId(HTMLInputElementTypeId) |
|
||||
ElementNodeTypeId(HTMLSelectElementTypeId) |
|
||||
ElementNodeTypeId(HTMLTextAreaElementTypeId) |
|
||||
ElementNodeTypeId(HTMLOptGroupElementTypeId) |
|
||||
ElementNodeTypeId(HTMLOptionElementTypeId) |
|
||||
//ElementNodeTypeId(HTMLMenuItemElementTypeId) |
|
||||
ElementNodeTypeId(HTMLFieldSetElementTypeId) => {
|
||||
node.flags.deref().borrow_mut().insert(InEnabledState);
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
node
|
||||
}
|
||||
|
||||
// http://dom.spec.whatwg.org/#concept-node-adopt
|
||||
|
@ -1966,3 +2028,51 @@ impl<'a> style::TNode<JSRef<'a, Element>> for JSRef<'a, Node> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait DisabledStateHelpers {
|
||||
fn check_ancestors_disabled_state_for_form_control(&self);
|
||||
fn check_parent_disabled_state_for_option(&self);
|
||||
fn check_disabled_attribute(&self);
|
||||
}
|
||||
|
||||
impl<'a> DisabledStateHelpers for JSRef<'a, Node> {
|
||||
fn check_ancestors_disabled_state_for_form_control(&self) {
|
||||
if self.get_disabled_state() { return; }
|
||||
for ancestor in self.ancestors().filter(|ancestor| ancestor.is_htmlfieldsetelement()) {
|
||||
if !ancestor.get_disabled_state() { continue; }
|
||||
if ancestor.is_parent_of(self) {
|
||||
self.set_disabled_state(true);
|
||||
self.set_enabled_state(false);
|
||||
return;
|
||||
}
|
||||
match ancestor.children().find(|child| child.is_htmllegendelement()) {
|
||||
Some(ref legend) => {
|
||||
// XXXabinader: should we save previous ancestor to avoid this iteration?
|
||||
if self.ancestors().any(|ancestor| ancestor == *legend) { continue; }
|
||||
},
|
||||
None => ()
|
||||
}
|
||||
self.set_disabled_state(true);
|
||||
self.set_enabled_state(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fn check_parent_disabled_state_for_option(&self) {
|
||||
if self.get_disabled_state() { return; }
|
||||
match self.parent_node().root() {
|
||||
Some(ref parent) if parent.is_htmloptgroupelement() && parent.get_disabled_state() => {
|
||||
self.set_disabled_state(true);
|
||||
self.set_enabled_state(false);
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn check_disabled_attribute(&self) {
|
||||
let elem: &JSRef<'a, Element> = ElementCast::to_ref(self).unwrap();
|
||||
let has_disabled_attrib = elem.has_attribute("disabled");
|
||||
self.set_disabled_state(has_disabled_attrib);
|
||||
self.set_enabled_state(!has_disabled_attrib);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,28 +5,59 @@
|
|||
use dom::attr::{AttrValue, StringAttrValue};
|
||||
use dom::bindings::codegen::InheritTypes::ElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLAnchorElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLAreaElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLBodyElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLButtonElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLCanvasElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLFieldSetElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLIFrameElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLImageElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLInputElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLLinkElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLObjectElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLOptGroupElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLOptionElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLSelectElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLStyleElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLTextAreaElementCast;
|
||||
use dom::bindings::js::JSRef;
|
||||
use dom::element::Element;
|
||||
use dom::element::{ElementTypeId, HTMLAnchorElementTypeId};
|
||||
use dom::element::{HTMLBodyElementTypeId, HTMLCanvasElementTypeId};
|
||||
use dom::element::{HTMLIFrameElementTypeId, HTMLImageElementTypeId};
|
||||
use dom::element::{HTMLObjectElementTypeId, HTMLStyleElementTypeId};
|
||||
use dom::element::ElementTypeId;
|
||||
use dom::element::HTMLAnchorElementTypeId;
|
||||
use dom::element::HTMLAreaElementTypeId;
|
||||
use dom::element::HTMLBodyElementTypeId;
|
||||
use dom::element::HTMLButtonElementTypeId;
|
||||
use dom::element::HTMLCanvasElementTypeId;
|
||||
use dom::element::HTMLFieldSetElementTypeId;
|
||||
use dom::element::HTMLIFrameElementTypeId;
|
||||
use dom::element::HTMLImageElementTypeId;
|
||||
use dom::element::HTMLInputElementTypeId;
|
||||
use dom::element::HTMLLinkElementTypeId;
|
||||
use dom::element::HTMLObjectElementTypeId;
|
||||
use dom::element::HTMLOptGroupElementTypeId;
|
||||
use dom::element::HTMLOptionElementTypeId;
|
||||
use dom::element::HTMLSelectElementTypeId;
|
||||
use dom::element::HTMLStyleElementTypeId;
|
||||
use dom::element::HTMLTextAreaElementTypeId;
|
||||
use dom::event::Event;
|
||||
use dom::htmlanchorelement::HTMLAnchorElement;
|
||||
use dom::htmlareaelement::HTMLAreaElement;
|
||||
use dom::htmlbodyelement::HTMLBodyElement;
|
||||
use dom::htmlbuttonelement::HTMLButtonElement;
|
||||
use dom::htmlcanvaselement::HTMLCanvasElement;
|
||||
use dom::htmlelement::HTMLElement;
|
||||
use dom::htmlfieldsetelement::HTMLFieldSetElement;
|
||||
use dom::htmliframeelement::HTMLIFrameElement;
|
||||
use dom::htmlimageelement::HTMLImageElement;
|
||||
use dom::htmlinputelement::HTMLInputElement;
|
||||
use dom::htmllinkelement::HTMLLinkElement;
|
||||
use dom::htmlobjectelement::HTMLObjectElement;
|
||||
use dom::htmloptgroupelement::HTMLOptGroupElement;
|
||||
use dom::htmloptionelement::HTMLOptionElement;
|
||||
use dom::htmlselectelement::HTMLSelectElement;
|
||||
use dom::htmlstyleelement::HTMLStyleElement;
|
||||
use dom::htmltextareaelement::HTMLTextAreaElement;
|
||||
use dom::node::{Node, NodeHelpers, ElementNodeTypeId};
|
||||
use servo_util::str::DOMString;
|
||||
|
||||
|
@ -111,14 +142,26 @@ pub fn vtable_for<'a>(node: &'a JSRef<Node>) -> &'a VirtualMethods {
|
|||
let element: &JSRef<HTMLAnchorElement> = HTMLAnchorElementCast::to_ref(node).unwrap();
|
||||
element as &VirtualMethods
|
||||
}
|
||||
ElementNodeTypeId(HTMLAreaElementTypeId) => {
|
||||
let element: &JSRef<HTMLAreaElement> = HTMLAreaElementCast::to_ref(node).unwrap();
|
||||
element as &VirtualMethods
|
||||
}
|
||||
ElementNodeTypeId(HTMLBodyElementTypeId) => {
|
||||
let element: &JSRef<HTMLBodyElement> = HTMLBodyElementCast::to_ref(node).unwrap();
|
||||
element as &VirtualMethods
|
||||
}
|
||||
ElementNodeTypeId(HTMLButtonElementTypeId) => {
|
||||
let element: &JSRef<HTMLButtonElement> = HTMLButtonElementCast::to_ref(node).unwrap();
|
||||
element as &VirtualMethods
|
||||
}
|
||||
ElementNodeTypeId(HTMLCanvasElementTypeId) => {
|
||||
let element: &JSRef<HTMLCanvasElement> = HTMLCanvasElementCast::to_ref(node).unwrap();
|
||||
element as &VirtualMethods
|
||||
}
|
||||
ElementNodeTypeId(HTMLFieldSetElementTypeId) => {
|
||||
let element: &JSRef<HTMLFieldSetElement> = HTMLFieldSetElementCast::to_ref(node).unwrap();
|
||||
element as &VirtualMethods
|
||||
}
|
||||
ElementNodeTypeId(HTMLImageElementTypeId) => {
|
||||
let element: &JSRef<HTMLImageElement> = HTMLImageElementCast::to_ref(node).unwrap();
|
||||
element as &VirtualMethods
|
||||
|
@ -127,14 +170,38 @@ pub fn vtable_for<'a>(node: &'a JSRef<Node>) -> &'a VirtualMethods {
|
|||
let element: &JSRef<HTMLIFrameElement> = HTMLIFrameElementCast::to_ref(node).unwrap();
|
||||
element as &VirtualMethods
|
||||
}
|
||||
ElementNodeTypeId(HTMLInputElementTypeId) => {
|
||||
let element: &JSRef<HTMLInputElement> = HTMLInputElementCast::to_ref(node).unwrap();
|
||||
element as &VirtualMethods
|
||||
}
|
||||
ElementNodeTypeId(HTMLLinkElementTypeId) => {
|
||||
let element: &JSRef<HTMLLinkElement> = HTMLLinkElementCast::to_ref(node).unwrap();
|
||||
element as &VirtualMethods
|
||||
}
|
||||
ElementNodeTypeId(HTMLObjectElementTypeId) => {
|
||||
let element: &JSRef<HTMLObjectElement> = HTMLObjectElementCast::to_ref(node).unwrap();
|
||||
element as &VirtualMethods
|
||||
}
|
||||
ElementNodeTypeId(HTMLOptGroupElementTypeId) => {
|
||||
let element: &JSRef<HTMLOptGroupElement> = HTMLOptGroupElementCast::to_ref(node).unwrap();
|
||||
element as &VirtualMethods
|
||||
}
|
||||
ElementNodeTypeId(HTMLOptionElementTypeId) => {
|
||||
let element: &JSRef<HTMLOptionElement> = HTMLOptionElementCast::to_ref(node).unwrap();
|
||||
element as &VirtualMethods
|
||||
}
|
||||
ElementNodeTypeId(HTMLSelectElementTypeId) => {
|
||||
let element: &JSRef<HTMLSelectElement> = HTMLSelectElementCast::to_ref(node).unwrap();
|
||||
element as &VirtualMethods
|
||||
}
|
||||
ElementNodeTypeId(HTMLStyleElementTypeId) => {
|
||||
let element: &JSRef<HTMLStyleElement> = HTMLStyleElementCast::to_ref(node).unwrap();
|
||||
element as &VirtualMethods
|
||||
}
|
||||
ElementNodeTypeId(HTMLTextAreaElementTypeId) => {
|
||||
let element: &JSRef<HTMLTextAreaElement> = HTMLTextAreaElementCast::to_ref(node).unwrap();
|
||||
element as &VirtualMethods
|
||||
}
|
||||
ElementNodeTypeId(ElementTypeId) => {
|
||||
let element: &JSRef<Element> = ElementCast::to_ref(node).unwrap();
|
||||
element as &VirtualMethods
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// http://www.whatwg.org/html/#htmlbuttonelement
|
||||
interface HTMLButtonElement : HTMLElement {
|
||||
// attribute boolean autofocus;
|
||||
// attribute boolean disabled;
|
||||
attribute boolean disabled;
|
||||
//readonly attribute HTMLFormElement? form;
|
||||
// attribute DOMString formAction;
|
||||
// attribute DOMString formEnctype;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
// http://www.whatwg.org/html/#htmlfieldsetelement
|
||||
interface HTMLFieldSetElement : HTMLElement {
|
||||
// attribute boolean disabled;
|
||||
attribute boolean disabled;
|
||||
//readonly attribute HTMLFormElement? form;
|
||||
// attribute DOMString name;
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ interface HTMLInputElement : HTMLElement {
|
|||
// attribute boolean defaultChecked;
|
||||
// attribute boolean checked;
|
||||
// attribute DOMString dirName;
|
||||
// attribute boolean disabled;
|
||||
attribute boolean disabled;
|
||||
//readonly attribute HTMLFormElement? form;
|
||||
//readonly attribute FileList? files;
|
||||
// attribute DOMString formAction;
|
||||
|
|
|
@ -5,6 +5,6 @@
|
|||
|
||||
// http://www.whatwg.org/html/#htmloptgroupelement
|
||||
interface HTMLOptGroupElement : HTMLElement {
|
||||
// attribute boolean disabled;
|
||||
attribute boolean disabled;
|
||||
// attribute DOMString label;
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// http://www.whatwg.org/html/#htmloptionelement
|
||||
//[NamedConstructor=Option(optional DOMString text = "", optional DOMString value, optional boolean defaultSelected = false, optional boolean selected = false)]
|
||||
interface HTMLOptionElement : HTMLElement {
|
||||
// attribute boolean disabled;
|
||||
attribute boolean disabled;
|
||||
//readonly attribute HTMLFormElement? form;
|
||||
// attribute DOMString label;
|
||||
// attribute boolean defaultSelected;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// http://www.whatwg.org/html/#htmlselectelement
|
||||
interface HTMLSelectElement : HTMLElement {
|
||||
// attribute boolean autofocus;
|
||||
// attribute boolean disabled;
|
||||
attribute boolean disabled;
|
||||
//readonly attribute HTMLFormElement? form;
|
||||
// attribute boolean multiple;
|
||||
// attribute DOMString name;
|
||||
|
|
|
@ -9,7 +9,7 @@ interface HTMLTextAreaElement : HTMLElement {
|
|||
// attribute boolean autofocus;
|
||||
// attribute unsigned long cols;
|
||||
// attribute DOMString dirName;
|
||||
// attribute boolean disabled;
|
||||
attribute boolean disabled;
|
||||
//readonly attribute HTMLFormElement? form;
|
||||
// attribute DOMString inputMode;
|
||||
// attribute long maxLength;
|
||||
|
|
|
@ -12,13 +12,14 @@ use dom::bindings::js::OptionalRootable;
|
|||
use dom::bindings::utils::Reflectable;
|
||||
use dom::bindings::utils::{wrap_for_same_compartment, pre_wrap};
|
||||
use dom::document::{Document, HTMLDocument, DocumentHelpers};
|
||||
use dom::element::{Element};
|
||||
use dom::element::{Element, HTMLButtonElementTypeId, HTMLInputElementTypeId};
|
||||
use dom::element::{HTMLSelectElementTypeId, HTMLTextAreaElementTypeId, HTMLOptionElementTypeId};
|
||||
use dom::event::{Event_, ResizeEvent, ReflowEvent, ClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent};
|
||||
use dom::event::Event;
|
||||
use dom::uievent::UIEvent;
|
||||
use dom::eventtarget::{EventTarget, EventTargetHelpers};
|
||||
use dom::node;
|
||||
use dom::node::{Node, NodeHelpers};
|
||||
use dom::node::{ElementNodeTypeId, Node, NodeHelpers};
|
||||
use dom::window::{TimerId, Window, WindowHelpers};
|
||||
use dom::xmlhttprequest::{TrustedXHRAddress, XMLHttpRequest, XHRProgress};
|
||||
use html::hubbub_html_parser::HtmlParserResult;
|
||||
|
@ -193,6 +194,24 @@ impl<'a> Drop for ScriptMemoryFailsafe<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
trait PrivateScriptTaskHelpers {
|
||||
fn click_event_filter_by_disabled_state(&self) -> bool;
|
||||
}
|
||||
|
||||
impl<'a> PrivateScriptTaskHelpers for JSRef<'a, Node> {
|
||||
fn click_event_filter_by_disabled_state(&self) -> bool {
|
||||
match self.type_id {
|
||||
ElementNodeTypeId(HTMLButtonElementTypeId) |
|
||||
ElementNodeTypeId(HTMLInputElementTypeId) |
|
||||
// ElementNodeTypeId(HTMLKeygenElementTypeId) |
|
||||
ElementNodeTypeId(HTMLOptionElementTypeId) |
|
||||
ElementNodeTypeId(HTMLSelectElementTypeId) |
|
||||
ElementNodeTypeId(HTMLTextAreaElementTypeId) if self.get_disabled_state() => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ScriptTask {
|
||||
/// Creates a new script task.
|
||||
pub fn new(id: PipelineId,
|
||||
|
@ -691,6 +710,8 @@ impl ScriptTask {
|
|||
match maybe_node {
|
||||
Some(node) => {
|
||||
debug!("clicked on {:s}", node.debug_str());
|
||||
// Prevent click event if form control element is disabled.
|
||||
if node.click_event_filter_by_disabled_state() { return; }
|
||||
match *page.frame() {
|
||||
Some(ref frame) => {
|
||||
let window = frame.window.root();
|
||||
|
|
|
@ -27,5 +27,7 @@ pub trait TElement {
|
|||
fn get_namespace<'a>(&'a self) -> &'a Namespace;
|
||||
fn get_hover_state(&self) -> bool;
|
||||
fn get_id(&self) -> Option<Atom>;
|
||||
fn get_disabled_state(&self) -> bool;
|
||||
fn get_enabled_state(&self) -> bool;
|
||||
}
|
||||
|
||||
|
|
|
@ -778,6 +778,18 @@ fn matches_simple_selector<E:TElement,
|
|||
let elem = element.as_element();
|
||||
elem.get_hover_state()
|
||||
},
|
||||
// http://www.whatwg.org/html/#selector-disabled
|
||||
Disabled => {
|
||||
*shareable = false;
|
||||
let elem = element.as_element();
|
||||
elem.get_disabled_state()
|
||||
},
|
||||
// http://www.whatwg.org/html/#selector-enabled
|
||||
Enabled => {
|
||||
*shareable = false;
|
||||
let elem = element.as_element();
|
||||
elem.get_enabled_state()
|
||||
},
|
||||
FirstChild => {
|
||||
*shareable = false;
|
||||
matches_first_child(element)
|
||||
|
|
|
@ -77,6 +77,8 @@ pub enum SimpleSelector {
|
|||
Link,
|
||||
Visited,
|
||||
Hover,
|
||||
Disabled,
|
||||
Enabled,
|
||||
FirstChild, LastChild, OnlyChild,
|
||||
// Empty,
|
||||
Root,
|
||||
|
@ -218,7 +220,7 @@ fn compute_specificity(mut selector: &CompoundSelector,
|
|||
&ClassSelector(..)
|
||||
| &AttrExists(..) | &AttrEqual(..) | &AttrIncludes(..) | &AttrDashMatch(..)
|
||||
| &AttrPrefixMatch(..) | &AttrSubstringMatch(..) | &AttrSuffixMatch(..)
|
||||
| &AnyLink | &Link | &Visited | &Hover
|
||||
| &AnyLink | &Link | &Visited | &Hover | &Disabled | &Enabled
|
||||
| &FirstChild | &LastChild | &OnlyChild | &Root
|
||||
// | &Empty | &Lang(*)
|
||||
| &NthChild(..) | &NthLastChild(..)
|
||||
|
@ -479,6 +481,8 @@ fn parse_simple_pseudo_class(name: &str) -> Option<SimpleSelector> {
|
|||
"link" => Some(Link),
|
||||
"visited" => Some(Visited),
|
||||
"hover" => Some(Hover),
|
||||
"disabled" => Some(Disabled),
|
||||
"enabled" => Some(Enabled),
|
||||
"first-child" => Some(FirstChild),
|
||||
"last-child" => Some(LastChild),
|
||||
"only-child" => Some(OnlyChild),
|
||||
|
|
|
@ -55,6 +55,15 @@ function should_not_throw(f) {
|
|||
}
|
||||
}
|
||||
|
||||
function check_selector(elem, selector, matches) {
|
||||
is(elem.matches(selector), matches);
|
||||
}
|
||||
|
||||
function check_disabled_selector(elem, disabled) {
|
||||
check_selector(elem, ":disabled", disabled);
|
||||
check_selector(elem, ":enabled", !disabled);
|
||||
}
|
||||
|
||||
var _test_complete = false;
|
||||
var _test_timeout = 10000; //10 seconds
|
||||
function finish() {
|
||||
|
|
181
src/test/content/test_enabled_disabled_selectors.html
Normal file
181
src/test/content/test_enabled_disabled_selectors.html
Normal file
|
@ -0,0 +1,181 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Tests for :enabled and :disabled selectors</title>
|
||||
<script src="harness.js"></script>
|
||||
<script>
|
||||
{ // Simple initialization checks.
|
||||
var list, i, elem;
|
||||
|
||||
// Examples of elements which are never :enabled or :disabled.
|
||||
list = ['div', 'p', 'body', 'head', 'span'];
|
||||
for(i = 0; i < list.length; i++) {
|
||||
elem = document.createElement(list[i]);
|
||||
check_selector(elem, ":enabled", false);
|
||||
check_selector(elem, ":disabled", false);
|
||||
}
|
||||
|
||||
// Anchor, Area and Link are :enabled with an href, but never :disabled.
|
||||
list = ["a", "area", "link"];
|
||||
for(i = 0; i < list.length; i++) {
|
||||
elem = document.createElement(list[i]);
|
||||
check_selector(elem, ":enabled", false);
|
||||
check_selector(elem, ":disabled", false);
|
||||
elem.setAttribute("href", "");
|
||||
check_selector(elem, ":enabled", true);
|
||||
check_selector(elem, ":disabled", false);
|
||||
}
|
||||
|
||||
// These are :enabled (and not :disabled) by default.
|
||||
// XXX: Add 'menuitem' here whenever available.
|
||||
list = ['button', 'input', 'select', 'textarea', 'optgroup', 'option', 'fieldset'];
|
||||
for(i = 0; i < list.length; i++) {
|
||||
elem = document.createElement(list[i]);
|
||||
check_disabled_selector(elem, false);
|
||||
}
|
||||
}
|
||||
|
||||
{ // Document elements tests.
|
||||
var click_count = 0;
|
||||
var click_event = new Event('click', {bubbles: true, cancelable: true});
|
||||
var list, elem1, elem2, elem3, elem4, elem5;
|
||||
|
||||
function on_click(ev) { click_count++; }
|
||||
|
||||
list = ['button', 'input', 'option', 'select', 'textarea'];
|
||||
for(i = 0; i < list.length; i++) {
|
||||
click_count = 0;
|
||||
|
||||
elem1 = document.getElementById(list[i] + "-1");
|
||||
is(elem1.disabled, false);
|
||||
|
||||
elem1.addEventListener('click', on_click);
|
||||
elem1.dispatchEvent(click_event);
|
||||
is(click_count, 1);
|
||||
|
||||
elem2 = document.getElementById(list[i] + "-2");
|
||||
is(elem2.disabled, true);
|
||||
|
||||
// Only user-generated click events are prevented.
|
||||
elem2.addEventListener('click', on_click);
|
||||
elem2.dispatchEvent(click_event);
|
||||
is(click_count, 2);
|
||||
|
||||
// This should look disabled, though - missing UA's CSS for :disabled?
|
||||
elem3 = document.getElementById(list[i] + "-3");
|
||||
is(elem3.disabled, false);
|
||||
|
||||
if (list[i] == 'option') { continue; }
|
||||
|
||||
elem4 = document.getElementById(list[i] + "-4");
|
||||
is(elem4.disabled, false);
|
||||
|
||||
// This should look disabled, though - missing UA's CSS for :disabled?
|
||||
elem5 = document.getElementById(list[i] + "-5");
|
||||
is(elem5.disabled, false);
|
||||
}
|
||||
}
|
||||
|
||||
{ // JS tests (Button, Input, Select, TextArea).
|
||||
var list = ['button', 'input', 'select', 'textarea'];
|
||||
var fieldset = document.createElement("fieldset");
|
||||
fieldset.disabled = true;
|
||||
var div = document.createElement("div");
|
||||
var elem;
|
||||
|
||||
for(i = 0; i < list.length; i++) {
|
||||
elem = document.createElement(list[i]);
|
||||
check_disabled_selector(elem, false);
|
||||
|
||||
div.appendChild(elem);
|
||||
check_disabled_selector(elem, false);
|
||||
|
||||
fieldset.appendChild(div);
|
||||
check_disabled_selector(elem, true);
|
||||
|
||||
document.body.appendChild(fieldset);
|
||||
check_disabled_selector(elem, true);
|
||||
|
||||
document.body.removeChild(fieldset);
|
||||
check_disabled_selector(elem, true);
|
||||
|
||||
fieldset.removeChild(div);
|
||||
check_disabled_selector(elem, false);
|
||||
|
||||
div.removeChild(elem);
|
||||
check_disabled_selector(elem, false);
|
||||
}
|
||||
}
|
||||
|
||||
{ // JS tests (Option).
|
||||
var optgroup = document.createElement("optgroup");
|
||||
optgroup.disabled = true;
|
||||
|
||||
var option = document.createElement("option");
|
||||
check_disabled_selector(option, false);
|
||||
|
||||
optgroup.appendChild(option);
|
||||
check_disabled_selector(option, true);
|
||||
|
||||
document.body.appendChild(optgroup);
|
||||
check_disabled_selector(option, true);
|
||||
|
||||
document.body.removeChild(optgroup);
|
||||
check_disabled_selector(option, true);
|
||||
|
||||
optgroup.removeChild(option);
|
||||
check_disabled_selector(option, false);
|
||||
}
|
||||
|
||||
finish();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<button id="button-1"></button>
|
||||
<button id="button-2" disabled></button>
|
||||
|
||||
<input id="input-1"></input>
|
||||
<input id="input-2" disabled></input>
|
||||
|
||||
<option id="option-1"></option>
|
||||
<option id="option-2" disabled></option>
|
||||
|
||||
<select id="select-1"></select>
|
||||
<select id="select-2" disabled></select>
|
||||
|
||||
<textarea id="textarea-1"></textarea>
|
||||
<textarea id="textarea-2" disabled></textarea>
|
||||
|
||||
<optgroup disabled>
|
||||
<option id="option-3"></option>
|
||||
</optgroup>
|
||||
|
||||
<fieldset disabled>
|
||||
<fieldset>
|
||||
<button id="button-3"></button>
|
||||
<input id="input-3"></input>
|
||||
<select id="select-3"></select>
|
||||
<textarea id="textarea-3"></textarea>
|
||||
</fieldset>
|
||||
</fieldset>
|
||||
|
||||
<fieldset disabled>
|
||||
<legend>
|
||||
<button id="button-4"></button>
|
||||
<input id="input-4"></input>
|
||||
<select id="select-4"></select>
|
||||
<textarea id="textarea-4"></textarea>
|
||||
</legend>
|
||||
</fieldset>
|
||||
|
||||
<fieldset disabled>
|
||||
<legend></legend>
|
||||
<legend>
|
||||
<button id="button-5"></button>
|
||||
<input id="input-5"></input>
|
||||
<select id="select-5"></select>
|
||||
<textarea id="textarea-5"></textarea>
|
||||
</legend>
|
||||
</fieldset>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue