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

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

mercurial