mirror of
https://github.com/servo/servo.git
synced 2025-06-13 02:44:29 +00:00
auto merge of #4190 : mttr/servo/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.
This commit is contained in:
commit
f18c18371d
7 changed files with 47 additions and 4 deletions
|
@ -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]
|
#[inline]
|
||||||
fn has_class(self, name: &Atom) -> bool {
|
fn has_class(self, name: &Atom) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -13,6 +13,7 @@ use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
|
||||||
use dom::bindings::codegen::Bindings::ElementBinding;
|
use dom::bindings::codegen::Bindings::ElementBinding;
|
||||||
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
|
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
|
||||||
use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
|
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::Bindings::NamedNodeMapBinding::NamedNodeMapMethods;
|
||||||
use dom::bindings::codegen::InheritTypes::{ElementDerived, HTMLInputElementDerived, HTMLTableCellElementDerived};
|
use dom::bindings::codegen::InheritTypes::{ElementDerived, HTMLInputElementDerived, HTMLTableCellElementDerived};
|
||||||
use dom::bindings::codegen::InheritTypes::{HTMLInputElementCast, NodeCast, EventTargetCast, ElementCast};
|
use dom::bindings::codegen::InheritTypes::{HTMLInputElementCast, NodeCast, EventTargetCast, ElementCast};
|
||||||
|
@ -198,6 +199,7 @@ pub trait RawLayoutElementHelpers {
|
||||||
-> LengthOrPercentageOrAuto;
|
-> LengthOrPercentageOrAuto;
|
||||||
unsafe fn get_integer_attribute_for_layout(&self, integer_attribute: IntegerAttribute)
|
unsafe fn get_integer_attribute_for_layout(&self, integer_attribute: IntegerAttribute)
|
||||||
-> Option<i32>;
|
-> Option<i32>;
|
||||||
|
unsafe fn get_checked_state_for_layout(&self) -> bool;
|
||||||
fn local_name<'a>(&'a self) -> &'a Atom;
|
fn local_name<'a>(&'a self) -> &'a Atom;
|
||||||
fn namespace<'a>(&'a self) -> &'a Namespace;
|
fn namespace<'a>(&'a self) -> &'a Namespace;
|
||||||
fn style_attribute<'a>(&'a self) -> &'a DOMRefCell<Option<style::PropertyDeclarationBlock>>;
|
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
|
// Getters used in components/layout/wrapper.rs
|
||||||
|
|
||||||
fn local_name<'a>(&'a self) -> &'a Atom {
|
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);
|
let node: JSRef<Node> = NodeCast::from_ref(self);
|
||||||
node.get_enabled_state()
|
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 {
|
fn has_class(self, name: &Atom) -> bool {
|
||||||
// FIXME(zwarich): Remove this when UFCS lands and there is a better way
|
// FIXME(zwarich): Remove this when UFCS lands and there is a better way
|
||||||
// of disambiguating methods.
|
// of disambiguating methods.
|
||||||
|
|
|
@ -125,6 +125,7 @@ pub trait LayoutHTMLInputElementHelpers {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RawLayoutHTMLInputElementHelpers {
|
pub trait RawLayoutHTMLInputElementHelpers {
|
||||||
|
unsafe fn get_checked_state_for_layout(&self) -> bool;
|
||||||
unsafe fn get_size_for_layout(&self) -> u32;
|
unsafe fn get_size_for_layout(&self) -> u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,6 +163,11 @@ impl LayoutHTMLInputElementHelpers for JS<HTMLInputElement> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RawLayoutHTMLInputElementHelpers for 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)]
|
#[allow(unrooted_must_root)]
|
||||||
unsafe fn get_size_for_layout(&self) -> u32 {
|
unsafe fn get_size_for_layout(&self) -> u32 {
|
||||||
self.size.get()
|
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
|
// 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
|
// https://html.spec.whatwg.org/multipage/forms.html#dom-input-readonly
|
||||||
make_bool_getter!(ReadOnly)
|
make_bool_getter!(ReadOnly)
|
||||||
|
|
|
@ -45,6 +45,7 @@ pub trait TElement<'a> : Copy {
|
||||||
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;
|
fn get_enabled_state(self) -> bool;
|
||||||
|
fn get_checked_state(self) -> bool;
|
||||||
fn has_class(self, name: &Atom) -> bool;
|
fn has_class(self, name: &Atom) -> bool;
|
||||||
|
|
||||||
// Ordinarily I wouldn't use callbacks like this, but the alternative is
|
// Ordinarily I wouldn't use callbacks like this, but the alternative is
|
||||||
|
|
|
@ -997,6 +997,12 @@ pub fn matches_simple_selector<'a,E,N>(selector: &SimpleSelector,
|
||||||
let elem = element.as_element();
|
let elem = element.as_element();
|
||||||
elem.get_enabled_state()
|
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 => {
|
FirstChild => {
|
||||||
*shareable = false;
|
*shareable = false;
|
||||||
matches_first_child(element)
|
matches_first_child(element)
|
||||||
|
|
|
@ -68,6 +68,7 @@ pub enum SimpleSelector {
|
||||||
Hover,
|
Hover,
|
||||||
Disabled,
|
Disabled,
|
||||||
Enabled,
|
Enabled,
|
||||||
|
Checked,
|
||||||
FirstChild, LastChild, OnlyChild,
|
FirstChild, LastChild, OnlyChild,
|
||||||
// Empty,
|
// Empty,
|
||||||
Root,
|
Root,
|
||||||
|
@ -226,7 +227,7 @@ fn compute_specificity(mut selector: &CompoundSelector,
|
||||||
| &AttrExists(..) | &AttrEqual(..) | &AttrIncludes(..) | &AttrDashMatch(..)
|
| &AttrExists(..) | &AttrEqual(..) | &AttrIncludes(..) | &AttrDashMatch(..)
|
||||||
| &AttrPrefixMatch(..) | &AttrSubstringMatch(..) | &AttrSuffixMatch(..)
|
| &AttrPrefixMatch(..) | &AttrSubstringMatch(..) | &AttrSuffixMatch(..)
|
||||||
| &AnyLink | &Link | &Visited | &Hover | &Disabled | &Enabled
|
| &AnyLink | &Link | &Visited | &Hover | &Disabled | &Enabled
|
||||||
| &FirstChild | &LastChild | &OnlyChild | &Root
|
| &FirstChild | &LastChild | &OnlyChild | &Root | &Checked
|
||||||
// | &Empty | &Lang(*)
|
// | &Empty | &Lang(*)
|
||||||
| &NthChild(..) | &NthLastChild(..)
|
| &NthChild(..) | &NthLastChild(..)
|
||||||
| &NthOfType(..) | &NthLastOfType(..)
|
| &NthOfType(..) | &NthLastOfType(..)
|
||||||
|
@ -497,6 +498,7 @@ fn parse_simple_pseudo_class(name: &str) -> Result<SimpleSelector, ()> {
|
||||||
"hover" => Ok(Hover),
|
"hover" => Ok(Hover),
|
||||||
"disabled" => Ok(Disabled),
|
"disabled" => Ok(Disabled),
|
||||||
"enabled" => Ok(Enabled),
|
"enabled" => Ok(Enabled),
|
||||||
|
"checked" => Ok(Checked),
|
||||||
"first-child" => Ok(FirstChild),
|
"first-child" => Ok(FirstChild),
|
||||||
"last-child" => Ok(LastChild),
|
"last-child" => Ok(LastChild),
|
||||||
"only-child" => Ok(OnlyChild),
|
"only-child" => Ok(OnlyChild),
|
||||||
|
|
|
@ -10,9 +10,9 @@ input[type="checkbox"],
|
||||||
input[type="radio"] { font-family: monospace !important; border: none !important; background: transparent; }
|
input[type="radio"] { font-family: monospace !important; border: none !important; background: transparent; }
|
||||||
|
|
||||||
input[type="checkbox"]::before { content: "[ ]"; padding: 0; }
|
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"]::before { content: "( )"; padding: 0; }
|
||||||
input[type="radio"][checked]::before { content: "(●)"; }
|
input[type="radio"]:checked::before { content: "(●)"; }
|
||||||
|
|
||||||
td[align="left"] { text-align: left; }
|
td[align="left"] { text-align: left; }
|
||||||
td[align="center"] { text-align: center; }
|
td[align="center"] { text-align: center; }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue