From 5d30f398bd39d63e9938165f9def84e2218c8589 Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Sat, 11 Sep 2010 06:10:31 +0200 Subject: [PATCH] Bug 561636 (4/4) - When an invalid form is submitted, an error messages should be displayed. r=dolske a2.0=blocking --- browser/base/content/browser.css | 4 + browser/base/content/browser.js | 74 +++++++++++++++++++ browser/base/content/browser.xul | 3 + .../themes/gnomestripe/browser/browser.css | 9 +++ browser/themes/pinstripe/browser/browser.css | 9 +++ browser/themes/winstripe/browser/browser.css | 9 +++ 6 files changed, 108 insertions(+) diff --git a/browser/base/content/browser.css b/browser/base/content/browser.css index ee71b2ef4fe..a153bdda114 100644 --- a/browser/base/content/browser.css +++ b/browser/base/content/browser.css @@ -372,6 +372,10 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m display: -moz-box; } +#invalid-form-popup { + max-width: 280px; +} + #geolocation-notification { -moz-binding: url("chrome://browser/content/urlbarBindings.xml#geolocation-notification"); } diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index a2c8b6f66e9..47a5785271f 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -789,6 +789,72 @@ const gXPInstallObserver = { } }; +const gFormSubmitObserver = { + QueryInterface : XPCOMUtils.generateQI([Ci.nsIFormSubmitObserver]), + + panel: null, + + init: function() + { + this.panel = document.getElementById('invalid-form-popup'); + this.panel.appendChild(document.createTextNode("")); + }, + + panelIsOpen: function() + { + return this.panel && this.panel.state != "hiding" && + this.panel.state != "closed"; + }, + + notifyInvalidSubmit : function (aFormElement, aInvalidElements) + { + // We are going to handle invalid form submission attempt by focusing the + // first invalid element and show the corresponding validation message in a + // panel attached to the element. + if (!aInvalidElements.length) { + return; + } + + // Don't show the popup if the current tab doesn't contain the invalid form. + if (gBrowser.selectedTab.linkedBrowser.contentDocument != + aFormElement.ownerDocument) { + return; + } + + let element = aInvalidElements.queryElementAt(0, Ci.nsISupports); + + if (!(element instanceof HTMLInputElement || + element instanceof HTMLTextAreaElement || + element instanceof HTMLSelectElement || + element instanceof HTMLButtonElement)) { + return; + } + + // Limit the message to 256 characters. + this.panel.firstChild.nodeValue = element.validationMessage.substring(0, 256); + + element.focus(); + + // If the user type something or blur the element, we want to remove the popup. + // We could check for clicks but a click is already removing the popup. + let eventHandler = function(e) { + gFormSubmitObserver.panel.hidePopup(); + }; + element.addEventListener("input", eventHandler, false); + element.addEventListener("blur", eventHandler, false); + + // One event to bring them all and in the darkness bind them all. + this.panel.addEventListener("popuphiding", function(aEvent) { + aEvent.target.removeEventListener("popuphiding", arguments.callee, false); + element.removeEventListener("input", eventHandler, false); + element.removeEventListener("blur", eventHandler, false); + }, false); + + this.panel.hidden = false; + this.panel.openPopup(element, "after_start", 0, 0); + } +}; + // Simple gestures support // // As per bug #412486, web content must not be allowed to receive any @@ -1318,10 +1384,12 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) { Services.obs.addObserver(gXPInstallObserver, "addon-install-blocked", false); Services.obs.addObserver(gXPInstallObserver, "addon-install-failed", false); Services.obs.addObserver(gXPInstallObserver, "addon-install-complete", false); + Services.obs.addObserver(gFormSubmitObserver, "invalidformsubmit", false); BrowserOffline.init(); OfflineApps.init(); IndexedDBPromptHelper.init(); + gFormSubmitObserver.init(); gBrowser.addEventListener("pageshow", function(evt) { setTimeout(pageShowEventHandlers, 0, evt); }, true); @@ -1562,6 +1630,7 @@ function BrowserShutdown() Services.obs.removeObserver(gXPInstallObserver, "addon-install-failed"); Services.obs.removeObserver(gXPInstallObserver, "addon-install-complete"); Services.obs.removeObserver(gPluginHandler.pluginCrashed, "plugin-crashed"); + Services.obs.removeObserver(gFormSubmitObserver, "invalidformsubmit"); try { gBrowser.removeProgressListener(window.XULBrowserWindow); @@ -4191,6 +4260,11 @@ var XULBrowserWindow = { var location = aLocationURI ? aLocationURI.spec : ""; this._hostChanged = true; + // Hide the form invalid popup. + if (gFormSubmitObserver.panelIsOpen()) { + gFormSubmitObserver.panel.hidePopup(); + } + if (document.tooltipNode) { // Optimise for the common case if (aWebProgress.DOMWindow == content) { diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul index d556be90fba..a1956ab4003 100644 --- a/browser/base/content/browser.xul +++ b/browser/base/content/browser.xul @@ -163,6 +163,9 @@