Skip to content

Commit

Permalink
Implement dirname for form submit and directionality for element
Browse files Browse the repository at this point in the history
  • Loading branch information
NeverHappened committed Feb 24, 2020
1 parent 6bc4a7d commit ef49f2e
Show file tree
Hide file tree
Showing 14 changed files with 178 additions and 19 deletions.
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion components/constellation/constellation.rs
Expand Up @@ -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
);
},
Expand Down
2 changes: 1 addition & 1 deletion components/embedder_traits/lib.rs
Expand Up @@ -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>),
Expand Down
1 change: 1 addition & 0 deletions components/script/Cargo.toml
Expand Up @@ -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"
Expand Down
64 changes: 64 additions & 0 deletions components/script/dom/element.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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)]
Expand Down
5 changes: 5 additions & 0 deletions components/script/dom/htmlelement.rs
Expand Up @@ -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);

Expand Down
18 changes: 16 additions & 2 deletions components/script/dom/htmlformelement.rs
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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>
Expand Down
36 changes: 36 additions & 0 deletions components/script/dom/htmlinputelement.rs
Expand Up @@ -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";
Expand Down Expand Up @@ -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 {
Expand Down
9 changes: 9 additions & 0 deletions components/script/dom/htmltextareaelement.rs
Expand Up @@ -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::{
Expand Down Expand Up @@ -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();
Expand Down
4 changes: 2 additions & 2 deletions components/script/dom/webidls/HTMLElement.webidl
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions components/script/dom/window.rs
Expand Up @@ -2017,6 +2017,7 @@ impl Window {
}
// TODO: step 11, navigationType.
// Step 12, 13
println!("ScriptThread::navigate");
ScriptThread::navigate(pipeline_id, load_data, replace);
};
}
Expand Down

This file was deleted.

Expand Up @@ -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>

0 comments on commit ef49f2e

Please sign in to comment.