Bug 1403251 - Only display validation message when element is invalid; r?sebastian
Only display form validation message when the element becomes invalid
after an invalid submission, by checking the "-moz-ui-invalid"
pseudo-class.
Also fix some message visibility bugs, by making sure in more places
that we only display messages for focused elements.
MozReview-Commit-ID: 16rvMmu8Zj6
--- a/mobile/android/modules/FormAssistant.jsm
+++ b/mobile/android/modules/FormAssistant.jsm
@@ -64,17 +64,17 @@ var FormAssistant = {
observe: function(aSubject, aTopic, aData) {
switch (aTopic) {
case "PanZoom:StateChange":
// If the user is just touching the screen and we haven't entered a pan
// or zoom state yet do nothing.
if (aData == "TOUCHING" || aData == "WAITING_LISTENERS") {
break;
}
- let focused = this._currentFocusedElement && this._currentFocusedElement.get();
+ let focused = this.focusedElement;
if (aData == "NOTHING") {
if (!focused || this._showValidationMessage(focused)) {
break;
}
this._showAutoCompleteSuggestions(focused, hasResults => {
if (!hasResults) {
this._hideFormAssistPopup(focused);
}
@@ -89,81 +89,89 @@ var FormAssistant = {
notifyInvalidSubmit: function(aFormElement, aInvalidElements) {
if (!aInvalidElements.length) {
return;
}
// Ignore this notificaiton if the current tab doesn't contain the invalid element
let currentElement = aInvalidElements.queryElementAt(0, Ci.nsISupports);
- let focused = this._currentFocusedElement && this._currentFocusedElement.get();
+ let focused = this.focusedElement;
if (focused && focused.ownerGlobal.top !== currentElement.ownerGlobal.top) {
return;
}
// Our focus listener will show the element's validation message
currentElement.focus();
},
+ get focusedElement() {
+ return this._currentFocusedElement && this._currentFocusedElement.get();
+ },
+
handleEvent: function(aEvent) {
switch (aEvent.type) {
case "focus": {
let currentElement = aEvent.target;
// Only show a validation message on focus.
if (this._showValidationMessage(currentElement) ||
this._isAutoComplete(currentElement)) {
this._currentFocusedElement = Cu.getWeakReference(currentElement);
}
break;
}
case "blur": {
- let focused = this._currentFocusedElement && this._currentFocusedElement.get();
+ let focused = this.focusedElement;
if (focused) {
this._hideFormAssistPopup(focused);
}
this._currentFocusedElement = null;
break;
}
case "click": {
let currentElement = aEvent.target;
+ if (currentElement !== this.focusedElement) {
+ break;
+ }
// Prioritize a form validation message over autocomplete suggestions
// when the element is first focused (a form validation message will
// only be available if an invalid form was submitted)
- if (this._showValidationMessage(currentElement)) {
+ if (this._isValidateable(currentElement)) {
break;
}
let checkResultsClick = hasResults => {
- if (!hasResults) {
+ if (!hasResults && currentElement === this.focusedElement) {
this._hideFormAssistPopup(currentElement);
}
};
this._showAutoCompleteSuggestions(currentElement, checkResultsClick);
break;
}
case "input": {
let currentElement = aEvent.target;
- let focused = this._currentFocusedElement && this._currentFocusedElement.get();
// If this element isn't focused, we're already in middle of an
// autocomplete, or its value hasn't changed, don't show the
// autocomplete popup.
- if (currentElement !== focused || this._doingAutocomplete) {
+ if (currentElement !== this.focusedElement || this._doingAutocomplete) {
break;
}
- // Since we can only show one popup at a time, prioritze autocomplete
+ // Since we can only show one popup at a time, prioritize autocomplete
// suggestions over a form validation message
let checkResultsInput = hasResults => {
- if (hasResults || this._showValidationMessage(currentElement)) {
+ if (hasResults ||
+ currentElement !== this.focusedElement ||
+ this._showValidationMessage(currentElement)) {
return;
}
// If we're not showing autocomplete suggestions, hide the form assist popup
this._hideFormAssistPopup(currentElement);
};
this._showAutoCompleteSuggestions(currentElement, checkResultsInput);
break;
@@ -259,17 +267,17 @@ var FormAssistant = {
let resultsAvailable = autoCompleteSuggestions => {
// On desktop, we show datalist suggestions below autocomplete suggestions,
// without duplicates removed.
let listSuggestions = this._getListSuggestions(aElement);
let suggestions = autoCompleteSuggestions.concat(listSuggestions);
// Return false if there are no suggestions to show
- if (!suggestions.length) {
+ if (!suggestions.length || aElement !== this.focusedElement) {
aCallback(false);
return;
}
GeckoViewUtils.getDispatcherForWindow(aElement.ownerGlobal).sendRequest({
type: "FormAssist:AutoCompleteResult",
suggestions: suggestions,
rect: this._getBoundingContentRect(aElement),
@@ -287,16 +295,17 @@ var FormAssistant = {
// Only show a validation message if the user submitted an invalid form,
// there's a non-empty message string, and the element is the correct type
_isValidateable: function(aElement) {
return (aElement instanceof Ci.nsIDOMHTMLInputElement ||
aElement instanceof Ci.nsIDOMHTMLTextAreaElement ||
aElement instanceof Ci.nsIDOMHTMLSelectElement ||
aElement instanceof Ci.nsIDOMHTMLButtonElement) &&
+ aElement.matches(":-moz-ui-invalid") &&
aElement.validationMessage;
},
// Sends a validation message and position data for an element to the Java UI.
// Returns true if there's a validation message to show, false otherwise.
_showValidationMessage: function(aElement) {
if (!this._isValidateable(aElement)) {
return false;