mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Rearrange directionality algorithm functions
This commit is contained in:
parent
cb34e5c887
commit
7d6d1c09cb
9 changed files with 141 additions and 95 deletions
|
@ -12,7 +12,6 @@ use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::ElementBinding;
|
use crate::dom::bindings::codegen::Bindings::ElementBinding;
|
||||||
use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
|
use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::FunctionBinding::Function;
|
use crate::dom::bindings::codegen::Bindings::FunctionBinding::Function;
|
||||||
use crate::dom::bindings::codegen::Bindings::HTMLElementBinding::HTMLElementBinding::HTMLElementMethods;
|
|
||||||
use crate::dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods;
|
use crate::dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRootBinding::ShadowRootMethods;
|
use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRootBinding::ShadowRootMethods;
|
||||||
|
@ -542,66 +541,13 @@ impl Element {
|
||||||
true // whatwg/html#5239
|
true // whatwg/html#5239
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/#the-directionality
|
// https://html.spec.whatwg.org/multipage/#the-directionality
|
||||||
pub fn directionality(&self) -> String {
|
pub fn directionality(&self) -> String {
|
||||||
if self.is::<HTMLElement>() {
|
if let Some(html_element) = self.downcast::<HTMLElement>() {
|
||||||
let htmlElement = self.downcast::<HTMLElement>().unwrap();
|
html_element.directionality()
|
||||||
self.html_element_directionality(&htmlElement.Dir())
|
|
||||||
} else {
|
} else {
|
||||||
let node = self.upcast::<Node>();
|
let node = self.upcast::<Node>();
|
||||||
self.parent_directionality(node)
|
node.parent_directionality()
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn html_element_directionality(&self, element_direction: &str) -> String {
|
|
||||||
if element_direction == "ltr" {
|
|
||||||
return "ltr".to_owned();
|
|
||||||
}
|
|
||||||
|
|
||||||
if element_direction == "rtl" {
|
|
||||||
return "rtl".to_owned();
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.is::<HTMLInputElement>() {
|
|
||||||
let input = self.downcast::<HTMLInputElement>().unwrap();
|
|
||||||
return input.directionality(element_direction);
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.is::<HTMLTextAreaElement>() {
|
|
||||||
let area = self.downcast::<HTMLTextAreaElement>().unwrap();
|
|
||||||
return area.directionality(element_direction);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(dmitry.klpv): 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/#the-bdi-element)
|
|
||||||
|
|
||||||
let node = self.upcast::<Node>();
|
|
||||||
self.parent_directionality(node)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parent_directionality(&self, node: &Node) -> String {
|
|
||||||
if !node.has_parent() {
|
|
||||||
return "ltr".to_owned();
|
|
||||||
}
|
|
||||||
|
|
||||||
let parent = node.GetParentNode();
|
|
||||||
match parent {
|
|
||||||
Some(parent) => {
|
|
||||||
if parent.is::<Document>() {
|
|
||||||
return "ltr".to_owned();
|
|
||||||
}
|
|
||||||
|
|
||||||
return if parent.is::<Element>() {
|
|
||||||
let parentHtml = parent.downcast::<Element>().unwrap();
|
|
||||||
parentHtml.directionality()
|
|
||||||
} else {
|
|
||||||
self.parent_directionality(&*parent)
|
|
||||||
};
|
|
||||||
},
|
|
||||||
None => "ltr".to_owned(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ use crate::dom::htmlframesetelement::HTMLFrameSetElement;
|
||||||
use crate::dom::htmlhtmlelement::HTMLHtmlElement;
|
use crate::dom::htmlhtmlelement::HTMLHtmlElement;
|
||||||
use crate::dom::htmlinputelement::{HTMLInputElement, InputType};
|
use crate::dom::htmlinputelement::{HTMLInputElement, InputType};
|
||||||
use crate::dom::htmllabelelement::HTMLLabelElement;
|
use crate::dom::htmllabelelement::HTMLLabelElement;
|
||||||
|
use crate::dom::htmltextareaelement::HTMLTextAreaElement;
|
||||||
use crate::dom::node::{document_from_node, window_from_node};
|
use crate::dom::node::{document_from_node, window_from_node};
|
||||||
use crate::dom::node::{BindContext, Node, NodeFlags, ShadowIncluding};
|
use crate::dom::node::{BindContext, Node, NodeFlags, ShadowIncluding};
|
||||||
use crate::dom::text::Text;
|
use crate::dom::text::Text;
|
||||||
|
@ -170,9 +171,9 @@ impl HTMLElementMethods for HTMLElement {
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-hidden
|
// https://html.spec.whatwg.org/multipage/#dom-hidden
|
||||||
make_bool_setter!(SetHidden, "hidden");
|
make_bool_setter!(SetHidden, "hidden");
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute
|
// https://html.spec.whatwg.org/multipage/#the-dir-attribute
|
||||||
make_getter!(Dir, "dir");
|
make_getter!(Dir, "dir");
|
||||||
// https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute
|
// https://html.spec.whatwg.org/multipage/#the-dir-attribute
|
||||||
make_setter!(SetDir, "dir");
|
make_setter!(SetDir, "dir");
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#globaleventhandlers
|
// https://html.spec.whatwg.org/multipage/#globaleventhandlers
|
||||||
|
@ -772,6 +773,39 @@ impl HTMLElement {
|
||||||
})
|
})
|
||||||
.count() as u32
|
.count() as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn directionality(&self) -> String {
|
||||||
|
println!("HTMLElement#directionality");
|
||||||
|
let element_direction: &str = &self.Dir();
|
||||||
|
println!("HTMLElement#element_direction={}", element_direction);
|
||||||
|
|
||||||
|
if element_direction == "ltr" {
|
||||||
|
return "ltr".to_owned();
|
||||||
|
}
|
||||||
|
|
||||||
|
if element_direction == "rtl" {
|
||||||
|
return "rtl".to_owned();
|
||||||
|
}
|
||||||
|
|
||||||
|
if element_direction == "auto" {
|
||||||
|
if let Some(directionality) = self.downcast::<HTMLInputElement>().and_then(|input| input.auto_directionality()) {
|
||||||
|
return directionality;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(area) = self.downcast::<HTMLTextAreaElement>() {
|
||||||
|
return 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)
|
||||||
|
|
||||||
|
let node = self.upcast::<Node>();
|
||||||
|
node.parent_directionality()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VirtualMethods for HTMLElement {
|
impl VirtualMethods for HTMLElement {
|
||||||
|
|
|
@ -951,6 +951,18 @@ impl HTMLFormElement {
|
||||||
HTMLElementTypeId::HTMLInputElement => {
|
HTMLElementTypeId::HTMLInputElement => {
|
||||||
let input = child.downcast::<HTMLInputElement>().unwrap();
|
let input = child.downcast::<HTMLInputElement>().unwrap();
|
||||||
data_set.append(&mut input.form_datums(submitter, encoding));
|
data_set.append(&mut input.form_datums(submitter, encoding));
|
||||||
|
|
||||||
|
let input_html_element = child.downcast::<HTMLElement>().unwrap();
|
||||||
|
let dirname: DOMString = input.DirName();
|
||||||
|
if !dirname.is_empty() {
|
||||||
|
let directionality =
|
||||||
|
DOMString::from(input_html_element.directionality());
|
||||||
|
data_set.push(FormDatum {
|
||||||
|
ty: input.Type().clone(),
|
||||||
|
name: dirname.clone(),
|
||||||
|
value: FormDatumValue::String(directionality),
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
HTMLElementTypeId::HTMLButtonElement => {
|
HTMLElementTypeId::HTMLButtonElement => {
|
||||||
let button = child.downcast::<HTMLButtonElement>().unwrap();
|
let button = child.downcast::<HTMLButtonElement>().unwrap();
|
||||||
|
@ -976,6 +988,18 @@ impl HTMLFormElement {
|
||||||
value: FormDatumValue::String(textarea.Value()),
|
value: FormDatumValue::String(textarea.Value()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let area_html_element = child.downcast::<HTMLElement>().unwrap();
|
||||||
|
let dirname: DOMString = textarea.DirName();
|
||||||
|
if !dirname.is_empty() {
|
||||||
|
let directionality =
|
||||||
|
DOMString::from(area_html_element.directionality());
|
||||||
|
data_set.push(FormDatum {
|
||||||
|
ty: textarea.Type().clone(),
|
||||||
|
name: dirname.clone(),
|
||||||
|
value: FormDatumValue::String(directionality),
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
|
@ -328,22 +328,18 @@ impl HTMLInputElement {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn directionality(&self, element_direction: &str) -> String {
|
pub fn auto_directionality(&self) -> Option<String> {
|
||||||
match self.input_type() {
|
match self.input_type() {
|
||||||
InputType::Tel => return "ltr".to_owned(),
|
InputType::Tel => return Some("ltr".to_owned()),
|
||||||
InputType::Text | InputType::Search | InputType::Url | InputType::Email => {
|
InputType::Text | InputType::Search | InputType::Url | InputType::Email => {
|
||||||
if element_direction == "auto" {
|
let value: String = self.Value().to_string();
|
||||||
let value: String = self.Value().to_string();
|
Some(HTMLInputElement::directionality_from_value(&value))
|
||||||
return HTMLInputElement::auto_directionality(&value);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|
||||||
return "ltr".to_owned();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn auto_directionality(value: &str) -> String {
|
pub fn directionality_from_value(value: &str) -> String {
|
||||||
if HTMLInputElement::first_strong_character_is_rtl(value) {
|
if HTMLInputElement::first_strong_character_is_rtl(value) {
|
||||||
"rtl".to_owned()
|
"rtl".to_owned()
|
||||||
} else {
|
} else {
|
||||||
|
@ -1473,25 +1469,11 @@ impl HTMLInputElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 5.12
|
// Step 5.12
|
||||||
let mut result = vec![FormDatum {
|
vec![FormDatum {
|
||||||
ty: ty.clone(),
|
ty: ty.clone(),
|
||||||
name: name,
|
name: name,
|
||||||
value: FormDatumValue::String(self.Value()),
|
value: FormDatumValue::String(self.Value()),
|
||||||
}];
|
}]
|
||||||
|
|
||||||
// 4.10.18.2
|
|
||||||
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#submitting-element-directionality:-the-dirname-attribute
|
|
||||||
let dirname: DOMString = self.DirName();
|
|
||||||
let directionality = DOMString::from(self.directionality("auto"));
|
|
||||||
if !dirname.is_empty() {
|
|
||||||
result.push(FormDatum {
|
|
||||||
ty: ty.clone(),
|
|
||||||
name: dirname.clone(),
|
|
||||||
value: FormDatumValue::String(directionality),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#radio-button-group
|
// https://html.spec.whatwg.org/multipage/#radio-button-group
|
||||||
|
|
|
@ -174,12 +174,9 @@ impl HTMLTextAreaElement {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn directionality(&self, element_direction: &str) -> String {
|
pub fn auto_directionality(&self) -> String {
|
||||||
if element_direction == "auto" {
|
let value: String = self.Value().to_string();
|
||||||
let value: String = self.Value().to_string();
|
return HTMLInputElement::directionality_from_value(&value);
|
||||||
return HTMLInputElement::auto_directionality(&value);
|
|
||||||
}
|
|
||||||
return "ltr".to_owned();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_placeholder_shown_state(&self) {
|
fn update_placeholder_shown_state(&self) {
|
||||||
|
@ -214,6 +211,12 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-textarea-cols
|
// https://html.spec.whatwg.org/multipage/#dom-textarea-cols
|
||||||
make_limited_uint_setter!(SetCols, "cols", DEFAULT_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
|
// https://html.spec.whatwg.org/multipage/#dom-fe-disabled
|
||||||
make_bool_getter!(Disabled, "disabled");
|
make_bool_getter!(Disabled, "disabled");
|
||||||
|
|
||||||
|
|
|
@ -432,6 +432,25 @@ impl Node {
|
||||||
.upcast::<Event>()
|
.upcast::<Event>()
|
||||||
.dispatch(self.upcast::<EventTarget>(), false);
|
.dispatch(self.upcast::<EventTarget>(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parent_directionality(&self) -> String {
|
||||||
|
println!("Node#parent_directionality");
|
||||||
|
match self.GetParentNode() {
|
||||||
|
Some(parent) => {
|
||||||
|
if parent.is::<Document>() {
|
||||||
|
return "ltr".to_owned();
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Node#parent_directionality Some(Parent)");
|
||||||
|
return if let Some(parent_html) = parent.downcast::<Element>() {
|
||||||
|
parent_html.directionality()
|
||||||
|
} else {
|
||||||
|
parent.parent_directionality()
|
||||||
|
};
|
||||||
|
},
|
||||||
|
None => "ltr".to_owned(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct QuerySelectorIterator {
|
pub struct QuerySelectorIterator {
|
||||||
|
|
|
@ -13,8 +13,8 @@ interface HTMLTextAreaElement : HTMLElement {
|
||||||
// attribute boolean autofocus;
|
// attribute boolean autofocus;
|
||||||
[CEReactions, SetterThrows]
|
[CEReactions, SetterThrows]
|
||||||
attribute unsigned long cols;
|
attribute unsigned long cols;
|
||||||
// [CEReactions]
|
[CEReactions]
|
||||||
// attribute DOMString dirName;
|
attribute DOMString dirName;
|
||||||
[CEReactions]
|
[CEReactions]
|
||||||
attribute boolean disabled;
|
attribute boolean disabled;
|
||||||
readonly attribute HTMLFormElement? form;
|
readonly attribute HTMLFormElement? form;
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>Submitting element directionality: the dirname attribute</title>
|
||||||
|
<link rel="author" title="Kolupaev Dmitry" href="mailto:dmitry.klpv@gmail.com">
|
||||||
|
<link rel=help href="https://html.spec.whatwg.org/multipage/#submitting-element-directionality:-the-dirname-attribute">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<div id="log"></div>
|
||||||
|
<div dir="rtl">
|
||||||
|
<form action="dirname-ltr-iframe.html" method=get target="iframe">
|
||||||
|
<p><label>Comment: <input type=text name="comment" dirname="comment.dir" required/></label></p>
|
||||||
|
<p><button type=submit>Post Comment</button></p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<iframe name="iframe"></iframe>
|
||||||
|
<script>
|
||||||
|
function getParameterByName(name) {
|
||||||
|
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
|
||||||
|
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
|
||||||
|
results = regex.exec(document.querySelector("iframe").contentWindow.location.search);
|
||||||
|
return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
|
||||||
|
}
|
||||||
|
|
||||||
|
var t = async_test("submit element directionality");
|
||||||
|
document.querySelector("input").value = "foobar";
|
||||||
|
document.querySelector("button").click();
|
||||||
|
|
||||||
|
var iframe = document.querySelector("iframe");
|
||||||
|
iframe.onload = t.step_func(function() {
|
||||||
|
// The initial about:blank load event can be fired before the form navigation occurs.
|
||||||
|
// See https://github.com/whatwg/html/issues/490 for more information.
|
||||||
|
if(iframe.contentWindow.location.href == "about:blank") { return; }
|
||||||
|
|
||||||
|
assert_equals(getParameterByName("comment.dir"), "rtl");
|
||||||
|
|
||||||
|
t.done();
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -7,7 +7,7 @@
|
||||||
<script src="/resources/testharnessreport.js"></script>
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
<div id="log"></div>
|
<div id="log"></div>
|
||||||
<form action="dirname-ltr-iframe.html" method=get target="iframe">
|
<form action="dirname-ltr-iframe.html" method=get target="iframe">
|
||||||
<p><label>Comment: <input type=text name="comment" dirname="comment.dir" required/></label></p>
|
<p><label>Comment: <input type=text name="comment" dir="auto" dirname="comment.dir" required/></label></p>
|
||||||
<p><button type=submit>Post Comment</button></p>
|
<p><button type=submit>Post Comment</button></p>
|
||||||
</form>
|
</form>
|
||||||
<iframe name="iframe"></iframe>
|
<iframe name="iframe"></iframe>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue