mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
Implement dirname for form submit and directionality for element
This commit is contained in:
parent
6bc4a7df24
commit
ef49f2e0eb
14 changed files with 178 additions and 19 deletions
6
Cargo.lock
generated
6
Cargo.lock
generated
|
@ -4783,6 +4783,7 @@ dependencies = [
|
|||
"tendril",
|
||||
"time",
|
||||
"tinyfiledialogs",
|
||||
"unicode-bidi",
|
||||
"unicode-segmentation",
|
||||
"url",
|
||||
"utf-8",
|
||||
|
@ -6291,13 +6292,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.3"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6a2c4e3710edd365cd7e78383153ed739fa31af19f9172f72d3575060f5a43a"
|
||||
checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
|
||||
dependencies = [
|
||||
"matches",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -1614,7 +1614,7 @@ where
|
|||
Some(ctx) => ctx.pipeline_id,
|
||||
None => {
|
||||
return warn!(
|
||||
"LoadUrl for unknow browsing context: {:?}",
|
||||
"LoadUrl for unknown browsing context: {:?}",
|
||||
top_level_browsing_context_id
|
||||
);
|
||||
},
|
||||
|
|
|
@ -149,7 +149,7 @@ pub enum EmbedderMsg {
|
|||
ResizeTo(DeviceIntSize),
|
||||
/// Show dialog to user
|
||||
Prompt(PromptDefinition, PromptOrigin),
|
||||
/// Wether or not to allow a pipeline to load a url.
|
||||
/// Whether or not to allow a pipeline to load a url.
|
||||
AllowNavigationRequest(PipelineId, ServoUrl),
|
||||
/// Whether or not to allow script to open a new tab/browser
|
||||
AllowOpeningBrowser(IpcSender<bool>),
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -12,6 +12,7 @@ use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
|
|||
use crate::dom::bindings::codegen::Bindings::ElementBinding;
|
||||
use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
|
||||
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::NodeBinding::NodeMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRootBinding::ShadowRootMethods;
|
||||
|
@ -540,6 +541,69 @@ impl Element {
|
|||
}
|
||||
true // whatwg/html#5239
|
||||
}
|
||||
|
||||
/// https://html.spec.whatwg.org/#the-directionality
|
||||
pub fn directionality(&self) -> String {
|
||||
if self.is::<HTMLElement>() {
|
||||
let htmlElement = self.downcast::<HTMLElement>().unwrap();
|
||||
self.html_element_directionality(&htmlElement.Dir())
|
||||
} else {
|
||||
let node = self.upcast::<Node>();
|
||||
self.parent_directionality(node)
|
||||
}
|
||||
}
|
||||
|
||||
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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
|
|
|
@ -170,6 +170,11 @@ impl HTMLElementMethods for HTMLElement {
|
|||
// https://html.spec.whatwg.org/multipage/#dom-hidden
|
||||
make_bool_setter!(SetHidden, "hidden");
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute
|
||||
make_getter!(Dir, "dir");
|
||||
// https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute
|
||||
make_setter!(SetDir, "dir");
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#globaleventhandlers
|
||||
global_event_handlers!(NoOnload);
|
||||
|
||||
|
|
|
@ -745,6 +745,8 @@ impl HTMLFormElement {
|
|||
.map(|field| (&*field.name, field.replace_value(charset))),
|
||||
);
|
||||
|
||||
println!("New URL: {url}", url = &load_data.url);
|
||||
|
||||
self.plan_to_navigate(load_data, target);
|
||||
}
|
||||
|
||||
|
@ -952,6 +954,20 @@ impl HTMLFormElement {
|
|||
let input = child.downcast::<HTMLInputElement>().unwrap();
|
||||
|
||||
data_set.append(&mut input.form_datums(submitter, encoding));
|
||||
|
||||
// TODO: probably move to input.form_datums(...) function
|
||||
// 4.10.18.2 https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#submitting-element-directionality:-the-dirname-attribute
|
||||
let dirname: DOMString = input.DirName();
|
||||
let dirname_str: &str = &*dirname;
|
||||
if !dirname_str.is_empty() {
|
||||
data_set.push(FormDatum {
|
||||
ty: input.Type(),
|
||||
name: DOMString::from_string(dirname_str.to_owned()),
|
||||
value: FormDatumValue::String(DOMString::from(
|
||||
input.directionality("auto"),
|
||||
)),
|
||||
});
|
||||
}
|
||||
},
|
||||
HTMLElementTypeId::HTMLButtonElement => {
|
||||
let button = child.downcast::<HTMLButtonElement>().unwrap();
|
||||
|
@ -983,8 +999,6 @@ impl HTMLFormElement {
|
|||
}
|
||||
}
|
||||
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,41 @@ impl HTMLInputElement {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn directionality(&self, element_direction: &str) -> String {
|
||||
match self.input_type() {
|
||||
InputType::Tel => return "ltr".to_owned(),
|
||||
InputType::Text | InputType::Search | InputType::Url | InputType::Email => {
|
||||
if element_direction == "auto" {
|
||||
let value: String = self.Value().to_string();
|
||||
return HTMLInputElement::auto_directionality(&value);
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
|
||||
return "ltr".to_owned();
|
||||
}
|
||||
|
||||
pub fn auto_directionality(value: &str) -> String {
|
||||
if HTMLInputElement::first_strong_character_is_rtl(value) {
|
||||
"rtl".to_owned()
|
||||
} else {
|
||||
"ltr".to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
fn first_strong_character_is_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,14 @@ impl HTMLTextAreaElement {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn directionality(&self, element_direction: &str) -> String {
|
||||
if element_direction == "auto" {
|
||||
let value: String = self.Value().to_string();
|
||||
return HTMLInputElement::auto_directionality(&value);
|
||||
}
|
||||
return "ltr".to_owned();
|
||||
}
|
||||
|
||||
fn update_placeholder_shown_state(&self) {
|
||||
let has_placeholder = !self.placeholder.borrow().is_empty();
|
||||
let has_value = !self.textinput.borrow().is_empty();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -2017,6 +2017,7 @@ impl Window {
|
|||
}
|
||||
// TODO: step 11, navigationType.
|
||||
// Step 12, 13
|
||||
println!("ScriptThread::navigate");
|
||||
ScriptThread::navigate(pipeline_id, load_data, replace);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
[dirname-ltr.html]
|
||||
type: testharness
|
||||
[submit element directionality]
|
||||
expected: FAIL
|
||||
|
|
@ -20,10 +20,12 @@
|
|||
}
|
||||
|
||||
var t = async_test("submit element directionality");
|
||||
document.querySelector("input").value="foobar";
|
||||
document.querySelector("button").click();
|
||||
setTimeout(function() {
|
||||
document.querySelector("input").value="foobar";
|
||||
document.querySelector("button").click();
|
||||
|
||||
document.querySelector("iframe").onload = t.step_func_done(function() {
|
||||
assert_equals(getParameterByName("comment.dir"), "ltr");
|
||||
});
|
||||
document.querySelector("iframe").onload = t.step_func_done(function() {
|
||||
assert_equals(getParameterByName("comment.dir"), "ltr");
|
||||
});
|
||||
}, 3000);
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Submitting element directionality: the dirname attribute</title>
|
||||
<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
|
||||
<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>
|
||||
<form action="dirname-ltr-iframe.html" method=get target="iframe">
|
||||
<p><label>Comment: <input type=text id="comment-input" name="comment" dirname="comment.dir" required/></label></p>
|
||||
<p><button type=submit>Post Comment</button></p>
|
||||
</form>
|
||||
<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");
|
||||
setTimeout(3000, function() {
|
||||
var rtlValue = "مرحبا";
|
||||
document.querySelector("input").value = rtlValue;
|
||||
document.querySelector("button").click();
|
||||
|
||||
document.querySelector("iframe").onload = t.step_func_done(function() {
|
||||
assert_equals(getParameterByName("comment.dir"), "rtl");
|
||||
});
|
||||
}, 3000);
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue