mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
Auto merge of #25499 - NeverHappened:implement-form-dirname, r=jdm
Implement dirname support for form element Added support for dirname in input on form submit Added Dir getter / setter for HTMLElement NOT YET Added get directionality according to https://html.spec.whatwg.org/multipage/dom.html#the-directionality - [X] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #25379 (GitHub issue number if applicable)
This commit is contained in:
commit
145c89a2d4
27 changed files with 252 additions and 3303 deletions
|
@ -110,6 +110,7 @@ style_traits = {path = "../style_traits"}
|
|||
swapper = "0.1"
|
||||
tendril = {version = "0.4.1", features = ["encoding_rs"]}
|
||||
time = "0.1.12"
|
||||
unicode-bidi = "0.3.4"
|
||||
unicode-segmentation = "1.1.0"
|
||||
url = "2.0"
|
||||
utf-8 = "0.7"
|
||||
|
|
|
@ -540,6 +540,16 @@ impl Element {
|
|||
}
|
||||
true // whatwg/html#5239
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#the-directionality
|
||||
pub fn directionality(&self) -> String {
|
||||
self.downcast::<HTMLElement>()
|
||||
.and_then(|html_element| html_element.directionality())
|
||||
.unwrap_or_else(|| {
|
||||
let node = self.upcast::<Node>();
|
||||
node.parent_directionality()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
|
|
|
@ -27,6 +27,7 @@ use crate::dom::htmlframesetelement::HTMLFrameSetElement;
|
|||
use crate::dom::htmlhtmlelement::HTMLHtmlElement;
|
||||
use crate::dom::htmlinputelement::{HTMLInputElement, InputType};
|
||||
use crate::dom::htmllabelelement::HTMLLabelElement;
|
||||
use crate::dom::htmltextareaelement::HTMLTextAreaElement;
|
||||
use crate::dom::node::{document_from_node, window_from_node};
|
||||
use crate::dom::node::{BindContext, Node, NodeFlags, ShadowIncluding};
|
||||
use crate::dom::text::Text;
|
||||
|
@ -170,6 +171,11 @@ impl HTMLElementMethods for HTMLElement {
|
|||
// https://html.spec.whatwg.org/multipage/#dom-hidden
|
||||
make_bool_setter!(SetHidden, "hidden");
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#the-dir-attribute
|
||||
make_getter!(Dir, "dir");
|
||||
// https://html.spec.whatwg.org/multipage/#the-dir-attribute
|
||||
make_setter!(SetDir, "dir");
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#globaleventhandlers
|
||||
global_event_handlers!(NoOnload);
|
||||
|
||||
|
@ -767,6 +773,48 @@ impl HTMLElement {
|
|||
})
|
||||
.count() as u32
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#the-directionality.
|
||||
// returns Some if can infer direction by itself or from child nodes
|
||||
// returns None if requires to go up to parent
|
||||
pub fn directionality(&self) -> Option<String> {
|
||||
let element_direction: &str = &self.Dir();
|
||||
|
||||
if element_direction == "ltr" {
|
||||
return Some("ltr".to_owned());
|
||||
}
|
||||
|
||||
if element_direction == "rtl" {
|
||||
return Some("rtl".to_owned());
|
||||
}
|
||||
|
||||
if let Some(input) = self.downcast::<HTMLInputElement>() {
|
||||
if input.input_type() == InputType::Tel {
|
||||
return Some("ltr".to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
if element_direction == "auto" {
|
||||
if let Some(directionality) = self
|
||||
.downcast::<HTMLInputElement>()
|
||||
.and_then(|input| input.auto_directionality())
|
||||
{
|
||||
return Some(directionality);
|
||||
}
|
||||
|
||||
if let Some(area) = self.downcast::<HTMLTextAreaElement>() {
|
||||
return Some(area.auto_directionality());
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(NeverHappened): Implement condition
|
||||
// If the element's dir attribute is in the auto state OR
|
||||
// If the element is a bdi element and the dir attribute is not in a defined state
|
||||
// (i.e. it is not present or has an invalid value)
|
||||
// Requires bdi element implementation (https://html.spec.whatwg.org/multipage/#the-bdi-element)
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl VirtualMethods for HTMLElement {
|
||||
|
|
|
@ -950,7 +950,6 @@ impl HTMLFormElement {
|
|||
match element {
|
||||
HTMLElementTypeId::HTMLInputElement => {
|
||||
let input = child.downcast::<HTMLInputElement>().unwrap();
|
||||
|
||||
data_set.append(&mut input.form_datums(submitter, encoding));
|
||||
},
|
||||
HTMLElementTypeId::HTMLButtonElement => {
|
||||
|
@ -981,10 +980,30 @@ impl HTMLFormElement {
|
|||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
// Step: 5.13. Add an entry if element has dirname attribute
|
||||
// An element can only have a dirname attribute if it is a textarea element
|
||||
// or an input element whose type attribute is in either the Text state or the Search state
|
||||
let child_element = child.downcast::<Element>().unwrap();
|
||||
let input_matches =
|
||||
child_element
|
||||
.downcast::<HTMLInputElement>()
|
||||
.map_or(false, |input| {
|
||||
input.input_type() == InputType::Text ||
|
||||
input.input_type() == InputType::Search
|
||||
});
|
||||
let textarea_matches = child_element.is::<HTMLTextAreaElement>();
|
||||
let dirname = child_element.get_string_attribute(&local_name!("dirname"));
|
||||
if (input_matches || textarea_matches) && !dirname.is_empty() {
|
||||
let dir = DOMString::from(child_element.directionality());
|
||||
data_set.push(FormDatum {
|
||||
ty: DOMString::from("string"),
|
||||
name: dirname,
|
||||
value: FormDatumValue::String(dir),
|
||||
});
|
||||
}
|
||||
}
|
||||
data_set
|
||||
// TODO: Handle `dirnames` (needs directionality support)
|
||||
// https://html.spec.whatwg.org/multipage/#the-directionality
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#constructing-the-form-data-set>
|
||||
|
|
|
@ -75,6 +75,7 @@ use std::ptr::NonNull;
|
|||
use style::attr::AttrValue;
|
||||
use style::element_state::ElementState;
|
||||
use style::str::{split_commas, str_join};
|
||||
use unicode_bidi::{bidi_class, BidiClass};
|
||||
|
||||
const DEFAULT_SUBMIT_VALUE: &'static str = "Submit";
|
||||
const DEFAULT_RESET_VALUE: &'static str = "Reset";
|
||||
|
@ -327,6 +328,36 @@ impl HTMLInputElement {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn auto_directionality(&self) -> Option<String> {
|
||||
match self.input_type() {
|
||||
InputType::Text | InputType::Search | InputType::Url | InputType::Email => {
|
||||
let value: String = self.Value().to_string();
|
||||
Some(HTMLInputElement::directionality_from_value(&value))
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn directionality_from_value(value: &str) -> String {
|
||||
if HTMLInputElement::is_first_strong_character_rtl(value) {
|
||||
"rtl".to_owned()
|
||||
} else {
|
||||
"ltr".to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
fn is_first_strong_character_rtl(value: &str) -> bool {
|
||||
for ch in value.chars() {
|
||||
return match bidi_class(ch) {
|
||||
BidiClass::L => false,
|
||||
BidiClass::AL => true,
|
||||
BidiClass::R => true,
|
||||
_ => continue,
|
||||
};
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-input-value
|
||||
// https://html.spec.whatwg.org/multipage/#concept-input-apply
|
||||
fn value_mode(&self) -> ValueMode {
|
||||
|
|
|
@ -22,6 +22,7 @@ use crate::dom::globalscope::GlobalScope;
|
|||
use crate::dom::htmlelement::HTMLElement;
|
||||
use crate::dom::htmlfieldsetelement::HTMLFieldSetElement;
|
||||
use crate::dom::htmlformelement::{FormControl, HTMLFormElement};
|
||||
use crate::dom::htmlinputelement::HTMLInputElement;
|
||||
use crate::dom::keyboardevent::KeyboardEvent;
|
||||
use crate::dom::node::{document_from_node, window_from_node};
|
||||
use crate::dom::node::{
|
||||
|
@ -173,6 +174,11 @@ impl HTMLTextAreaElement {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn auto_directionality(&self) -> String {
|
||||
let value: String = self.Value().to_string();
|
||||
return HTMLInputElement::directionality_from_value(&value);
|
||||
}
|
||||
|
||||
fn update_placeholder_shown_state(&self) {
|
||||
let has_placeholder = !self.placeholder.borrow().is_empty();
|
||||
let has_value = !self.textinput.borrow().is_empty();
|
||||
|
@ -205,6 +211,12 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
|
|||
// https://html.spec.whatwg.org/multipage/#dom-textarea-cols
|
||||
make_limited_uint_setter!(SetCols, "cols", DEFAULT_COLS);
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-input-dirName
|
||||
make_getter!(DirName, "dirname");
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-input-dirName
|
||||
make_setter!(SetDirName, "dirname");
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-fe-disabled
|
||||
make_bool_getter!(Disabled, "disabled");
|
||||
|
||||
|
|
|
@ -440,6 +440,26 @@ impl Node {
|
|||
.upcast::<Event>()
|
||||
.dispatch(self.upcast::<EventTarget>(), false);
|
||||
}
|
||||
|
||||
pub fn parent_directionality(&self) -> String {
|
||||
let mut current = self.GetParentNode();
|
||||
|
||||
loop {
|
||||
match current {
|
||||
Some(node) => {
|
||||
if let Some(directionality) = node
|
||||
.downcast::<HTMLElement>()
|
||||
.and_then(|html_element| html_element.directionality())
|
||||
{
|
||||
return directionality;
|
||||
} else {
|
||||
current = node.GetParentNode();
|
||||
}
|
||||
},
|
||||
None => return "ltr".to_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct QuerySelectorIterator {
|
||||
|
|
|
@ -14,8 +14,8 @@ interface HTMLElement : Element {
|
|||
attribute DOMString lang;
|
||||
[CEReactions]
|
||||
attribute boolean translate;
|
||||
// [CEReactions]
|
||||
// attribute DOMString dir;
|
||||
[CEReactions]
|
||||
attribute DOMString dir;
|
||||
readonly attribute DOMStringMap dataset;
|
||||
|
||||
// microdata
|
||||
|
|
|
@ -13,8 +13,8 @@ interface HTMLTextAreaElement : HTMLElement {
|
|||
// attribute boolean autofocus;
|
||||
[CEReactions, SetterThrows]
|
||||
attribute unsigned long cols;
|
||||
// [CEReactions]
|
||||
// attribute DOMString dirName;
|
||||
[CEReactions]
|
||||
attribute DOMString dirName;
|
||||
[CEReactions]
|
||||
attribute boolean disabled;
|
||||
readonly attribute HTMLFormElement? form;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue