aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/script/dom/node.rs
diff options
context:
space:
mode:
authorBruno de Oliveira Abinader <bruno.d@partner.samsung.com>2014-06-27 15:25:09 -0400
committerBruno de Oliveira Abinader <bruno.d@partner.samsung.com>2014-08-05 11:01:53 -0400
commit7771350898ae1dd8e81dd1863da431e8cc7486e3 (patch)
treef53c25429020386995afac1ea043211c7616f790 /src/components/script/dom/node.rs
parent40048b791c44a0ef250d09633af38be0a9f257fd (diff)
downloadservo-7771350898ae1dd8e81dd1863da431e8cc7486e3.tar.gz
servo-7771350898ae1dd8e81dd1863da431e8cc7486e3.zip
Implement support for :disabled CSS selector
Diffstat (limited to 'src/components/script/dom/node.rs')
-rw-r--r--src/components/script/dom/node.rs71
1 files changed, 69 insertions, 2 deletions
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<Node> {
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<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);
+ 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);
+ }
+}