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] 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 eed51e9a86a6..73001d56ddd3 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 df618c7a8ff3..75c77cf2148d 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 f854cd23bab1..6b64c60bd21b 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;