From 7771350898ae1dd8e81dd1863da431e8cc7486e3 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Fri, 27 Jun 2014 15:25:09 -0400 Subject: [PATCH 01/13] Implement support for :disabled CSS selector --- src/components/layout/wrapper.rs | 6 ++ src/components/script/dom/element.rs | 27 ++++++++- src/components/script/dom/node.rs | 71 ++++++++++++++++++++++- src/components/script/script_task.rs | 25 +++++++- src/components/style/node.rs | 1 + src/components/style/selector_matching.rs | 6 ++ src/components/style/selectors.rs | 4 +- 7 files changed, 134 insertions(+), 6 deletions(-) diff --git a/src/components/layout/wrapper.rs b/src/components/layout/wrapper.rs index b0ecbbcd2fd..026857d9ad7 100644 --- a/src/components/layout/wrapper.rs +++ b/src/components/layout/wrapper.rs @@ -398,6 +398,12 @@ impl<'le> TElement for LayoutElement<'le> { fn get_id(&self) -> Option { 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_content(content_list: &content::T) -> String { diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs index 04d9603bdb6..a95d1ff8cc1 100644 --- a/src/components/script/dom/element.rs +++ b/src/components/script/dom/element.rs @@ -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,8 @@ impl<'a> style::TElement for JSRef<'a, Element> { } }) } + fn get_disabled_state(&self) -> bool { + let node: &JSRef = NodeCast::from_ref(self); + node.get_disabled_state() + } } diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index a73c4d7e879..425d3b95ef5 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -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}; @@ -123,8 +125,10 @@ 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 } } @@ -383,6 +387,9 @@ 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 dump(&self); fn dump_indent(&self, indent: uint); fn debug_str(&self) -> String; @@ -500,6 +507,18 @@ 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); + } + } + /// Iterates over this node and all its descendants, in preorder. fn traverse_preorder<'a>(&'a self) -> TreeIterator<'a> { let mut nodes = vec!(); @@ -728,12 +747,16 @@ impl LayoutNodeHelpers for JS { pub trait RawLayoutNodeHelpers { unsafe fn get_hover_state_for_layout(&self) -> bool; + unsafe fn get_disabled_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) + } } @@ -1966,3 +1989,47 @@ impl<'a> style::TNode> 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); + 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); + 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); + }, + _ => () + } + } + + 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); + } +} diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index 9b31c8b0dfc..5c6ade2b939 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -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(); diff --git a/src/components/style/node.rs b/src/components/style/node.rs index 62c588dffd4..b98d9651fca 100644 --- a/src/components/style/node.rs +++ b/src/components/style/node.rs @@ -27,5 +27,6 @@ pub trait TElement { fn get_namespace<'a>(&'a self) -> &'a Namespace; fn get_hover_state(&self) -> bool; fn get_id(&self) -> Option; + fn get_disabled_state(&self) -> bool; } diff --git a/src/components/style/selector_matching.rs b/src/components/style/selector_matching.rs index 133c7dd65be..5a2b3798ff9 100644 --- a/src/components/style/selector_matching.rs +++ b/src/components/style/selector_matching.rs @@ -778,6 +778,12 @@ fn matches_simple_selector { + *shareable = false; + let elem = element.as_element(); + elem.get_disabled_state() + }, FirstChild => { *shareable = false; matches_first_child(element) diff --git a/src/components/style/selectors.rs b/src/components/style/selectors.rs index 8eadd371086..c1d7bf0b892 100644 --- a/src/components/style/selectors.rs +++ b/src/components/style/selectors.rs @@ -77,6 +77,7 @@ pub enum SimpleSelector { Link, Visited, Hover, + Disabled, FirstChild, LastChild, OnlyChild, // Empty, Root, @@ -218,7 +219,7 @@ fn compute_specificity(mut selector: &CompoundSelector, &ClassSelector(..) | &AttrExists(..) | &AttrEqual(..) | &AttrIncludes(..) | &AttrDashMatch(..) | &AttrPrefixMatch(..) | &AttrSubstringMatch(..) | &AttrSuffixMatch(..) - | &AnyLink | &Link | &Visited | &Hover + | &AnyLink | &Link | &Visited | &Hover | &Disabled | &FirstChild | &LastChild | &OnlyChild | &Root // | &Empty | &Lang(*) | &NthChild(..) | &NthLastChild(..) @@ -479,6 +480,7 @@ fn parse_simple_pseudo_class(name: &str) -> Option { "link" => Some(Link), "visited" => Some(Visited), "hover" => Some(Hover), + "disabled" => Some(Disabled), "first-child" => Some(FirstChild), "last-child" => Some(LastChild), "only-child" => Some(OnlyChild), From 10a20e69fd51a734b71db0203601308da7712c96 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Fri, 27 Jun 2014 16:06:27 -0400 Subject: [PATCH 02/13] Implement support for :enabled CSS selector --- src/components/layout/wrapper.rs | 6 +++ src/components/script/dom/element.rs | 4 ++ src/components/script/dom/node.rs | 49 +++++++++++++++++++++-- src/components/style/node.rs | 1 + src/components/style/selector_matching.rs | 6 +++ src/components/style/selectors.rs | 4 +- 6 files changed, 66 insertions(+), 4 deletions(-) diff --git a/src/components/layout/wrapper.rs b/src/components/layout/wrapper.rs index 026857d9ad7..9d1884579da 100644 --- a/src/components/layout/wrapper.rs +++ b/src/components/layout/wrapper.rs @@ -404,6 +404,12 @@ impl<'le> TElement for LayoutElement<'le> { 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 { diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs index a95d1ff8cc1..354d6a66a1b 100644 --- a/src/components/script/dom/element.rs +++ b/src/components/script/dom/element.rs @@ -950,4 +950,8 @@ impl<'a> style::TElement for JSRef<'a, Element> { let node: &JSRef = NodeCast::from_ref(self); node.get_disabled_state() } + fn get_enabled_state(&self) -> bool { + let node: &JSRef = NodeCast::from_ref(self); + node.get_enabled_state() + } } diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index 425d3b95ef5..8b9f6ce3061 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -32,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; @@ -128,7 +131,9 @@ bitflags! { #[doc = "Specifies whether this node is in hover state."] static InHoverState = 0x02, #[doc = "Specifies whether this node is in disabled state."] - static InDisabledState = 0x04 + static InDisabledState = 0x04, + #[doc = "Specifies whether this node is in enabled state."] + static InEnabledState = 0x08 } } @@ -390,6 +395,9 @@ pub trait NodeHelpers { 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; @@ -519,6 +527,18 @@ impl<'a> NodeHelpers for JSRef<'a, Node> { } } + 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!(); @@ -748,6 +768,7 @@ impl LayoutNodeHelpers for JS { 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 { @@ -757,6 +778,9 @@ impl RawLayoutNodeHelpers for Node { 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) + } } @@ -949,7 +973,7 @@ impl Node { } fn new_(type_id: NodeTypeId, doc: Option>) -> Node { - Node { + let node = Node { eventtarget: EventTarget::new_inherited(NodeTargetTypeId(type_id)), type_id: type_id, @@ -964,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 @@ -2003,6 +2042,7 @@ impl<'a> DisabledStateHelpers for JSRef<'a, Node> { 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()) { @@ -2013,6 +2053,7 @@ impl<'a> DisabledStateHelpers for JSRef<'a, Node> { None => () } self.set_disabled_state(true); + self.set_enabled_state(false); return; } } @@ -2022,6 +2063,7 @@ impl<'a> DisabledStateHelpers for JSRef<'a, Node> { 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); }, _ => () } @@ -2031,5 +2073,6 @@ impl<'a> DisabledStateHelpers for JSRef<'a, Node> { 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); } } diff --git a/src/components/style/node.rs b/src/components/style/node.rs index b98d9651fca..9e8da53100a 100644 --- a/src/components/style/node.rs +++ b/src/components/style/node.rs @@ -28,5 +28,6 @@ pub trait TElement { fn get_hover_state(&self) -> bool; fn get_id(&self) -> Option; fn get_disabled_state(&self) -> bool; + fn get_enabled_state(&self) -> bool; } diff --git a/src/components/style/selector_matching.rs b/src/components/style/selector_matching.rs index 5a2b3798ff9..2ca288f2f6c 100644 --- a/src/components/style/selector_matching.rs +++ b/src/components/style/selector_matching.rs @@ -784,6 +784,12 @@ fn matches_simple_selector { + *shareable = false; + let elem = element.as_element(); + elem.get_enabled_state() + }, FirstChild => { *shareable = false; matches_first_child(element) diff --git a/src/components/style/selectors.rs b/src/components/style/selectors.rs index c1d7bf0b892..e18ad0556a9 100644 --- a/src/components/style/selectors.rs +++ b/src/components/style/selectors.rs @@ -78,6 +78,7 @@ pub enum SimpleSelector { Visited, Hover, Disabled, + Enabled, FirstChild, LastChild, OnlyChild, // Empty, Root, @@ -219,7 +220,7 @@ fn compute_specificity(mut selector: &CompoundSelector, &ClassSelector(..) | &AttrExists(..) | &AttrEqual(..) | &AttrIncludes(..) | &AttrDashMatch(..) | &AttrPrefixMatch(..) | &AttrSubstringMatch(..) | &AttrSuffixMatch(..) - | &AnyLink | &Link | &Visited | &Hover | &Disabled + | &AnyLink | &Link | &Visited | &Hover | &Disabled | &Enabled | &FirstChild | &LastChild | &OnlyChild | &Root // | &Empty | &Lang(*) | &NthChild(..) | &NthLastChild(..) @@ -481,6 +482,7 @@ fn parse_simple_pseudo_class(name: &str) -> Option { "visited" => Some(Visited), "hover" => Some(Hover), "disabled" => Some(Disabled), + "enabled" => Some(Enabled), "first-child" => Some(FirstChild), "last-child" => Some(LastChild), "only-child" => Some(OnlyChild), From 2017ffce375d0f4666d5afb36a9174c5ee96adfa Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Fri, 27 Jun 2014 16:13:55 -0400 Subject: [PATCH 03/13] Implement support for 'disabled' property in HTMLButtonElement --- .../script/dom/htmlbuttonelement.rs | 84 ++++++++++++++++++- src/components/script/dom/virtualmethods.rs | 19 ++++- .../dom/webidls/HTMLButtonElement.webidl | 2 +- 3 files changed, 97 insertions(+), 8 deletions(-) diff --git a/src/components/script/dom/htmlbuttonelement.rs b/src/components/script/dom/htmlbuttonelement.rs index 4e89545737b..d0fb4bb16a6 100644 --- a/src/components/script/dom/htmlbuttonelement.rs +++ b/src/components/script/dom/htmlbuttonelement.rs @@ -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 = ElementCast::from_ref(self); + elem.has_attribute("disabled") + } + + // http://www.whatwg.org/html/#dom-fe-disabled + fn SetDisabled(&self, disabled: bool) { + let elem: &JSRef = 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 = 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 = 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 = 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 = 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 = 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 { diff --git a/src/components/script/dom/virtualmethods.rs b/src/components/script/dom/virtualmethods.rs index 042420d7479..df618c7a8ff 100644 --- a/src/components/script/dom/virtualmethods.rs +++ b/src/components/script/dom/virtualmethods.rs @@ -6,6 +6,7 @@ use dom::attr::{AttrValue, StringAttrValue}; use dom::bindings::codegen::InheritTypes::ElementCast; use dom::bindings::codegen::InheritTypes::HTMLAnchorElementCast; 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::HTMLIFrameElementCast; @@ -14,13 +15,19 @@ use dom::bindings::codegen::InheritTypes::HTMLObjectElementCast; use dom::bindings::codegen::InheritTypes::HTMLStyleElementCast; 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::HTMLBodyElementTypeId; +use dom::element::HTMLButtonElementTypeId; +use dom::element::HTMLCanvasElementTypeId; +use dom::element::HTMLIFrameElementTypeId; +use dom::element::HTMLImageElementTypeId; +use dom::element::HTMLObjectElementTypeId; +use dom::element::HTMLStyleElementTypeId; use dom::event::Event; use dom::htmlanchorelement::HTMLAnchorElement; use dom::htmlbodyelement::HTMLBodyElement; +use dom::htmlbuttonelement::HTMLButtonElement; use dom::htmlcanvaselement::HTMLCanvasElement; use dom::htmlelement::HTMLElement; use dom::htmliframeelement::HTMLIFrameElement; @@ -115,6 +122,10 @@ pub fn vtable_for<'a>(node: &'a JSRef) -> &'a VirtualMethods { let element: &JSRef = HTMLBodyElementCast::to_ref(node).unwrap(); element as &VirtualMethods } + ElementNodeTypeId(HTMLButtonElementTypeId) => { + let element: &JSRef = HTMLButtonElementCast::to_ref(node).unwrap(); + element as &VirtualMethods + } ElementNodeTypeId(HTMLCanvasElementTypeId) => { let element: &JSRef = HTMLCanvasElementCast::to_ref(node).unwrap(); element as &VirtualMethods diff --git a/src/components/script/dom/webidls/HTMLButtonElement.webidl b/src/components/script/dom/webidls/HTMLButtonElement.webidl index 6425ed3e119..ad21e11370f 100644 --- a/src/components/script/dom/webidls/HTMLButtonElement.webidl +++ b/src/components/script/dom/webidls/HTMLButtonElement.webidl @@ -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; From c257a2e8ad1bd542b04bcfaa5209c26c8aaab514 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Fri, 27 Jun 2014 16:16:31 -0400 Subject: [PATCH 04/13] Implement support for 'disabled' property in HTMLFieldSetElement --- .../script/dom/htmlfieldsetelement.rs | 90 ++++++++++++++++++- src/components/script/dom/virtualmethods.rs | 7 ++ .../dom/webidls/HTMLFieldSetElement.webidl | 2 +- 3 files changed, 96 insertions(+), 3 deletions(-) diff --git a/src/components/script/dom/htmlfieldsetelement.rs b/src/components/script/dom/htmlfieldsetelement.rs index eed51e9a86a..73001d56ddd 100644 --- a/src/components/script/dom/htmlfieldsetelement.rs +++ b/src/components/script/dom/htmlfieldsetelement.rs @@ -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 = ElementCast::from_ref(self); + elem.has_attribute("disabled") + } + + // http://www.whatwg.org/html/#dom-fieldset-disabled + fn SetDisabled(&self, disabled: bool) { + let elem: &JSRef = 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 = 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 = 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> = 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 = 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> = 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 { diff --git a/src/components/script/dom/virtualmethods.rs b/src/components/script/dom/virtualmethods.rs index df618c7a8ff..75c77cf2148 100644 --- a/src/components/script/dom/virtualmethods.rs +++ b/src/components/script/dom/virtualmethods.rs @@ -9,6 +9,7 @@ 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::HTMLObjectElementCast; @@ -20,6 +21,7 @@ use dom::element::HTMLAnchorElementTypeId; 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::HTMLObjectElementTypeId; @@ -30,6 +32,7 @@ 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::htmlobjectelement::HTMLObjectElement; @@ -130,6 +133,10 @@ pub fn vtable_for<'a>(node: &'a JSRef) -> &'a VirtualMethods { let element: &JSRef = HTMLCanvasElementCast::to_ref(node).unwrap(); element as &VirtualMethods } + ElementNodeTypeId(HTMLFieldSetElementTypeId) => { + let element: &JSRef = HTMLFieldSetElementCast::to_ref(node).unwrap(); + element as &VirtualMethods + } ElementNodeTypeId(HTMLImageElementTypeId) => { let element: &JSRef = HTMLImageElementCast::to_ref(node).unwrap(); element as &VirtualMethods diff --git a/src/components/script/dom/webidls/HTMLFieldSetElement.webidl b/src/components/script/dom/webidls/HTMLFieldSetElement.webidl index f854cd23bab..6b64c60bd21 100644 --- a/src/components/script/dom/webidls/HTMLFieldSetElement.webidl +++ b/src/components/script/dom/webidls/HTMLFieldSetElement.webidl @@ -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; From 4e37b3c8c7d9288161ff0aec0b35aad72d43275e Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Fri, 27 Jun 2014 16:18:33 -0400 Subject: [PATCH 05/13] Implement support for 'disabled' property in HTMLInputElement --- src/components/script/dom/htmlinputelement.rs | 87 ++++++++++++++++++- src/components/script/dom/virtualmethods.rs | 7 ++ .../dom/webidls/HTMLInputElement.webidl | 2 +- 3 files changed, 92 insertions(+), 4 deletions(-) diff --git a/src/components/script/dom/htmlinputelement.rs b/src/components/script/dom/htmlinputelement.rs index 1209fa11619..9701ef384be 100644 --- a/src/components/script/dom/htmlinputelement.rs +++ b/src/components/script/dom/htmlinputelement.rs @@ -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 = ElementCast::from_ref(self); + elem.has_attribute("disabled") + } + + // http://www.whatwg.org/html/#dom-fe-disabled + fn SetDisabled(&self, disabled: bool) { + let elem: &JSRef = 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 = 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 = 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 = 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 = 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 = 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() diff --git a/src/components/script/dom/virtualmethods.rs b/src/components/script/dom/virtualmethods.rs index 75c77cf2148..80440f68af0 100644 --- a/src/components/script/dom/virtualmethods.rs +++ b/src/components/script/dom/virtualmethods.rs @@ -12,6 +12,7 @@ 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::HTMLObjectElementCast; use dom::bindings::codegen::InheritTypes::HTMLStyleElementCast; use dom::bindings::js::JSRef; @@ -24,6 +25,7 @@ use dom::element::HTMLCanvasElementTypeId; use dom::element::HTMLFieldSetElementTypeId; use dom::element::HTMLIFrameElementTypeId; use dom::element::HTMLImageElementTypeId; +use dom::element::HTMLInputElementTypeId; use dom::element::HTMLObjectElementTypeId; use dom::element::HTMLStyleElementTypeId; use dom::event::Event; @@ -35,6 +37,7 @@ use dom::htmlelement::HTMLElement; use dom::htmlfieldsetelement::HTMLFieldSetElement; use dom::htmliframeelement::HTMLIFrameElement; use dom::htmlimageelement::HTMLImageElement; +use dom::htmlinputelement::HTMLInputElement; use dom::htmlobjectelement::HTMLObjectElement; use dom::htmlstyleelement::HTMLStyleElement; use dom::node::{Node, NodeHelpers, ElementNodeTypeId}; @@ -145,6 +148,10 @@ pub fn vtable_for<'a>(node: &'a JSRef) -> &'a VirtualMethods { let element: &JSRef = HTMLIFrameElementCast::to_ref(node).unwrap(); element as &VirtualMethods } + ElementNodeTypeId(HTMLInputElementTypeId) => { + let element: &JSRef = HTMLInputElementCast::to_ref(node).unwrap(); + element as &VirtualMethods + } ElementNodeTypeId(HTMLObjectElementTypeId) => { let element: &JSRef = HTMLObjectElementCast::to_ref(node).unwrap(); element as &VirtualMethods diff --git a/src/components/script/dom/webidls/HTMLInputElement.webidl b/src/components/script/dom/webidls/HTMLInputElement.webidl index 256cc814cff..1caa9137e0b 100644 --- a/src/components/script/dom/webidls/HTMLInputElement.webidl +++ b/src/components/script/dom/webidls/HTMLInputElement.webidl @@ -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; From 1e52a5afb8cdd702493c93e8c9d2a8ca55f2ec36 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Fri, 27 Jun 2014 16:21:44 -0400 Subject: [PATCH 06/13] Implement support for 'disabled' property in HTMLOptGroupElement --- .../script/dom/htmloptgroupelement.rs | 69 ++++++++++++++++++- src/components/script/dom/virtualmethods.rs | 7 ++ .../dom/webidls/HTMLOptGroupElement.webidl | 2 +- 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/src/components/script/dom/htmloptgroupelement.rs b/src/components/script/dom/htmloptgroupelement.rs index 8f3be20a432..4eda6938610 100644 --- a/src/components/script/dom/htmloptgroupelement.rs +++ b/src/components/script/dom/htmloptgroupelement.rs @@ -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 = ElementCast::from_ref(self); + elem.has_attribute("disabled") + } + + // http://www.whatwg.org/html#dom-optgroup-disabled + fn SetDisabled(&self, disabled: bool) { + let elem: &JSRef = 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 = 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 = 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 = 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() diff --git a/src/components/script/dom/virtualmethods.rs b/src/components/script/dom/virtualmethods.rs index 80440f68af0..d58b2aa3ba2 100644 --- a/src/components/script/dom/virtualmethods.rs +++ b/src/components/script/dom/virtualmethods.rs @@ -14,6 +14,7 @@ use dom::bindings::codegen::InheritTypes::HTMLIFrameElementCast; use dom::bindings::codegen::InheritTypes::HTMLImageElementCast; use dom::bindings::codegen::InheritTypes::HTMLInputElementCast; use dom::bindings::codegen::InheritTypes::HTMLObjectElementCast; +use dom::bindings::codegen::InheritTypes::HTMLOptGroupElementCast; use dom::bindings::codegen::InheritTypes::HTMLStyleElementCast; use dom::bindings::js::JSRef; use dom::element::Element; @@ -27,6 +28,7 @@ use dom::element::HTMLIFrameElementTypeId; use dom::element::HTMLImageElementTypeId; use dom::element::HTMLInputElementTypeId; use dom::element::HTMLObjectElementTypeId; +use dom::element::HTMLOptGroupElementTypeId; use dom::element::HTMLStyleElementTypeId; use dom::event::Event; use dom::htmlanchorelement::HTMLAnchorElement; @@ -39,6 +41,7 @@ use dom::htmliframeelement::HTMLIFrameElement; use dom::htmlimageelement::HTMLImageElement; use dom::htmlinputelement::HTMLInputElement; use dom::htmlobjectelement::HTMLObjectElement; +use dom::htmloptgroupelement::HTMLOptGroupElement; use dom::htmlstyleelement::HTMLStyleElement; use dom::node::{Node, NodeHelpers, ElementNodeTypeId}; use servo_util::str::DOMString; @@ -156,6 +159,10 @@ pub fn vtable_for<'a>(node: &'a JSRef) -> &'a VirtualMethods { let element: &JSRef = HTMLObjectElementCast::to_ref(node).unwrap(); element as &VirtualMethods } + ElementNodeTypeId(HTMLOptGroupElementTypeId) => { + let element: &JSRef = HTMLOptGroupElementCast::to_ref(node).unwrap(); + element as &VirtualMethods + } ElementNodeTypeId(HTMLStyleElementTypeId) => { let element: &JSRef = HTMLStyleElementCast::to_ref(node).unwrap(); element as &VirtualMethods diff --git a/src/components/script/dom/webidls/HTMLOptGroupElement.webidl b/src/components/script/dom/webidls/HTMLOptGroupElement.webidl index e5831d1df78..13646f00ab1 100644 --- a/src/components/script/dom/webidls/HTMLOptGroupElement.webidl +++ b/src/components/script/dom/webidls/HTMLOptGroupElement.webidl @@ -5,6 +5,6 @@ // http://www.whatwg.org/html/#htmloptgroupelement interface HTMLOptGroupElement : HTMLElement { - // attribute boolean disabled; + attribute boolean disabled; // attribute DOMString label; }; From cad5f990d190301f4759a855c0a5a421a11c1060 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Fri, 27 Jun 2014 16:34:02 -0400 Subject: [PATCH 07/13] Implement support for 'disabled' property in HTMLOptionElement --- .../script/dom/htmloptionelement.rs | 85 ++++++++++++++++++- src/components/script/dom/virtualmethods.rs | 7 ++ .../dom/webidls/HTMLOptionElement.webidl | 2 +- 3 files changed, 91 insertions(+), 3 deletions(-) diff --git a/src/components/script/dom/htmloptionelement.rs b/src/components/script/dom/htmloptionelement.rs index 68b1422412a..a0c4f9e4067 100644 --- a/src/components/script/dom/htmloptionelement.rs +++ b/src/components/script/dom/htmloptionelement.rs @@ -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 = ElementCast::from_ref(self); + elem.has_attribute("disabled") + } + + // http://www.whatwg.org/html/#dom-option-disabled + fn SetDisabled(&self, disabled: bool) { + let elem: &JSRef = 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 = 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 = 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 = 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 = 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 = 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() diff --git a/src/components/script/dom/virtualmethods.rs b/src/components/script/dom/virtualmethods.rs index d58b2aa3ba2..b78c562011c 100644 --- a/src/components/script/dom/virtualmethods.rs +++ b/src/components/script/dom/virtualmethods.rs @@ -15,6 +15,7 @@ use dom::bindings::codegen::InheritTypes::HTMLImageElementCast; use dom::bindings::codegen::InheritTypes::HTMLInputElementCast; use dom::bindings::codegen::InheritTypes::HTMLObjectElementCast; use dom::bindings::codegen::InheritTypes::HTMLOptGroupElementCast; +use dom::bindings::codegen::InheritTypes::HTMLOptionElementCast; use dom::bindings::codegen::InheritTypes::HTMLStyleElementCast; use dom::bindings::js::JSRef; use dom::element::Element; @@ -29,6 +30,7 @@ use dom::element::HTMLImageElementTypeId; use dom::element::HTMLInputElementTypeId; use dom::element::HTMLObjectElementTypeId; use dom::element::HTMLOptGroupElementTypeId; +use dom::element::HTMLOptionElementTypeId; use dom::element::HTMLStyleElementTypeId; use dom::event::Event; use dom::htmlanchorelement::HTMLAnchorElement; @@ -42,6 +44,7 @@ use dom::htmlimageelement::HTMLImageElement; use dom::htmlinputelement::HTMLInputElement; use dom::htmlobjectelement::HTMLObjectElement; use dom::htmloptgroupelement::HTMLOptGroupElement; +use dom::htmloptionelement::HTMLOptionElement; use dom::htmlstyleelement::HTMLStyleElement; use dom::node::{Node, NodeHelpers, ElementNodeTypeId}; use servo_util::str::DOMString; @@ -163,6 +166,10 @@ pub fn vtable_for<'a>(node: &'a JSRef) -> &'a VirtualMethods { let element: &JSRef = HTMLOptGroupElementCast::to_ref(node).unwrap(); element as &VirtualMethods } + ElementNodeTypeId(HTMLOptionElementTypeId) => { + let element: &JSRef = HTMLOptionElementCast::to_ref(node).unwrap(); + element as &VirtualMethods + } ElementNodeTypeId(HTMLStyleElementTypeId) => { let element: &JSRef = HTMLStyleElementCast::to_ref(node).unwrap(); element as &VirtualMethods diff --git a/src/components/script/dom/webidls/HTMLOptionElement.webidl b/src/components/script/dom/webidls/HTMLOptionElement.webidl index 2cb5ab76d64..7855449c6f4 100644 --- a/src/components/script/dom/webidls/HTMLOptionElement.webidl +++ b/src/components/script/dom/webidls/HTMLOptionElement.webidl @@ -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; From 186c8d9eddc3b2a6abc01f178b06f2f10cb53da2 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Fri, 27 Jun 2014 16:35:02 -0400 Subject: [PATCH 08/13] Implement support for 'disabled' property in HTMLSelectElement --- .../script/dom/htmlselectelement.rs | 84 ++++++++++++++++++- src/components/script/dom/virtualmethods.rs | 7 ++ .../dom/webidls/HTMLSelectElement.webidl | 2 +- 3 files changed, 89 insertions(+), 4 deletions(-) diff --git a/src/components/script/dom/htmlselectelement.rs b/src/components/script/dom/htmlselectelement.rs index 3170006bbbd..518bcbeb03c 100644 --- a/src/components/script/dom/htmlselectelement.rs +++ b/src/components/script/dom/htmlselectelement.rs @@ -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) { } + + // http://www.whatwg.org/html/#dom-fe-disabled + fn Disabled(&self) -> bool { + let elem: &JSRef = ElementCast::from_ref(self); + elem.has_attribute("disabled") + } + + // http://www.whatwg.org/html/#dom-fe-disabled + fn SetDisabled(&self, disabled: bool) { + let elem: &JSRef = 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 = 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 = 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 = 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 = 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 = 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 { diff --git a/src/components/script/dom/virtualmethods.rs b/src/components/script/dom/virtualmethods.rs index b78c562011c..7c0644005fe 100644 --- a/src/components/script/dom/virtualmethods.rs +++ b/src/components/script/dom/virtualmethods.rs @@ -16,6 +16,7 @@ use dom::bindings::codegen::InheritTypes::HTMLInputElementCast; 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::js::JSRef; use dom::element::Element; @@ -31,6 +32,7 @@ use dom::element::HTMLInputElementTypeId; use dom::element::HTMLObjectElementTypeId; use dom::element::HTMLOptGroupElementTypeId; use dom::element::HTMLOptionElementTypeId; +use dom::element::HTMLSelectElementTypeId; use dom::element::HTMLStyleElementTypeId; use dom::event::Event; use dom::htmlanchorelement::HTMLAnchorElement; @@ -45,6 +47,7 @@ use dom::htmlinputelement::HTMLInputElement; use dom::htmlobjectelement::HTMLObjectElement; use dom::htmloptgroupelement::HTMLOptGroupElement; use dom::htmloptionelement::HTMLOptionElement; +use dom::htmlselectelement::HTMLSelectElement; use dom::htmlstyleelement::HTMLStyleElement; use dom::node::{Node, NodeHelpers, ElementNodeTypeId}; use servo_util::str::DOMString; @@ -170,6 +173,10 @@ pub fn vtable_for<'a>(node: &'a JSRef) -> &'a VirtualMethods { let element: &JSRef = HTMLOptionElementCast::to_ref(node).unwrap(); element as &VirtualMethods } + ElementNodeTypeId(HTMLSelectElementTypeId) => { + let element: &JSRef = HTMLSelectElementCast::to_ref(node).unwrap(); + element as &VirtualMethods + } ElementNodeTypeId(HTMLStyleElementTypeId) => { let element: &JSRef = HTMLStyleElementCast::to_ref(node).unwrap(); element as &VirtualMethods diff --git a/src/components/script/dom/webidls/HTMLSelectElement.webidl b/src/components/script/dom/webidls/HTMLSelectElement.webidl index 0dec2171609..91d4c3b0917 100644 --- a/src/components/script/dom/webidls/HTMLSelectElement.webidl +++ b/src/components/script/dom/webidls/HTMLSelectElement.webidl @@ -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; From 09583d94b83de933ca4cb91ac6d83354e5543b0c Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Fri, 27 Jun 2014 16:35:16 -0400 Subject: [PATCH 09/13] Implement support for 'disabled' property in HTMLTextAreaElement --- .../script/dom/htmltextareaelement.rs | 87 ++++++++++++++++++- src/components/script/dom/virtualmethods.rs | 7 ++ .../dom/webidls/HTMLTextAreaElement.webidl | 2 +- 3 files changed, 92 insertions(+), 4 deletions(-) diff --git a/src/components/script/dom/htmltextareaelement.rs b/src/components/script/dom/htmltextareaelement.rs index f4170a20f1f..ac96c0789eb 100644 --- a/src/components/script/dom/htmltextareaelement.rs +++ b/src/components/script/dom/htmltextareaelement.rs @@ -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 = ElementCast::from_ref(self); + elem.has_attribute("disabled") + } + + // http://www.whatwg.org/html/#dom-fe-disabled + fn SetDisabled(&self, disabled: bool) { + let elem: &JSRef = 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 = 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 = 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 = 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 = 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 = 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() diff --git a/src/components/script/dom/virtualmethods.rs b/src/components/script/dom/virtualmethods.rs index 7c0644005fe..24cd91ccea7 100644 --- a/src/components/script/dom/virtualmethods.rs +++ b/src/components/script/dom/virtualmethods.rs @@ -18,6 +18,7 @@ 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; @@ -34,6 +35,7 @@ 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::htmlbodyelement::HTMLBodyElement; @@ -49,6 +51,7 @@ 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; @@ -181,6 +184,10 @@ pub fn vtable_for<'a>(node: &'a JSRef) -> &'a VirtualMethods { let element: &JSRef = HTMLStyleElementCast::to_ref(node).unwrap(); element as &VirtualMethods } + ElementNodeTypeId(HTMLTextAreaElementTypeId) => { + let element: &JSRef = HTMLTextAreaElementCast::to_ref(node).unwrap(); + element as &VirtualMethods + } ElementNodeTypeId(ElementTypeId) => { let element: &JSRef = ElementCast::to_ref(node).unwrap(); element as &VirtualMethods diff --git a/src/components/script/dom/webidls/HTMLTextAreaElement.webidl b/src/components/script/dom/webidls/HTMLTextAreaElement.webidl index 5425bb321fb..534bb87a0e5 100644 --- a/src/components/script/dom/webidls/HTMLTextAreaElement.webidl +++ b/src/components/script/dom/webidls/HTMLTextAreaElement.webidl @@ -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; From ad9220c932af718aa75e845b017ed00016722c44 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Tue, 15 Jul 2014 22:01:17 -0400 Subject: [PATCH 10/13] Implement support for 'enabled' property in HTMLAnchorElement --- .../script/dom/htmlanchorelement.rs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/components/script/dom/htmlanchorelement.rs b/src/components/script/dom/htmlanchorelement.rs index 5b905b1bd44..b69536a3303 100644 --- a/src/components/script/dom/htmlanchorelement.rs +++ b/src/components/script/dom/htmlanchorelement.rs @@ -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 = 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 = NodeCast::from_ref(self); + match name.as_slice() { + "href" => node.set_enabled_state(false), + _ => () + } + } + fn handle_event(&self, event: &JSRef) { match self.super_type() { Some(s) => { From d94be160e43e4134b7a7b0bec7c3d0f7126beb75 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Tue, 15 Jul 2014 22:02:24 -0400 Subject: [PATCH 11/13] Implement support for 'enabled' property in HTMLAreaElement --- src/components/script/dom/htmlareaelement.rs | 37 +++++++++++++++++++- src/components/script/dom/virtualmethods.rs | 7 ++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/components/script/dom/htmlareaelement.rs b/src/components/script/dom/htmlareaelement.rs index 61f7890945c..339355c844f 100644 --- a/src/components/script/dom/htmlareaelement.rs +++ b/src/components/script/dom/htmlareaelement.rs @@ -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 = 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 = 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 = 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() diff --git a/src/components/script/dom/virtualmethods.rs b/src/components/script/dom/virtualmethods.rs index 24cd91ccea7..ae3b3b702e3 100644 --- a/src/components/script/dom/virtualmethods.rs +++ b/src/components/script/dom/virtualmethods.rs @@ -5,6 +5,7 @@ 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; @@ -23,6 +24,7 @@ use dom::bindings::js::JSRef; use dom::element::Element; use dom::element::ElementTypeId; use dom::element::HTMLAnchorElementTypeId; +use dom::element::HTMLAreaElementTypeId; use dom::element::HTMLBodyElementTypeId; use dom::element::HTMLButtonElementTypeId; use dom::element::HTMLCanvasElementTypeId; @@ -38,6 +40,7 @@ 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; @@ -136,6 +139,10 @@ pub fn vtable_for<'a>(node: &'a JSRef) -> &'a VirtualMethods { let element: &JSRef = HTMLAnchorElementCast::to_ref(node).unwrap(); element as &VirtualMethods } + ElementNodeTypeId(HTMLAreaElementTypeId) => { + let element: &JSRef = HTMLAreaElementCast::to_ref(node).unwrap(); + element as &VirtualMethods + } ElementNodeTypeId(HTMLBodyElementTypeId) => { let element: &JSRef = HTMLBodyElementCast::to_ref(node).unwrap(); element as &VirtualMethods From 1dea5d26806590a22676345c9151d8bfc3412301 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Tue, 15 Jul 2014 22:03:01 -0400 Subject: [PATCH 12/13] Implement support for 'enabled' property in HTMLLinkElement --- src/components/script/dom/htmllinkelement.rs | 37 +++++++++++++++++++- src/components/script/dom/virtualmethods.rs | 7 ++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/components/script/dom/htmllinkelement.rs b/src/components/script/dom/htmllinkelement.rs index c10c74adc89..3d3a46d28c4 100644 --- a/src/components/script/dom/htmllinkelement.rs +++ b/src/components/script/dom/htmllinkelement.rs @@ -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 = 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 = 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 = 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() diff --git a/src/components/script/dom/virtualmethods.rs b/src/components/script/dom/virtualmethods.rs index ae3b3b702e3..c050d2e5449 100644 --- a/src/components/script/dom/virtualmethods.rs +++ b/src/components/script/dom/virtualmethods.rs @@ -14,6 +14,7 @@ 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; @@ -32,6 +33,7 @@ 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; @@ -49,6 +51,7 @@ 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; @@ -171,6 +174,10 @@ pub fn vtable_for<'a>(node: &'a JSRef) -> &'a VirtualMethods { let element: &JSRef = HTMLInputElementCast::to_ref(node).unwrap(); element as &VirtualMethods } + ElementNodeTypeId(HTMLLinkElementTypeId) => { + let element: &JSRef = HTMLLinkElementCast::to_ref(node).unwrap(); + element as &VirtualMethods + } ElementNodeTypeId(HTMLObjectElementTypeId) => { let element: &JSRef = HTMLObjectElementCast::to_ref(node).unwrap(); element as &VirtualMethods From 7a760fc9db789511c604f983ea393fdca0a6264e Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Tue, 5 Aug 2014 10:39:18 -0400 Subject: [PATCH 13/13] Added content tests for :disabled & :enabled CSS selectors --- src/test/content/harness.js | 9 + .../test_enabled_disabled_selectors.html | 181 ++++++++++++++++++ 2 files changed, 190 insertions(+) create mode 100644 src/test/content/test_enabled_disabled_selectors.html diff --git a/src/test/content/harness.js b/src/test/content/harness.js index 48c41d214b1..7bd118a9dff 100644 --- a/src/test/content/harness.js +++ b/src/test/content/harness.js @@ -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() { diff --git a/src/test/content/test_enabled_disabled_selectors.html b/src/test/content/test_enabled_disabled_selectors.html new file mode 100644 index 00000000000..b6c255b945e --- /dev/null +++ b/src/test/content/test_enabled_disabled_selectors.html @@ -0,0 +1,181 @@ + + + + Tests for :enabled and :disabled selectors + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+
+ +
+ + + + + + +
+ +
+ + + + + + + +
+ +