servo: Merge #4190 - Implements the :checked pseudo-class for inputs (from mttr:checked_pseudo_class); r=Manishearth

Relevant spec:
https://html.spec.whatwg.org/multipage/scripting.html#selector-checked

Also modifies HTMLInputElement::SetChecked to no longer modify its
checked content value, instead making use of its internal checkedness
state now that we can match `:checked` properly.

Source-Repo: https://github.com/servo/servo
Source-Revision: f18c18371d2bb5edde9d64e46b74bf01411afab3
This commit is contained in:
Matthew Rasmus 2014-12-08 12:01:51 -07:00
parent d9885c4396
commit 0c6c8fc464
7 changed files with 47 additions and 4 deletions

View File

@ -552,6 +552,13 @@ impl<'le> TElement<'le> for LayoutElement<'le> {
}
}
#[inline]
fn get_checked_state(self) -> bool {
unsafe {
self.element.get_checked_state_for_layout()
}
}
#[inline]
fn has_class(self, name: &Atom) -> bool {
unsafe {

View File

@ -13,6 +13,7 @@ use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
use dom::bindings::codegen::Bindings::ElementBinding;
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods;
use dom::bindings::codegen::Bindings::NamedNodeMapBinding::NamedNodeMapMethods;
use dom::bindings::codegen::InheritTypes::{ElementDerived, HTMLInputElementDerived, HTMLTableCellElementDerived};
use dom::bindings::codegen::InheritTypes::{HTMLInputElementCast, NodeCast, EventTargetCast, ElementCast};
@ -198,6 +199,7 @@ pub trait RawLayoutElementHelpers {
-> LengthOrPercentageOrAuto;
unsafe fn get_integer_attribute_for_layout(&self, integer_attribute: IntegerAttribute)
-> Option<i32>;
unsafe fn get_checked_state_for_layout(&self) -> bool;
fn local_name<'a>(&'a self) -> &'a Atom;
fn namespace<'a>(&'a self) -> &'a Namespace;
fn style_attribute<'a>(&'a self) -> &'a DOMRefCell<Option<style::PropertyDeclarationBlock>>;
@ -313,6 +315,17 @@ impl RawLayoutElementHelpers for Element {
}
}
#[inline]
#[allow(unrooted_must_root)]
unsafe fn get_checked_state_for_layout(&self) -> bool {
// TODO option and menuitem can also have a checked state.
if !self.is_htmlinputelement() {
return false
}
let this: &HTMLInputElement = mem::transmute(self);
this.get_checked_state_for_layout()
}
// Getters used in components/layout/wrapper.rs
fn local_name<'a>(&'a self) -> &'a Atom {
@ -1156,6 +1169,12 @@ impl<'a> style::TElement<'a> for JSRef<'a, Element> {
let node: JSRef<Node> = NodeCast::from_ref(self);
node.get_enabled_state()
}
fn get_checked_state(self) -> bool {
match HTMLInputElementCast::to_ref(self) {
Some(input) => input.Checked(),
None => false,
}
}
fn has_class(self, name: &Atom) -> bool {
// FIXME(zwarich): Remove this when UFCS lands and there is a better way
// of disambiguating methods.

View File

@ -125,6 +125,7 @@ pub trait LayoutHTMLInputElementHelpers {
}
pub trait RawLayoutHTMLInputElementHelpers {
unsafe fn get_checked_state_for_layout(&self) -> bool;
unsafe fn get_size_for_layout(&self) -> u32;
}
@ -162,6 +163,11 @@ impl LayoutHTMLInputElementHelpers for JS<HTMLInputElement> {
}
impl RawLayoutHTMLInputElementHelpers for HTMLInputElement {
#[allow(unrooted_must_root)]
unsafe fn get_checked_state_for_layout(&self) -> bool {
self.checked.get()
}
#[allow(unrooted_must_root)]
unsafe fn get_size_for_layout(&self) -> u32 {
self.size.get()
@ -181,7 +187,9 @@ impl<'a> HTMLInputElementMethods for JSRef<'a, HTMLInputElement> {
}
// https://html.spec.whatwg.org/multipage/forms.html#dom-input-checked
make_bool_setter!(SetChecked, "checked")
fn SetChecked(self, checked: bool) {
self.update_checked_state(checked);
}
// https://html.spec.whatwg.org/multipage/forms.html#dom-input-readonly
make_bool_getter!(ReadOnly)

View File

@ -45,6 +45,7 @@ pub trait TElement<'a> : Copy {
fn get_id(self) -> Option<Atom>;
fn get_disabled_state(self) -> bool;
fn get_enabled_state(self) -> bool;
fn get_checked_state(self) -> bool;
fn has_class(self, name: &Atom) -> bool;
// Ordinarily I wouldn't use callbacks like this, but the alternative is

View File

@ -997,6 +997,12 @@ pub fn matches_simple_selector<'a,E,N>(selector: &SimpleSelector,
let elem = element.as_element();
elem.get_enabled_state()
},
// https://html.spec.whatwg.org/multipage/scripting.html#selector-checked
Checked => {
*shareable = false;
let elem = element.as_element();
elem.get_checked_state()
}
FirstChild => {
*shareable = false;
matches_first_child(element)

View File

@ -68,6 +68,7 @@ pub enum SimpleSelector {
Hover,
Disabled,
Enabled,
Checked,
FirstChild, LastChild, OnlyChild,
// Empty,
Root,
@ -226,7 +227,7 @@ fn compute_specificity(mut selector: &CompoundSelector,
| &AttrExists(..) | &AttrEqual(..) | &AttrIncludes(..) | &AttrDashMatch(..)
| &AttrPrefixMatch(..) | &AttrSubstringMatch(..) | &AttrSuffixMatch(..)
| &AnyLink | &Link | &Visited | &Hover | &Disabled | &Enabled
| &FirstChild | &LastChild | &OnlyChild | &Root
| &FirstChild | &LastChild | &OnlyChild | &Root | &Checked
// | &Empty | &Lang(*)
| &NthChild(..) | &NthLastChild(..)
| &NthOfType(..) | &NthLastOfType(..)
@ -497,6 +498,7 @@ fn parse_simple_pseudo_class(name: &str) -> Result<SimpleSelector, ()> {
"hover" => Ok(Hover),
"disabled" => Ok(Disabled),
"enabled" => Ok(Enabled),
"checked" => Ok(Checked),
"first-child" => Ok(FirstChild),
"last-child" => Ok(LastChild),
"only-child" => Ok(OnlyChild),

View File

@ -10,9 +10,9 @@ input[type="checkbox"],
input[type="radio"] { font-family: monospace !important; border: none !important; background: transparent; }
input[type="checkbox"]::before { content: "[ ]"; padding: 0; }
input[type="checkbox"][checked]::before { content: "[✓]"; }
input[type="checkbox"]:checked::before { content: "[✓]"; }
input[type="radio"]::before { content: "( )"; padding: 0; }
input[type="radio"][checked]::before { content: "(●)"; }
input[type="radio"]:checked::before { content: "(●)"; }
td[align="left"] { text-align: left; }
td[align="center"] { text-align: center; }