Bumping manifests a=b2g-bump
[gecko.git] / browser / modules / FormValidationHandler.jsm
blob05be510e183da98f6f2af7abffbd8a69dbe223a7
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 /*
6  * Chrome side handling of form validation popup.
7  */
9 "use strict";
11 let Cc = Components.classes;
12 let Ci = Components.interfaces;
13 let Cu = Components.utils;
15 this.EXPORTED_SYMBOLS = [ "FormValidationHandler" ];
17 Cu.import("resource://gre/modules/Services.jsm");
19 let FormValidationHandler =
21   _panel: null,
22   _anchor: null,
24   /*
25    * Public apis
26    */
28   init: function () {
29     let mm = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
30     mm.addMessageListener("FormValidation:ShowPopup", this);
31     mm.addMessageListener("FormValidation:HidePopup", this);
32   },
34   uninit: function () {
35     let mm = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
36     mm.removeMessageListener("FormValidation:ShowPopup", this);
37     mm.removeMessageListener("FormValidation:HidePopup", this);
38     this._panel = null;
39     this._anchor = null;
40   },
42   hidePopup: function () {
43     this._hidePopup();
44   },
46   /*
47    * Events
48    */
50   receiveMessage: function (aMessage) {
51     let window = aMessage.target.ownerDocument.defaultView;
52     let json = aMessage.json;
53     let tabBrowser = window.gBrowser;
54     switch (aMessage.name) {
55       case "FormValidation:ShowPopup":
56         // target is the <browser>, make sure we're receiving a message
57         // from the foreground tab.
58         if (tabBrowser && aMessage.target != tabBrowser.selectedBrowser) {
59           return;
60         }
61         this._showPopup(window, json);
62         break;
63       case "FormValidation:HidePopup":
64         this._hidePopup();
65         break;
66     }
67   },
69   observe: function (aSubject, aTopic, aData) {
70     this._hidePopup();
71   },
73   handleEvent: function (aEvent) {
74     switch (aEvent.type) {
75       case "FullZoomChange":
76       case "TextZoomChange":
77       case "ZoomChangeUsingMouseWheel":
78       case "scroll":
79         this._hidePopup();
80         break;
81       case "popuphiding":
82         this._onPopupHiding(aEvent);
83         break;
84     }
85   },
87   /*
88    * Internal
89    */
91   _onPopupHiding: function (aEvent) {
92     aEvent.originalTarget.removeEventListener("popuphiding", this, true);
93     let tabBrowser = aEvent.originalTarget.ownerDocument.getElementById("content");
94     tabBrowser.selectedBrowser.removeEventListener("scroll", this, true);
95     tabBrowser.selectedBrowser.removeEventListener("FullZoomChange", this, false);
96     tabBrowser.selectedBrowser.removeEventListener("TextZoomChange", this, false);
97     tabBrowser.selectedBrowser.removeEventListener("ZoomChangeUsingMouseWheel", this, false);
99     this._panel.hidden = true;
100     this._panel = null;
101     this._anchor.hidden = true;
102     this._anchor = null;
103   },
105   /*
106    * Shows the form validation popup at a specified position or updates the
107    * messaging and position if the popup is already displayed.
108    *
109    * @aWindow - the chrome window
110    * @aPanelData - Object that contains popup information
111    *  aPanelData stucture detail:
112    *   contentRect - the bounding client rect of the target element. If
113    *    content is remote, this is relative to the browser, otherwise its
114    *    relative to the window.
115    *   position - popup positional string constants.
116    *   message - the form element validation message text.
117    */
118   _showPopup: function (aWindow, aPanelData) {
119     let previouslyShown = !!this._panel;
120     this._panel = aWindow.document.getElementById("invalid-form-popup");
121     this._panel.firstChild.textContent = aPanelData.message;
122     this._panel.hidden = false;
124     let tabBrowser = aWindow.gBrowser;
125     this._anchor = tabBrowser.formValidationAnchor;
126     this._anchor.left = aPanelData.contentRect.left;
127     this._anchor.top = aPanelData.contentRect.top;
128     this._anchor.width = aPanelData.contentRect.width;
129     this._anchor.height = aPanelData.contentRect.height;
130     this._anchor.hidden = false;
132     // Display the panel if it isn't already visible.
133     if (!previouslyShown) {
134       // Cleanup after the popup is hidden
135       this._panel.addEventListener("popuphiding", this, true);
137       // Hide if the user scrolls the page
138       tabBrowser.selectedBrowser.addEventListener("scroll", this, true);
139       tabBrowser.selectedBrowser.addEventListener("FullZoomChange", this, false);
140       tabBrowser.selectedBrowser.addEventListener("TextZoomChange", this, false);
141       tabBrowser.selectedBrowser.addEventListener("ZoomChangeUsingMouseWheel", this, false);
143       // Open the popup
144       this._panel.openPopup(this._anchor, aPanelData.position, 0, 0, false);
145     }
146   },
148   /*
149    * Hide the popup if currently displayed. Will fire an event to onPopupHiding
150    * above if visible.
151    */
152   _hidePopup: function () {
153     if (this._panel) {
154       this._panel.hidePopup();
155     }
156   }