browser/metro/base/content/helperui/FormHelperUI.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 /*
michael@0 6 * Responsible for filling in form information.
michael@0 7 * - displays select popups
michael@0 8 * - Provides autocomplete box for input fields.
michael@0 9 */
michael@0 10
michael@0 11 var FormHelperUI = {
michael@0 12 _debugEvents: false,
michael@0 13 _currentBrowser: null,
michael@0 14 _currentElement: null,
michael@0 15 _currentCaretRect: null,
michael@0 16 _currentElementRect: null,
michael@0 17 _open: false,
michael@0 18
michael@0 19 type: "form",
michael@0 20
michael@0 21 init: function formHelperInit() {
michael@0 22 // Listen for form assistant messages from content
michael@0 23 messageManager.addMessageListener("FormAssist:Show", this);
michael@0 24 messageManager.addMessageListener("FormAssist:Hide", this);
michael@0 25 messageManager.addMessageListener("FormAssist:Update", this);
michael@0 26 messageManager.addMessageListener("FormAssist:AutoComplete", this);
michael@0 27
michael@0 28 // Listen for events where form assistant should be closed or updated
michael@0 29 let tabs = Elements.tabList;
michael@0 30 tabs.addEventListener("TabSelect", this, true);
michael@0 31 tabs.addEventListener("TabClose", this, true);
michael@0 32 Elements.browsers.addEventListener("URLChanged", this, true);
michael@0 33 Elements.browsers.addEventListener("SizeChanged", this, true);
michael@0 34
michael@0 35 // Listen some events to show/hide arrows
michael@0 36 Elements.browsers.addEventListener("PanBegin", this, false);
michael@0 37 Elements.browsers.addEventListener("PanFinished", this, false);
michael@0 38 },
michael@0 39
michael@0 40 /*
michael@0 41 * Open of the form helper proper. Currently doesn't display anything
michael@0 42 * on metro since the nav buttons are off.
michael@0 43 */
michael@0 44 show: function formHelperShow(aElement) {
michael@0 45 // Delay the operation until all resize operations generated by the
michael@0 46 // keyboard apparition are done.
michael@0 47 if (!InputSourceHelper.isPrecise && aElement.editable &&
michael@0 48 ContentAreaObserver.isKeyboardTransitioning) {
michael@0 49 this._waitForKeyboard(aElement);
michael@0 50 return;
michael@0 51 }
michael@0 52
michael@0 53 this._currentBrowser = Browser.selectedBrowser;
michael@0 54 this._currentCaretRect = null;
michael@0 55
michael@0 56 let lastElement = this._currentElement || null;
michael@0 57
michael@0 58 this._currentElement = {
michael@0 59 id: aElement.id,
michael@0 60 name: aElement.name,
michael@0 61 title: aElement.title,
michael@0 62 value: aElement.value,
michael@0 63 maxLength: aElement.maxLength,
michael@0 64 type: aElement.type,
michael@0 65 choices: aElement.choices,
michael@0 66 isAutocomplete: aElement.isAutocomplete,
michael@0 67 list: aElement.list,
michael@0 68 rect: aElement.rect
michael@0 69 };
michael@0 70
michael@0 71 this._updateContainerForSelect(lastElement, this._currentElement);
michael@0 72 this._showAutoCompleteSuggestions(this._currentElement);
michael@0 73
michael@0 74 // Prevent the view to scroll automatically while typing
michael@0 75 this._currentBrowser.scrollSync = false;
michael@0 76
michael@0 77 this._open = true;
michael@0 78 },
michael@0 79
michael@0 80 hide: function formHelperHide() {
michael@0 81 this._open = false;
michael@0 82
michael@0 83 SelectHelperUI.hide();
michael@0 84 AutofillMenuUI.hide();
michael@0 85
michael@0 86 // Restore the scroll synchonisation
michael@0 87 if (this._currentBrowser)
michael@0 88 this._currentBrowser.scrollSync = true;
michael@0 89
michael@0 90 // reset current Element and Caret Rect
michael@0 91 this._currentElementRect = null;
michael@0 92 this._currentCaretRect = null;
michael@0 93
michael@0 94 this._updateContainerForSelect(this._currentElement, null);
michael@0 95 if (this._currentBrowser)
michael@0 96 this._currentBrowser.messageManager.sendAsyncMessage("FormAssist:Closed", { });
michael@0 97 },
michael@0 98
michael@0 99 _onShowRequest: function _onShowRequest(aJsonMsg) {
michael@0 100 if (aJsonMsg.current.choices) {
michael@0 101 // Note, aJsonMsg.current.rect is translated from browser to client
michael@0 102 // in the SelectHelperUI code.
michael@0 103 SelectHelperUI.show(aJsonMsg.current.choices, aJsonMsg.current.title,
michael@0 104 aJsonMsg.current.rect);
michael@0 105 } else {
michael@0 106 this._currentBrowser = getBrowser();
michael@0 107 this._currentElementRect =
michael@0 108 Rect.fromRect(this._currentBrowser.rectBrowserToClient(aJsonMsg.current.rect));
michael@0 109 this.show(aJsonMsg.current);
michael@0 110 }
michael@0 111 },
michael@0 112
michael@0 113 /*
michael@0 114 * Events
michael@0 115 */
michael@0 116
michael@0 117 handleEvent: function formHelperHandleEvent(aEvent) {
michael@0 118 if (this._debugEvents) Util.dumpLn(aEvent.type);
michael@0 119
michael@0 120 if (!this._open)
michael@0 121 return;
michael@0 122
michael@0 123 switch (aEvent.type) {
michael@0 124 case "TabSelect":
michael@0 125 case "TabClose":
michael@0 126 case "PanBegin":
michael@0 127 case "SizeChanged":
michael@0 128 this.hide();
michael@0 129 break;
michael@0 130
michael@0 131 case "URLChanged":
michael@0 132 if (aEvent.detail && aEvent.target == getBrowser())
michael@0 133 this.hide();
michael@0 134 break;
michael@0 135 }
michael@0 136 },
michael@0 137
michael@0 138 receiveMessage: function formHelperReceiveMessage(aMessage) {
michael@0 139 if (this._debugEvents) Util.dumpLn(aMessage.name);
michael@0 140 let json = aMessage.json;
michael@0 141
michael@0 142 switch (aMessage.name) {
michael@0 143 case "FormAssist:Show":
michael@0 144 this._onShowRequest(json);
michael@0 145 break;
michael@0 146
michael@0 147 case "FormAssist:Hide":
michael@0 148 this.hide();
michael@0 149 break;
michael@0 150
michael@0 151 case "FormAssist:AutoComplete":
michael@0 152 this.show(json.current);
michael@0 153 break;
michael@0 154 }
michael@0 155 },
michael@0 156
michael@0 157 doAutoComplete: function formHelperDoAutoComplete(aData) {
michael@0 158 this._currentBrowser.messageManager.sendAsyncMessage("FormAssist:AutoComplete",
michael@0 159 { value: aData });
michael@0 160 },
michael@0 161
michael@0 162 /*
michael@0 163 * Retrieves autocomplete suggestions asynchronously for an element from the
michael@0 164 * form autocomplete service and updates and displays the autocompletepopup.
michael@0 165 *
michael@0 166 * @param aElement form input element
michael@0 167 */
michael@0 168 _showAutoCompleteSuggestions: function (aElement) {
michael@0 169 if (!aElement.isAutocomplete) {
michael@0 170 return;
michael@0 171 }
michael@0 172
michael@0 173 let resultsAvailable = autoCompleteSuggestions => {
michael@0 174 // Return false if there are no suggestions to show
michael@0 175 if (!autoCompleteSuggestions.length) {
michael@0 176 return;
michael@0 177 }
michael@0 178 AutofillMenuUI.show(this._currentElementRect, autoCompleteSuggestions);
michael@0 179 };
michael@0 180
michael@0 181 this._getAutoCompleteSuggestions(aElement.value, aElement, resultsAvailable);
michael@0 182 },
michael@0 183
michael@0 184 /*
michael@0 185 * Retrieves autocomplete suggestions for an element from the form
michael@0 186 * autocomplete service.
michael@0 187 *
michael@0 188 * @param aSearchString text entered into form
michael@0 189 * @param aElement form input element
michael@0 190 * @param aCallback(array_of_suggestions) called when results are available.
michael@0 191 */
michael@0 192 _getAutoCompleteSuggestions: function (aSearchString, aElement, aCallback) {
michael@0 193 // Cache the form autocomplete service for future use
michael@0 194 if (!this._formAutoCompleteService)
michael@0 195 this._formAutoCompleteService = Cc["@mozilla.org/satchel/form-autocomplete;1"].
michael@0 196 getService(Ci.nsIFormAutoComplete);
michael@0 197
michael@0 198 // results callback
michael@0 199 let resultsAvailable = function (results) {
michael@0 200 let suggestions = [];
michael@0 201 for (let idx = 0; idx < results.matchCount; idx++) {
michael@0 202 let value = results.getValueAt(idx);
michael@0 203
michael@0 204 // Do not show the value if it is the current one in the input field
michael@0 205 if (value == aSearchString)
michael@0 206 continue;
michael@0 207
michael@0 208 // Supply a label and value, since they can differ for datalist suggestions
michael@0 209 suggestions.push({ label: value, value: value });
michael@0 210 }
michael@0 211
michael@0 212 // Add the datalist elements provided by the website, note that the
michael@0 213 // displayed value can differ from the real value of the element.
michael@0 214 let options = aElement.list;
michael@0 215 for (let idx = 0; idx < options.length; idx++) {
michael@0 216 suggestions.push(options[idx]);
michael@0 217 }
michael@0 218
michael@0 219 aCallback(suggestions);
michael@0 220 };
michael@0 221
michael@0 222 // Send the query
michael@0 223 this._formAutoCompleteService.autoCompleteSearchAsync(aElement.name || aElement.id,
michael@0 224 aSearchString, aElement, null,
michael@0 225 resultsAvailable);
michael@0 226 },
michael@0 227
michael@0 228 /*
michael@0 229 * Setup for displaying the selection choices menu
michael@0 230 */
michael@0 231 _updateContainerForSelect: function _formHelperUpdateContainerForSelect(aLastElement, aCurrentElement) {
michael@0 232 let lastHasChoices = aLastElement && (aLastElement.choices != null);
michael@0 233 let currentHasChoices = aCurrentElement && (aCurrentElement.choices != null);
michael@0 234
michael@0 235 if (currentHasChoices)
michael@0 236 SelectHelperUI.show(aCurrentElement.choices, aCurrentElement.title, aCurrentElement.rect);
michael@0 237 else if (lastHasChoices)
michael@0 238 SelectHelperUI.hide();
michael@0 239 },
michael@0 240
michael@0 241 _waitForKeyboard: function formHelperWaitForKeyboard(aElement) {
michael@0 242 let self = this;
michael@0 243 window.addEventListener("KeyboardChanged", function(aEvent) {
michael@0 244 window.removeEventListener("KeyboardChanged", arguments.callee, false);
michael@0 245 self._currentBrowser.messageManager.sendAsyncMessage("FormAssist:Update", {});
michael@0 246 }, false);
michael@0 247 }
michael@0 248 };
michael@0 249

mercurial