mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
webdriver: Implement element clear (#38208)
Initial Implementation of [Element Clear](https://w3c.github.io/webdriver/#element-clear). Testing: `tests/wpt/tests/webdriver/tests/classic/element_clear/` --------- Signed-off-by: PotatoCP <Kenzie.Raditya.Tirtarahardja@huawei.com> Signed-off-by: Kenzie Raditya Tirtarahardja <kenzieradityatirtarahardja18@gmail.com> Co-authored-by: Euclid Ye <yezhizhenjiakang@gmail.com> Co-authored-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
parent
1fb782bc38
commit
4b12ae73fe
11 changed files with 175 additions and 367 deletions
|
@ -41,6 +41,7 @@ use crate::dom::bindings::codegen::Bindings::HTMLElementBinding::HTMLElementMeth
|
|||
use crate::dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::HTMLOptionElementBinding::HTMLOptionElementMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::HTMLSelectElementBinding::HTMLSelectElementMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding::HTMLTextAreaElementMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::NodeBinding::{GetRootNodeOptions, NodeMethods};
|
||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::XMLSerializerBinding::XMLSerializerMethods;
|
||||
|
@ -64,11 +65,13 @@ use crate::dom::globalscope::GlobalScope;
|
|||
use crate::dom::htmlbodyelement::HTMLBodyElement;
|
||||
use crate::dom::htmldatalistelement::HTMLDataListElement;
|
||||
use crate::dom::htmlelement::HTMLElement;
|
||||
use crate::dom::htmlformelement::FormControl;
|
||||
use crate::dom::htmliframeelement::HTMLIFrameElement;
|
||||
use crate::dom::htmlinputelement::{HTMLInputElement, InputType};
|
||||
use crate::dom::htmloptgroupelement::HTMLOptGroupElement;
|
||||
use crate::dom::htmloptionelement::HTMLOptionElement;
|
||||
use crate::dom::htmlselectelement::HTMLSelectElement;
|
||||
use crate::dom::htmltextareaelement::HTMLTextAreaElement;
|
||||
use crate::dom::node::{Node, NodeTraits, ShadowIncluding};
|
||||
use crate::dom::nodelist::NodeList;
|
||||
use crate::dom::types::ShadowRoot;
|
||||
|
@ -1651,6 +1654,107 @@ pub(crate) fn handle_get_url(
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
/// <https://w3c.github.io/webdriver/#dfn-mutable-form-control-element>
|
||||
fn element_is_mutable_form_control(element: &Element) -> bool {
|
||||
if let Some(input_element) = element.downcast::<HTMLInputElement>() {
|
||||
input_element.is_mutable() &&
|
||||
matches!(
|
||||
input_element.input_type(),
|
||||
InputType::Text |
|
||||
InputType::Search |
|
||||
InputType::Url |
|
||||
InputType::Tel |
|
||||
InputType::Email |
|
||||
InputType::Password |
|
||||
InputType::Date |
|
||||
InputType::Month |
|
||||
InputType::Week |
|
||||
InputType::Time |
|
||||
InputType::DatetimeLocal |
|
||||
InputType::Number |
|
||||
InputType::Range |
|
||||
InputType::Color |
|
||||
InputType::File
|
||||
)
|
||||
} else if let Some(textarea_element) = element.downcast::<HTMLTextAreaElement>() {
|
||||
textarea_element.is_mutable()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://w3c.github.io/webdriver/#dfn-clear-a-resettable-element>
|
||||
fn clear_a_resettable_element(element: &Element, can_gc: CanGc) -> Result<(), ErrorStatus> {
|
||||
let html_element = element
|
||||
.downcast::<HTMLElement>()
|
||||
.ok_or(ErrorStatus::UnknownError)?;
|
||||
|
||||
// Step 1 - 2. if element is a candidate for constraint
|
||||
// validation and value is empty, abort steps.
|
||||
if html_element.is_candidate_for_constraint_validation() {
|
||||
if let Some(input_element) = element.downcast::<HTMLInputElement>() {
|
||||
if input_element.Value().is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
} else if let Some(textarea_element) = element.downcast::<HTMLTextAreaElement>() {
|
||||
if textarea_element.Value().is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3. Invoke the focusing steps for the element.
|
||||
html_element.Focus(can_gc);
|
||||
|
||||
// Step 4. Run clear algorithm for element.
|
||||
if let Some(input_element) = element.downcast::<HTMLInputElement>() {
|
||||
input_element.clear(can_gc);
|
||||
} else if let Some(textarea_element) = element.downcast::<HTMLTextAreaElement>() {
|
||||
textarea_element.clear();
|
||||
} else {
|
||||
unreachable!("We have confirm previously that element is mutable form control");
|
||||
}
|
||||
|
||||
let event_target = element.upcast::<EventTarget>();
|
||||
event_target.fire_bubbling_event(atom!("input"), can_gc);
|
||||
event_target.fire_bubbling_event(atom!("change"), can_gc);
|
||||
|
||||
// Step 5. Run the unfocusing steps for the element.
|
||||
html_element.Blur(can_gc);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// <https://w3c.github.io/webdriver/#element-clear>
|
||||
pub(crate) fn handle_element_clear(
|
||||
documents: &DocumentCollection,
|
||||
pipeline: PipelineId,
|
||||
element_id: String,
|
||||
reply: IpcSender<Result<(), ErrorStatus>>,
|
||||
can_gc: CanGc,
|
||||
) {
|
||||
reply
|
||||
.send(
|
||||
get_known_element(documents, pipeline, element_id).and_then(|element| {
|
||||
// Step 4. If element is not editable, return ErrorStatus::InvalidElementState.
|
||||
// TODO: editing hosts and content editable elements are not implemented yet,
|
||||
// hence we currently skip the check
|
||||
if !element_is_mutable_form_control(&element) {
|
||||
return Err(ErrorStatus::InvalidElementState);
|
||||
}
|
||||
|
||||
// TODO: Step 5. Scroll Into View
|
||||
// TODO: Step 6 - 10
|
||||
// Wait until element become interactable and check.
|
||||
|
||||
// Step 11
|
||||
// TODO: Clear content editable elements
|
||||
clear_a_resettable_element(&element, can_gc)
|
||||
}),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn get_option_parent(node: &Node) -> Option<DomRoot<Node>> {
|
||||
// Get parent for `<option>` or `<optiongrp>` based on container spec:
|
||||
// > 1. Let datalist parent be the first datalist element reached by traversing the tree
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue