aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/htmlformelement.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/htmlformelement.rs')
-rw-r--r--components/script/dom/htmlformelement.rs111
1 files changed, 45 insertions, 66 deletions
diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs
index 08f2cf0499c..d3a23a2e3b0 100644
--- a/components/script/dom/htmlformelement.rs
+++ b/components/script/dom/htmlformelement.rs
@@ -8,6 +8,7 @@ use crate::dom::bindings::codegen::Bindings::BlobBinding::BlobMethods;
use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use crate::dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use crate::dom::bindings::codegen::Bindings::HTMLButtonElementBinding::HTMLButtonElementMethods;
+use crate::dom::bindings::codegen::Bindings::HTMLElementBinding::HTMLElementMethods;
use crate::dom::bindings::codegen::Bindings::HTMLFormControlsCollectionBinding::HTMLFormControlsCollectionMethods;
use crate::dom::bindings::codegen::Bindings::HTMLFormElementBinding::HTMLFormElementMethods;
use crate::dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods;
@@ -43,7 +44,7 @@ use crate::dom::htmloutputelement::HTMLOutputElement;
use crate::dom::htmlselectelement::HTMLSelectElement;
use crate::dom::htmltextareaelement::HTMLTextAreaElement;
use crate::dom::node::{document_from_node, window_from_node};
-use crate::dom::node::{Node, NodeFlags, ShadowIncluding};
+use crate::dom::node::{Node, NodeFlags};
use crate::dom::node::{UnbindContext, VecPreOrderInsertionHelper};
use crate::dom::nodelist::{NodeList, RadioListMode};
use crate::dom::radionodelist::RadioNodeList;
@@ -509,6 +510,16 @@ impl HTMLFormElementMethods for HTMLFormElement {
return names_vec;
}
+
+ // https://html.spec.whatwg.org/multipage/#dom-form-checkvalidity
+ fn CheckValidity(&self) -> bool {
+ self.static_validation().is_ok()
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-form-reportvalidity
+ fn ReportValidity(&self) -> bool {
+ self.interactive_validation().is_ok()
+ }
}
#[derive(Clone, Copy, MallocSizeOf, PartialEq)]
@@ -856,48 +867,56 @@ impl HTMLFormElement {
/// Interactively validate the constraints of form elements
/// <https://html.spec.whatwg.org/multipage/#interactively-validate-the-constraints>
fn interactive_validation(&self) -> Result<(), ()> {
- // Step 1-3
- let _unhandled_invalid_controls = match self.static_validation() {
+ // Step 1-2
+ let unhandled_invalid_controls = match self.static_validation() {
Ok(()) => return Ok(()),
Err(err) => err,
};
- // TODO: Report the problems with the constraints of at least one of
- // the elements given in unhandled invalid controls to the user
+
+ // Step 3
+ let mut first = true;
+
+ for elem in unhandled_invalid_controls {
+ if let Some(validatable) = elem.as_maybe_validatable() {
+ println!("Validation error: {}", validatable.validation_message());
+ }
+ if first {
+ if let Some(html_elem) = elem.downcast::<HTMLElement>() {
+ html_elem.Focus();
+ first = false;
+ }
+ }
+ }
+
// Step 4
Err(())
}
/// Statitically validate the constraints of form elements
/// <https://html.spec.whatwg.org/multipage/#statically-validate-the-constraints>
- fn static_validation(&self) -> Result<(), Vec<FormSubmittableElement>> {
- let node = self.upcast::<Node>();
- // FIXME(#3553): This is an incorrect way of getting controls owned by the
- // form, refactor this when html5ever's form owner PR lands
+ fn static_validation(&self) -> Result<(), Vec<DomRoot<Element>>> {
+ let controls = self.controls.borrow();
// Step 1-3
- let invalid_controls = node
- .traverse_preorder(ShadowIncluding::No)
+ let invalid_controls = controls
+ .iter()
.filter_map(|field| {
if let Some(el) = field.downcast::<Element>() {
- if el.disabled_state() {
+ let validatable = match el.as_maybe_validatable() {
+ Some(v) => v,
+ None => return None,
+ };
+ if !validatable.is_instance_validatable() {
+ None
+ } else if validatable.validate(ValidationFlags::all()).is_empty() {
None
} else {
- 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))
- }
+ Some(DomRoot::from_ref(el))
}
} else {
None
}
})
- .collect::<Vec<FormSubmittableElement>>();
+ .collect::<Vec<DomRoot<Element>>>();
// Step 4
if invalid_controls.is_empty() {
return Ok(());
@@ -907,14 +926,14 @@ impl HTMLFormElement {
.into_iter()
.filter_map(|field| {
let event = field
- .as_event_target()
+ .upcast::<EventTarget>()
.fire_cancelable_event(atom!("invalid"));
if !event.DefaultPrevented() {
return Some(field);
}
None
})
- .collect::<Vec<FormSubmittableElement>>();
+ .collect::<Vec<DomRoot<Element>>>();
// Step 7
Err(unhandled_invalid_controls)
}
@@ -1204,46 +1223,6 @@ pub enum FormMethod {
FormDialog,
}
-#[derive(MallocSizeOf)]
-#[allow(dead_code)]
-pub enum FormSubmittableElement {
- ButtonElement(DomRoot<HTMLButtonElement>),
- InputElement(DomRoot<HTMLInputElement>),
- // TODO: HTMLKeygenElement unimplemented
- // KeygenElement(&'a HTMLKeygenElement),
- ObjectElement(DomRoot<HTMLObjectElement>),
- SelectElement(DomRoot<HTMLSelectElement>),
- TextAreaElement(DomRoot<HTMLTextAreaElement>),
-}
-
-impl FormSubmittableElement {
- fn as_event_target(&self) -> &EventTarget {
- match *self {
- FormSubmittableElement::ButtonElement(ref button) => button.upcast(),
- FormSubmittableElement::InputElement(ref input) => input.upcast(),
- FormSubmittableElement::ObjectElement(ref object) => object.upcast(),
- FormSubmittableElement::SelectElement(ref select) => select.upcast(),
- FormSubmittableElement::TextAreaElement(ref textarea) => textarea.upcast(),
- }
- }
-
- fn from_element(element: &Element) -> FormSubmittableElement {
- if let Some(input) = element.downcast::<HTMLInputElement>() {
- FormSubmittableElement::InputElement(DomRoot::from_ref(&input))
- } else if let Some(input) = element.downcast::<HTMLButtonElement>() {
- FormSubmittableElement::ButtonElement(DomRoot::from_ref(&input))
- } else if let Some(input) = element.downcast::<HTMLObjectElement>() {
- FormSubmittableElement::ObjectElement(DomRoot::from_ref(&input))
- } else if let Some(input) = element.downcast::<HTMLSelectElement>() {
- FormSubmittableElement::SelectElement(DomRoot::from_ref(&input))
- } else if let Some(input) = element.downcast::<HTMLTextAreaElement>() {
- FormSubmittableElement::TextAreaElement(DomRoot::from_ref(&input))
- } else {
- unreachable!()
- }
- }
-}
-
#[derive(Clone, Copy, MallocSizeOf)]
pub enum FormSubmitter<'a> {
FormElement(&'a HTMLFormElement),