diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs
index 53867c755f82..dfd2dac46506 100755
--- a/components/script/dom/htmlformelement.rs
+++ b/components/script/dom/htmlformelement.rs
@@ -7,6 +7,7 @@ use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods;
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::Bindings::HTMLButtonElementBinding::HTMLButtonElementMethods;
+use dom::bindings::codegen::Bindings::HTMLElementBinding::HTMLElementBinding::HTMLElementMethods;
use dom::bindings::codegen::Bindings::HTMLFormControlsCollectionBinding::HTMLFormControlsCollectionMethods;
use dom::bindings::codegen::Bindings::HTMLFormElementBinding;
use dom::bindings::codegen::Bindings::HTMLFormElementBinding::HTMLFormElementMethods;
@@ -454,13 +455,18 @@ 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
+ // TODO: Replace println! by something more visible to the user when a better reporting method
+ // becomes available.
+ let ref first_invalid_element = unhandled_invalid_controls[0].as_html_element();
+ println!("Validation error in element {}",
+ first_invalid_element.upcast::().get_string_attribute(&local_name!("name")));
+ first_invalid_element.Focus();
// Step 4
Err(())
}
@@ -757,6 +763,16 @@ impl FormSubmittableElement {
unreachable!()
}
}
+
+ fn as_html_element(&self) -> &HTMLElement {
+ 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()
+ }
+ }
}
#[derive(Copy, Clone, HeapSizeOf)]
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs
index fc20326b906e..92ac2121cb97 100755
--- a/components/script/dom/htmlinputelement.rs
+++ b/components/script/dom/htmlinputelement.rs
@@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use caseless::compatibility_caseless_match_str;
+use core::borrow::Borrow;
use dom::activation::{Activatable, ActivationSource, synthetic_click_activation};
use dom::attr::Attr;
use dom::bindings::cell::DOMRefCell;
@@ -43,11 +44,13 @@ use mime_guess;
use net_traits::{CoreResourceMsg, IpcSend};
use net_traits::blob_url_store::get_blob_origin;
use net_traits::filemanager_thread::{FileManagerThreadMsg, FilterPattern};
+use regex::Regex;
use script_layout_interface::rpc::TextIndexResponse;
use script_traits::ScriptMsg as ConstellationMsg;
use servo_atoms::Atom;
use std::borrow::ToOwned;
use std::cell::Cell;
+use std::error::{Error as StdError};
use std::ops::Range;
use style::attr::AttrValue;
use style::element_state::*;
@@ -1188,7 +1191,63 @@ impl Validatable for HTMLInputElement {
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
+ use dom::validitystate::*;
+
+ let value = self.Value();
+ let value_str: &str = value.borrow();
+ // https://html.spec.whatwg.org/multipage/#suffering-from-being-missing
+ if _validate_flags.contains(VALUE_MISSING) {
+ if value_str.is_empty() {
+ return false;
+ }
+ }
+ // https://html.spec.whatwg.org/multipage/#suffering-from-a-type-mismatch
+ if _validate_flags.contains(TYPE_MISMATCH) {
+ let validation_patterns = match self.Type().borrow() {
+ "url" => vec!(".", "/"),
+ "email" => vec!("@"),
+ _ => vec!(),
+ };
+
+ if validation_patterns.iter().all(|&p| !value_str.contains(p)) {
+ return false;
+ }
+ }
+ // https://html.spec.whatwg.org/multipage/#suffering-from-a-pattern-mismatch
+ if _validate_flags.contains(PATTERN_MISMATCH) {
+ let pattern = self.Pattern();
+ let pattern_str: &str = pattern.borrow();
+ if pattern_str.len() > 0 {
+ let pattern_regex = format!("^{}$", pattern_str);
+ match Regex::new(pattern_regex.as_str()) {
+ Ok(regex) => {
+ if !regex.is_match(value_str) {
+ return false;
+ }
+ },
+ Err(error) => {
+ // TODO When possible, report this error to the developer console, as suggested in
+ // https://html.spec.whatwg.org/multipage/#attr-input-pattern
+ println!("Invalid pattern for element {}: {}",
+ self.Name(), error.description());
+ }
+ };
+ }
+ }
+ // https://html.spec.whatwg.org/multipage/#suffering-from-being-too-long
+ if _validate_flags.contains(TOO_LONG) {
+ let maxlength = self.maxlength.get();
+ if maxlength != DEFAULT_MAX_LENGTH && value_str.len() > (maxlength as usize) {
+ return false;
+ }
+ }
+ // https://html.spec.whatwg.org/multipage/#suffering-from-being-too-short
+ if _validate_flags.contains(TOO_SHORT) {
+ let minlength = self.minlength.get();
+ if minlength != DEFAULT_MIN_LENGTH && value_str.len() < (minlength as usize) {
+ return false;
+ }
+ }
true
}
}
diff --git a/components/script/dom/validitystate.rs b/components/script/dom/validitystate.rs
index 879438aa3893..8db74131aac9 100755
--- a/components/script/dom/validitystate.rs
+++ b/components/script/dom/validitystate.rs
@@ -70,56 +70,56 @@ impl ValidityState {
impl ValidityStateMethods for ValidityState {
// https://html.spec.whatwg.org/multipage/#dom-validitystate-valuemissing
fn ValueMissing(&self) -> bool {
- false
+ self.element.as_maybe_validatable().map_or(false, |e| e.validate(VALUE_MISSING))
}
// https://html.spec.whatwg.org/multipage/#dom-validitystate-typemismatch
fn TypeMismatch(&self) -> bool {
- false
+ self.element.as_maybe_validatable().map_or(false, |e| e.validate(TYPE_MISMATCH))
}
// https://html.spec.whatwg.org/multipage/#dom-validitystate-patternmismatch
fn PatternMismatch(&self) -> bool {
- false
+ self.element.as_maybe_validatable().map_or(false, |e| e.validate(PATTERN_MISMATCH))
}
// https://html.spec.whatwg.org/multipage/#dom-validitystate-toolong
fn TooLong(&self) -> bool {
- false
+ self.element.as_maybe_validatable().map_or(false, |e| e.validate(TOO_LONG))
}
// https://html.spec.whatwg.org/multipage/#dom-validitystate-tooshort
fn TooShort(&self) -> bool {
- false
+ self.element.as_maybe_validatable().map_or(false, |e| e.validate(TOO_SHORT))
}
// https://html.spec.whatwg.org/multipage/#dom-validitystate-rangeunderflow
fn RangeUnderflow(&self) -> bool {
- false
+ self.element.as_maybe_validatable().map_or(false, |e| e.validate(RANGE_UNDERFLOW))
}
// https://html.spec.whatwg.org/multipage/#dom-validitystate-rangeoverflow
fn RangeOverflow(&self) -> bool {
- false
+ self.element.as_maybe_validatable().map_or(false, |e| e.validate(RANGE_OVERFLOW))
}
// https://html.spec.whatwg.org/multipage/#dom-validitystate-stepmismatch
fn StepMismatch(&self) -> bool {
- false
+ self.element.as_maybe_validatable().map_or(false, |e| e.validate(STEP_MISMATCH))
}
// https://html.spec.whatwg.org/multipage/#dom-validitystate-badinput
fn BadInput(&self) -> bool {
- false
+ self.element.as_maybe_validatable().map_or(false, |e| e.validate(BAD_INPUT))
}
// https://html.spec.whatwg.org/multipage/#dom-validitystate-customerror
fn CustomError(&self) -> bool {
- false
+ self.element.as_maybe_validatable().map_or(false, |e| e.validate(CUSTOM_ERROR))
}
// https://html.spec.whatwg.org/multipage/#dom-validitystate-valid
fn Valid(&self) -> bool {
- false
+ !self.element.as_maybe_validatable().map_or(false, |e| e.validate(ValidationFlags::all()))
}
}