mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Implement support for :enabled CSS selector
This commit is contained in:
parent
7771350898
commit
10a20e69fd
6 changed files with 66 additions and 4 deletions
|
@ -404,6 +404,12 @@ impl<'le> TElement for LayoutElement<'le> {
|
||||||
self.element.node.get_disabled_state_for_layout()
|
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 {
|
fn get_content(content_list: &content::T) -> String {
|
||||||
|
|
|
@ -950,4 +950,8 @@ impl<'a> style::TElement for JSRef<'a, Element> {
|
||||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||||
node.get_disabled_state()
|
node.get_disabled_state()
|
||||||
}
|
}
|
||||||
|
fn get_enabled_state(&self) -> bool {
|
||||||
|
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||||
|
node.get_enabled_state()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,10 @@ use dom::document::{Document, DocumentHelpers, HTMLDocument, NonHTMLDocument};
|
||||||
use dom::documentfragment::DocumentFragment;
|
use dom::documentfragment::DocumentFragment;
|
||||||
use dom::documenttype::DocumentType;
|
use dom::documenttype::DocumentType;
|
||||||
use dom::element::{AttributeHandlers, Element, ElementTypeId};
|
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::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||||
use dom::nodelist::{NodeList};
|
use dom::nodelist::{NodeList};
|
||||||
use dom::processinginstruction::ProcessingInstruction;
|
use dom::processinginstruction::ProcessingInstruction;
|
||||||
|
@ -128,7 +131,9 @@ bitflags! {
|
||||||
#[doc = "Specifies whether this node is in hover state."]
|
#[doc = "Specifies whether this node is in hover state."]
|
||||||
static InHoverState = 0x02,
|
static InHoverState = 0x02,
|
||||||
#[doc = "Specifies whether this node is in disabled state."]
|
#[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 get_disabled_state(&self) -> bool;
|
||||||
fn set_disabled_state(&self, state: 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(&self);
|
||||||
fn dump_indent(&self, indent: uint);
|
fn dump_indent(&self, indent: uint);
|
||||||
fn debug_str(&self) -> String;
|
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.
|
/// Iterates over this node and all its descendants, in preorder.
|
||||||
fn traverse_preorder<'a>(&'a self) -> TreeIterator<'a> {
|
fn traverse_preorder<'a>(&'a self) -> TreeIterator<'a> {
|
||||||
let mut nodes = vec!();
|
let mut nodes = vec!();
|
||||||
|
@ -748,6 +768,7 @@ impl LayoutNodeHelpers for JS<Node> {
|
||||||
pub trait RawLayoutNodeHelpers {
|
pub trait RawLayoutNodeHelpers {
|
||||||
unsafe fn get_hover_state_for_layout(&self) -> bool;
|
unsafe fn get_hover_state_for_layout(&self) -> bool;
|
||||||
unsafe fn get_disabled_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 {
|
impl RawLayoutNodeHelpers for Node {
|
||||||
|
@ -757,6 +778,9 @@ impl RawLayoutNodeHelpers for Node {
|
||||||
unsafe fn get_disabled_state_for_layout(&self) -> bool {
|
unsafe fn get_disabled_state_for_layout(&self) -> bool {
|
||||||
self.flags.deref().borrow().contains(InDisabledState)
|
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<JSRef<Document>>) -> Node {
|
fn new_(type_id: NodeTypeId, doc: Option<JSRef<Document>>) -> Node {
|
||||||
Node {
|
let node = Node {
|
||||||
eventtarget: EventTarget::new_inherited(NodeTargetTypeId(type_id)),
|
eventtarget: EventTarget::new_inherited(NodeTargetTypeId(type_id)),
|
||||||
type_id: type_id,
|
type_id: type_id,
|
||||||
|
|
||||||
|
@ -964,7 +988,22 @@ impl Node {
|
||||||
flags: Traceable::new(RefCell::new(NodeFlags::new(type_id))),
|
flags: Traceable::new(RefCell::new(NodeFlags::new(type_id))),
|
||||||
|
|
||||||
layout_data: LayoutDataRef::new(),
|
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
|
// 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.get_disabled_state() { continue; }
|
||||||
if ancestor.is_parent_of(self) {
|
if ancestor.is_parent_of(self) {
|
||||||
self.set_disabled_state(true);
|
self.set_disabled_state(true);
|
||||||
|
self.set_enabled_state(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
match ancestor.children().find(|child| child.is_htmllegendelement()) {
|
match ancestor.children().find(|child| child.is_htmllegendelement()) {
|
||||||
|
@ -2013,6 +2053,7 @@ impl<'a> DisabledStateHelpers for JSRef<'a, Node> {
|
||||||
None => ()
|
None => ()
|
||||||
}
|
}
|
||||||
self.set_disabled_state(true);
|
self.set_disabled_state(true);
|
||||||
|
self.set_enabled_state(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2022,6 +2063,7 @@ impl<'a> DisabledStateHelpers for JSRef<'a, Node> {
|
||||||
match self.parent_node().root() {
|
match self.parent_node().root() {
|
||||||
Some(ref parent) if parent.is_htmloptgroupelement() && parent.get_disabled_state() => {
|
Some(ref parent) if parent.is_htmloptgroupelement() && parent.get_disabled_state() => {
|
||||||
self.set_disabled_state(true);
|
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 elem: &JSRef<'a, Element> = ElementCast::to_ref(self).unwrap();
|
||||||
let has_disabled_attrib = elem.has_attribute("disabled");
|
let has_disabled_attrib = elem.has_attribute("disabled");
|
||||||
self.set_disabled_state(has_disabled_attrib);
|
self.set_disabled_state(has_disabled_attrib);
|
||||||
|
self.set_enabled_state(!has_disabled_attrib);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,5 +28,6 @@ pub trait TElement {
|
||||||
fn get_hover_state(&self) -> bool;
|
fn get_hover_state(&self) -> bool;
|
||||||
fn get_id(&self) -> Option<Atom>;
|
fn get_id(&self) -> Option<Atom>;
|
||||||
fn get_disabled_state(&self) -> bool;
|
fn get_disabled_state(&self) -> bool;
|
||||||
|
fn get_enabled_state(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -784,6 +784,12 @@ fn matches_simple_selector<E:TElement,
|
||||||
let elem = element.as_element();
|
let elem = element.as_element();
|
||||||
elem.get_disabled_state()
|
elem.get_disabled_state()
|
||||||
},
|
},
|
||||||
|
// http://www.whatwg.org/html/#selector-enabled
|
||||||
|
Enabled => {
|
||||||
|
*shareable = false;
|
||||||
|
let elem = element.as_element();
|
||||||
|
elem.get_enabled_state()
|
||||||
|
},
|
||||||
FirstChild => {
|
FirstChild => {
|
||||||
*shareable = false;
|
*shareable = false;
|
||||||
matches_first_child(element)
|
matches_first_child(element)
|
||||||
|
|
|
@ -78,6 +78,7 @@ pub enum SimpleSelector {
|
||||||
Visited,
|
Visited,
|
||||||
Hover,
|
Hover,
|
||||||
Disabled,
|
Disabled,
|
||||||
|
Enabled,
|
||||||
FirstChild, LastChild, OnlyChild,
|
FirstChild, LastChild, OnlyChild,
|
||||||
// Empty,
|
// Empty,
|
||||||
Root,
|
Root,
|
||||||
|
@ -219,7 +220,7 @@ fn compute_specificity(mut selector: &CompoundSelector,
|
||||||
&ClassSelector(..)
|
&ClassSelector(..)
|
||||||
| &AttrExists(..) | &AttrEqual(..) | &AttrIncludes(..) | &AttrDashMatch(..)
|
| &AttrExists(..) | &AttrEqual(..) | &AttrIncludes(..) | &AttrDashMatch(..)
|
||||||
| &AttrPrefixMatch(..) | &AttrSubstringMatch(..) | &AttrSuffixMatch(..)
|
| &AttrPrefixMatch(..) | &AttrSubstringMatch(..) | &AttrSuffixMatch(..)
|
||||||
| &AnyLink | &Link | &Visited | &Hover | &Disabled
|
| &AnyLink | &Link | &Visited | &Hover | &Disabled | &Enabled
|
||||||
| &FirstChild | &LastChild | &OnlyChild | &Root
|
| &FirstChild | &LastChild | &OnlyChild | &Root
|
||||||
// | &Empty | &Lang(*)
|
// | &Empty | &Lang(*)
|
||||||
| &NthChild(..) | &NthLastChild(..)
|
| &NthChild(..) | &NthLastChild(..)
|
||||||
|
@ -481,6 +482,7 @@ fn parse_simple_pseudo_class(name: &str) -> Option<SimpleSelector> {
|
||||||
"visited" => Some(Visited),
|
"visited" => Some(Visited),
|
||||||
"hover" => Some(Hover),
|
"hover" => Some(Hover),
|
||||||
"disabled" => Some(Disabled),
|
"disabled" => Some(Disabled),
|
||||||
|
"enabled" => Some(Enabled),
|
||||||
"first-child" => Some(FirstChild),
|
"first-child" => Some(FirstChild),
|
||||||
"last-child" => Some(LastChild),
|
"last-child" => Some(LastChild),
|
||||||
"only-child" => Some(OnlyChild),
|
"only-child" => Some(OnlyChild),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue