mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Auto merge of #13969 - bbansalWolfPack:master, r=jdm
html form validation initial steps with test html file <!-- Please describe your changes on the following line: --> Added code for initial steps in html form validation. 1. Added methods for trait validatable 2. implemented stub methods for elements like HTMLInputElement, HTMLButtonElement, etc <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X ] `./mach build -d` does not report any errors - [ X] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/13969) <!-- Reviewable:end -->
This commit is contained in:
commit
beec035eb0
9 changed files with 124 additions and 15 deletions
13
components/script/dom/htmlbuttonelement.rs
Normal file → Executable file
13
components/script/dom/htmlbuttonelement.rs
Normal file → Executable file
|
@ -21,7 +21,7 @@ use dom::htmlformelement::HTMLFormElement;
|
||||||
use dom::node::{Node, UnbindContext, document_from_node, window_from_node};
|
use dom::node::{Node, UnbindContext, document_from_node, window_from_node};
|
||||||
use dom::nodelist::NodeList;
|
use dom::nodelist::NodeList;
|
||||||
use dom::validation::Validatable;
|
use dom::validation::Validatable;
|
||||||
use dom::validitystate::ValidityState;
|
use dom::validitystate::{ValidityState, ValidationFlags};
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
use html5ever_atoms::LocalName;
|
use html5ever_atoms::LocalName;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
@ -238,7 +238,16 @@ impl VirtualMethods for HTMLButtonElement {
|
||||||
|
|
||||||
impl FormControl for HTMLButtonElement {}
|
impl FormControl for HTMLButtonElement {}
|
||||||
|
|
||||||
impl Validatable for HTMLButtonElement {}
|
impl Validatable for HTMLButtonElement {
|
||||||
|
fn is_instance_validatable(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
fn validate(&self, validate_flags: ValidationFlags) -> bool {
|
||||||
|
if validate_flags.is_empty() {}
|
||||||
|
// Need more flag check for different validation types later
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Activatable for HTMLButtonElement {
|
impl Activatable for HTMLButtonElement {
|
||||||
fn as_element(&self) -> &Element {
|
fn as_element(&self) -> &Element {
|
||||||
|
|
45
components/script/dom/htmlformelement.rs
Normal file → Executable file
45
components/script/dom/htmlformelement.rs
Normal file → Executable file
|
@ -35,6 +35,7 @@ use dom::htmloutputelement::HTMLOutputElement;
|
||||||
use dom::htmlselectelement::HTMLSelectElement;
|
use dom::htmlselectelement::HTMLSelectElement;
|
||||||
use dom::htmltextareaelement::HTMLTextAreaElement;
|
use dom::htmltextareaelement::HTMLTextAreaElement;
|
||||||
use dom::node::{Node, document_from_node, window_from_node};
|
use dom::node::{Node, document_from_node, window_from_node};
|
||||||
|
use dom::validitystate::ValidationFlags;
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
use encoding::EncodingRef;
|
use encoding::EncodingRef;
|
||||||
use encoding::all::UTF_8;
|
use encoding::all::UTF_8;
|
||||||
|
@ -470,12 +471,22 @@ impl HTMLFormElement {
|
||||||
// form, refactor this when html5ever's form owner PR lands
|
// form, refactor this when html5ever's form owner PR lands
|
||||||
// Step 1-3
|
// Step 1-3
|
||||||
let invalid_controls = node.traverse_preorder().filter_map(|field| {
|
let invalid_controls = node.traverse_preorder().filter_map(|field| {
|
||||||
if let Some(_el) = field.downcast::<Element>() {
|
if let Some(el) = field.downcast::<Element>() {
|
||||||
None // Remove this line if you decide to refactor
|
if el.disabled_state() {
|
||||||
|
None
|
||||||
// XXXKiChjang: Form control elements should each have a candidate_for_validation
|
} else {
|
||||||
// and satisfies_constraints methods
|
let validatable = match el.as_maybe_validatable() {
|
||||||
|
Some(v) => v,
|
||||||
|
None => return None
|
||||||
|
};
|
||||||
|
if !validatable.is_instance_validatable() {
|
||||||
|
None
|
||||||
|
} else if validatable.validate(ValidationFlags::empty()) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(FormSubmittableElement::from_element(&el))
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -697,7 +708,7 @@ pub enum FormSubmittableElement {
|
||||||
// KeygenElement(&'a HTMLKeygenElement),
|
// KeygenElement(&'a HTMLKeygenElement),
|
||||||
ObjectElement(Root<HTMLObjectElement>),
|
ObjectElement(Root<HTMLObjectElement>),
|
||||||
SelectElement(Root<HTMLSelectElement>),
|
SelectElement(Root<HTMLSelectElement>),
|
||||||
TextAreaElement(Root<HTMLTextAreaElement>)
|
TextAreaElement(Root<HTMLTextAreaElement>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FormSubmittableElement {
|
impl FormSubmittableElement {
|
||||||
|
@ -710,6 +721,26 @@ impl FormSubmittableElement {
|
||||||
FormSubmittableElement::TextAreaElement(ref textarea) => textarea.upcast()
|
FormSubmittableElement::TextAreaElement(ref textarea) => textarea.upcast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn from_element(element: &Element) -> FormSubmittableElement {
|
||||||
|
if let Some(input) = element.downcast::<HTMLInputElement>() {
|
||||||
|
FormSubmittableElement::InputElement(Root::from_ref(&input))
|
||||||
|
}
|
||||||
|
else if let Some(input) = element.downcast::<HTMLButtonElement>() {
|
||||||
|
FormSubmittableElement::ButtonElement(Root::from_ref(&input))
|
||||||
|
}
|
||||||
|
else if let Some(input) = element.downcast::<HTMLObjectElement>() {
|
||||||
|
FormSubmittableElement::ObjectElement(Root::from_ref(&input))
|
||||||
|
}
|
||||||
|
else if let Some(input) = element.downcast::<HTMLSelectElement>() {
|
||||||
|
FormSubmittableElement::SelectElement(Root::from_ref(&input))
|
||||||
|
}
|
||||||
|
else if let Some(input) = element.downcast::<HTMLTextAreaElement>() {
|
||||||
|
FormSubmittableElement::TextAreaElement(Root::from_ref(&input))
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, HeapSizeOf)]
|
#[derive(Copy, Clone, HeapSizeOf)]
|
||||||
|
|
12
components/script/dom/htmlinputelement.rs
Normal file → Executable file
12
components/script/dom/htmlinputelement.rs
Normal file → Executable file
|
@ -31,6 +31,7 @@ use dom::node::{Node, NodeDamage, UnbindContext};
|
||||||
use dom::node::{document_from_node, window_from_node};
|
use dom::node::{document_from_node, window_from_node};
|
||||||
use dom::nodelist::NodeList;
|
use dom::nodelist::NodeList;
|
||||||
use dom::validation::Validatable;
|
use dom::validation::Validatable;
|
||||||
|
use dom::validitystate::ValidationFlags;
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
use html5ever_atoms::LocalName;
|
use html5ever_atoms::LocalName;
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::{self, IpcSender};
|
||||||
|
@ -1131,7 +1132,16 @@ impl VirtualMethods for HTMLInputElement {
|
||||||
|
|
||||||
impl FormControl for HTMLInputElement {}
|
impl FormControl for HTMLInputElement {}
|
||||||
|
|
||||||
impl Validatable for HTMLInputElement {}
|
impl Validatable for HTMLInputElement {
|
||||||
|
fn is_instance_validatable(&self) -> bool {
|
||||||
|
// https://html.spec.whatwg.org/multipage/#candidate-for-constraint-validation
|
||||||
|
true
|
||||||
|
}
|
||||||
|
fn validate(&self, _validate_flags: ValidationFlags) -> bool {
|
||||||
|
// call stub methods defined in validityState.rs file here according to the flags set in validate_flags
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Activatable for HTMLInputElement {
|
impl Activatable for HTMLInputElement {
|
||||||
fn as_element(&self) -> &Element {
|
fn as_element(&self) -> &Element {
|
||||||
|
|
13
components/script/dom/htmlobjectelement.rs
Normal file → Executable file
13
components/script/dom/htmlobjectelement.rs
Normal file → Executable file
|
@ -15,7 +15,7 @@ use dom::htmlelement::HTMLElement;
|
||||||
use dom::htmlformelement::{FormControl, HTMLFormElement};
|
use dom::htmlformelement::{FormControl, HTMLFormElement};
|
||||||
use dom::node::{Node, window_from_node};
|
use dom::node::{Node, window_from_node};
|
||||||
use dom::validation::Validatable;
|
use dom::validation::Validatable;
|
||||||
use dom::validitystate::ValidityState;
|
use dom::validitystate::{ValidityState, ValidationFlags};
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
use html5ever_atoms::LocalName;
|
use html5ever_atoms::LocalName;
|
||||||
use net_traits::image::base::Image;
|
use net_traits::image::base::Image;
|
||||||
|
@ -89,7 +89,16 @@ impl HTMLObjectElementMethods for HTMLObjectElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validatable for HTMLObjectElement {}
|
impl Validatable for HTMLObjectElement {
|
||||||
|
fn is_instance_validatable(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
fn validate(&self, validate_flags: ValidationFlags) -> bool {
|
||||||
|
if validate_flags.is_empty() {}
|
||||||
|
// Need more flag check for different validation types later
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl VirtualMethods for HTMLObjectElement {
|
impl VirtualMethods for HTMLObjectElement {
|
||||||
fn super_type(&self) -> Option<&VirtualMethods> {
|
fn super_type(&self) -> Option<&VirtualMethods> {
|
||||||
|
|
13
components/script/dom/htmlselectelement.rs
Normal file → Executable file
13
components/script/dom/htmlselectelement.rs
Normal file → Executable file
|
@ -28,7 +28,7 @@ use dom::htmloptionscollection::HTMLOptionsCollection;
|
||||||
use dom::node::{Node, UnbindContext, window_from_node};
|
use dom::node::{Node, UnbindContext, window_from_node};
|
||||||
use dom::nodelist::NodeList;
|
use dom::nodelist::NodeList;
|
||||||
use dom::validation::Validatable;
|
use dom::validation::Validatable;
|
||||||
use dom::validitystate::ValidityState;
|
use dom::validitystate::{ValidityState, ValidationFlags};
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
use html5ever_atoms::LocalName;
|
use html5ever_atoms::LocalName;
|
||||||
use style::attr::AttrValue;
|
use style::attr::AttrValue;
|
||||||
|
@ -384,4 +384,13 @@ impl VirtualMethods for HTMLSelectElement {
|
||||||
|
|
||||||
impl FormControl for HTMLSelectElement {}
|
impl FormControl for HTMLSelectElement {}
|
||||||
|
|
||||||
impl Validatable for HTMLSelectElement {}
|
impl Validatable for HTMLSelectElement {
|
||||||
|
fn is_instance_validatable(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
fn validate(&self, validate_flags: ValidationFlags) -> bool {
|
||||||
|
if validate_flags.is_empty() {}
|
||||||
|
// Need more flag check for different validation types later
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
1
components/script/dom/htmltextareaelement.rs
Normal file → Executable file
1
components/script/dom/htmltextareaelement.rs
Normal file → Executable file
|
@ -406,4 +406,5 @@ impl VirtualMethods for HTMLTextAreaElement {
|
||||||
|
|
||||||
impl FormControl for HTMLTextAreaElement {}
|
impl FormControl for HTMLTextAreaElement {}
|
||||||
|
|
||||||
|
|
||||||
impl Validatable for HTMLTextAreaElement {}
|
impl Validatable for HTMLTextAreaElement {}
|
||||||
|
|
6
components/script/dom/validation.rs
Normal file → Executable file
6
components/script/dom/validation.rs
Normal file → Executable file
|
@ -1,5 +1,9 @@
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
use dom::validitystate::ValidationFlags;
|
||||||
|
|
||||||
pub trait Validatable {}
|
pub trait Validatable {
|
||||||
|
fn is_instance_validatable(&self) -> bool { true }
|
||||||
|
fn validate(&self, _validate_flags: ValidationFlags) -> bool { true }
|
||||||
|
}
|
||||||
|
|
15
components/script/dom/validitystate.rs
Normal file → Executable file
15
components/script/dom/validitystate.rs
Normal file → Executable file
|
@ -26,6 +26,21 @@ pub enum ValidityStatus {
|
||||||
Valid
|
Valid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bitflags!{
|
||||||
|
pub flags ValidationFlags: u32 {
|
||||||
|
const VALUE_MISSING = 0b0000000001,
|
||||||
|
const TYPE_MISMATCH = 0b0000000010,
|
||||||
|
const PATTERN_MISMATCH = 0b0000000100,
|
||||||
|
const TOO_LONG = 0b0000001000,
|
||||||
|
const TOO_SHORT = 0b0000010000,
|
||||||
|
const RANGE_UNDERFLOW = 0b0000100000,
|
||||||
|
const RANGE_OVERFLOW = 0b0001000000,
|
||||||
|
const STEP_MISMATCH = 0b0010000000,
|
||||||
|
const BAD_INPUT = 0b0100000000,
|
||||||
|
const CUSTOM_ERROR = 0b1000000000,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#validitystate
|
// https://html.spec.whatwg.org/multipage/#validitystate
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct ValidityState {
|
pub struct ValidityState {
|
||||||
|
|
21
tests/html/html_validation_test.html
Normal file
21
tests/html/html_validation_test.html
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<form>
|
||||||
|
First name:<br>
|
||||||
|
<input type="text" name="firstname" value="Mickey" required>
|
||||||
|
<br>
|
||||||
|
Last name:<br>
|
||||||
|
<input type="text" name="lastname" value="Mouse" required>
|
||||||
|
<br><br>
|
||||||
|
<input type="submit" value="Submit">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<p>If you click the "Submit" button, the form-data will be sent to a page called "action_page.php".</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue