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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/browser/metro/base/content/helperui/FormHelperUI.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,249 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +/*
     1.9 + * Responsible for filling in form information.
    1.10 + *  - displays select popups
    1.11 + *  - Provides autocomplete box for input fields.
    1.12 + */
    1.13 +
    1.14 +var FormHelperUI = {
    1.15 +  _debugEvents: false,
    1.16 +  _currentBrowser: null,
    1.17 +  _currentElement: null,
    1.18 +  _currentCaretRect: null,
    1.19 +  _currentElementRect: null,
    1.20 +  _open: false,
    1.21 +
    1.22 +  type: "form",
    1.23 +
    1.24 +  init: function formHelperInit() {
    1.25 +    // Listen for form assistant messages from content
    1.26 +    messageManager.addMessageListener("FormAssist:Show", this);
    1.27 +    messageManager.addMessageListener("FormAssist:Hide", this);
    1.28 +    messageManager.addMessageListener("FormAssist:Update", this);
    1.29 +    messageManager.addMessageListener("FormAssist:AutoComplete", this);
    1.30 +
    1.31 +    // Listen for events where form assistant should be closed or updated
    1.32 +    let tabs = Elements.tabList;
    1.33 +    tabs.addEventListener("TabSelect", this, true);
    1.34 +    tabs.addEventListener("TabClose", this, true);
    1.35 +    Elements.browsers.addEventListener("URLChanged", this, true);
    1.36 +    Elements.browsers.addEventListener("SizeChanged", this, true);
    1.37 +
    1.38 +    // Listen some events to show/hide arrows
    1.39 +    Elements.browsers.addEventListener("PanBegin", this, false);
    1.40 +    Elements.browsers.addEventListener("PanFinished", this, false);
    1.41 +  },
    1.42 +
    1.43 +  /*
    1.44 +   * Open of the form helper proper. Currently doesn't display anything
    1.45 +   * on metro since the nav buttons are off.
    1.46 +   */
    1.47 +  show: function formHelperShow(aElement) {
    1.48 +    // Delay the operation until all resize operations generated by the
    1.49 +    // keyboard apparition are done.
    1.50 +    if (!InputSourceHelper.isPrecise && aElement.editable &&
    1.51 +        ContentAreaObserver.isKeyboardTransitioning) {
    1.52 +      this._waitForKeyboard(aElement);
    1.53 +      return;
    1.54 +    }
    1.55 +
    1.56 +    this._currentBrowser = Browser.selectedBrowser;
    1.57 +    this._currentCaretRect = null;
    1.58 +
    1.59 +    let lastElement = this._currentElement || null;
    1.60 +
    1.61 +    this._currentElement = {
    1.62 +      id: aElement.id,
    1.63 +      name: aElement.name,
    1.64 +      title: aElement.title,
    1.65 +      value: aElement.value,
    1.66 +      maxLength: aElement.maxLength,
    1.67 +      type: aElement.type,
    1.68 +      choices: aElement.choices,
    1.69 +      isAutocomplete: aElement.isAutocomplete,
    1.70 +      list: aElement.list,
    1.71 +      rect: aElement.rect
    1.72 +    };
    1.73 +
    1.74 +    this._updateContainerForSelect(lastElement, this._currentElement);
    1.75 +    this._showAutoCompleteSuggestions(this._currentElement);
    1.76 +
    1.77 +    // Prevent the view to scroll automatically while typing
    1.78 +    this._currentBrowser.scrollSync = false;
    1.79 +
    1.80 +    this._open = true;
    1.81 +  },
    1.82 +
    1.83 +  hide: function formHelperHide() {
    1.84 +    this._open = false;
    1.85 +
    1.86 +    SelectHelperUI.hide();
    1.87 +    AutofillMenuUI.hide();
    1.88 +
    1.89 +    // Restore the scroll synchonisation
    1.90 +    if (this._currentBrowser)
    1.91 +      this._currentBrowser.scrollSync = true;
    1.92 +
    1.93 +    // reset current Element and Caret Rect
    1.94 +    this._currentElementRect = null;
    1.95 +    this._currentCaretRect = null;
    1.96 +
    1.97 +    this._updateContainerForSelect(this._currentElement, null);
    1.98 +    if (this._currentBrowser)
    1.99 +      this._currentBrowser.messageManager.sendAsyncMessage("FormAssist:Closed", { });
   1.100 +  },
   1.101 +
   1.102 +  _onShowRequest: function _onShowRequest(aJsonMsg) {
   1.103 +    if (aJsonMsg.current.choices) {
   1.104 +      // Note, aJsonMsg.current.rect is translated from browser to client
   1.105 +      // in the SelectHelperUI code.
   1.106 +      SelectHelperUI.show(aJsonMsg.current.choices, aJsonMsg.current.title,
   1.107 +                          aJsonMsg.current.rect);
   1.108 +    } else {
   1.109 +      this._currentBrowser = getBrowser();
   1.110 +      this._currentElementRect =
   1.111 +        Rect.fromRect(this._currentBrowser.rectBrowserToClient(aJsonMsg.current.rect));
   1.112 +      this.show(aJsonMsg.current);
   1.113 +    }
   1.114 +  },
   1.115 +
   1.116 +  /*
   1.117 +   * Events
   1.118 +   */
   1.119 +
   1.120 +  handleEvent: function formHelperHandleEvent(aEvent) {
   1.121 +    if (this._debugEvents) Util.dumpLn(aEvent.type);
   1.122 +
   1.123 +    if (!this._open)
   1.124 +      return;
   1.125 +
   1.126 +    switch (aEvent.type) {
   1.127 +      case "TabSelect":
   1.128 +      case "TabClose":
   1.129 +      case "PanBegin":
   1.130 +      case "SizeChanged":
   1.131 +        this.hide();
   1.132 +        break;
   1.133 +
   1.134 +      case "URLChanged":
   1.135 +        if (aEvent.detail && aEvent.target == getBrowser())
   1.136 +          this.hide();
   1.137 +        break;
   1.138 +    }
   1.139 +  },
   1.140 +
   1.141 +  receiveMessage: function formHelperReceiveMessage(aMessage) {
   1.142 +    if (this._debugEvents) Util.dumpLn(aMessage.name);
   1.143 +    let json = aMessage.json;
   1.144 +
   1.145 +    switch (aMessage.name) {
   1.146 +      case "FormAssist:Show":
   1.147 +        this._onShowRequest(json);
   1.148 +        break;
   1.149 +
   1.150 +      case "FormAssist:Hide":
   1.151 +        this.hide();
   1.152 +        break;
   1.153 +
   1.154 +      case "FormAssist:AutoComplete":
   1.155 +        this.show(json.current);
   1.156 +        break;
   1.157 +    }
   1.158 +  },
   1.159 +
   1.160 +  doAutoComplete: function formHelperDoAutoComplete(aData) {
   1.161 +    this._currentBrowser.messageManager.sendAsyncMessage("FormAssist:AutoComplete",
   1.162 +      { value: aData });
   1.163 +  },
   1.164 +
   1.165 +  /*
   1.166 +   * Retrieves autocomplete suggestions asynchronously for an element from the
   1.167 +   * form autocomplete service and updates and displays the autocompletepopup.
   1.168 +   *
   1.169 +   * @param aElement form input element
   1.170 +   */
   1.171 +  _showAutoCompleteSuggestions: function (aElement) {
   1.172 +    if (!aElement.isAutocomplete) {
   1.173 +      return;
   1.174 +    }
   1.175 +
   1.176 +    let resultsAvailable = autoCompleteSuggestions => {
   1.177 +      // Return false if there are no suggestions to show
   1.178 +      if (!autoCompleteSuggestions.length) {
   1.179 +        return;
   1.180 +      }
   1.181 +      AutofillMenuUI.show(this._currentElementRect, autoCompleteSuggestions);
   1.182 +    };
   1.183 +
   1.184 +    this._getAutoCompleteSuggestions(aElement.value, aElement, resultsAvailable);
   1.185 +  },
   1.186 +
   1.187 +  /*
   1.188 +   * Retrieves autocomplete suggestions for an element from the form
   1.189 +   * autocomplete service. 
   1.190 +   *
   1.191 +   * @param aSearchString text entered into form
   1.192 +   * @param aElement form input element
   1.193 +   * @param aCallback(array_of_suggestions) called when results are available.
   1.194 +   */
   1.195 +  _getAutoCompleteSuggestions: function (aSearchString, aElement, aCallback) {
   1.196 +    // Cache the form autocomplete service for future use
   1.197 +    if (!this._formAutoCompleteService)
   1.198 +      this._formAutoCompleteService = Cc["@mozilla.org/satchel/form-autocomplete;1"].
   1.199 +                                      getService(Ci.nsIFormAutoComplete);
   1.200 +
   1.201 +    // results callback
   1.202 +    let resultsAvailable = function (results) {
   1.203 +      let suggestions = [];
   1.204 +      for (let idx = 0; idx < results.matchCount; idx++) {
   1.205 +        let value = results.getValueAt(idx);
   1.206 +
   1.207 +        // Do not show the value if it is the current one in the input field
   1.208 +        if (value == aSearchString)
   1.209 +          continue;
   1.210 +
   1.211 +        // Supply a label and value, since they can differ for datalist suggestions
   1.212 +        suggestions.push({ label: value, value: value });
   1.213 +      }
   1.214 +
   1.215 +      // Add the datalist elements provided by the website, note that the
   1.216 +      // displayed value can differ from the real value of the element.
   1.217 +      let options = aElement.list;
   1.218 +      for (let idx = 0; idx < options.length; idx++) {
   1.219 +        suggestions.push(options[idx]);
   1.220 +      }
   1.221 +
   1.222 +      aCallback(suggestions);
   1.223 +    };
   1.224 +
   1.225 +    // Send the query
   1.226 +    this._formAutoCompleteService.autoCompleteSearchAsync(aElement.name || aElement.id,
   1.227 +                                                          aSearchString, aElement, null,
   1.228 +                                                          resultsAvailable);
   1.229 +  },
   1.230 +  
   1.231 +  /*
   1.232 +   * Setup for displaying the selection choices menu
   1.233 +   */
   1.234 +  _updateContainerForSelect: function _formHelperUpdateContainerForSelect(aLastElement, aCurrentElement) {
   1.235 +    let lastHasChoices = aLastElement && (aLastElement.choices != null);
   1.236 +    let currentHasChoices = aCurrentElement && (aCurrentElement.choices != null);
   1.237 +
   1.238 +    if (currentHasChoices)
   1.239 +      SelectHelperUI.show(aCurrentElement.choices, aCurrentElement.title, aCurrentElement.rect);
   1.240 +    else if (lastHasChoices)
   1.241 +      SelectHelperUI.hide();
   1.242 +  },
   1.243 +
   1.244 +  _waitForKeyboard: function formHelperWaitForKeyboard(aElement) {
   1.245 +    let self = this;
   1.246 +    window.addEventListener("KeyboardChanged", function(aEvent) {
   1.247 +      window.removeEventListener("KeyboardChanged", arguments.callee, false);
   1.248 +      self._currentBrowser.messageManager.sendAsyncMessage("FormAssist:Update", {});
   1.249 +    }, false);
   1.250 +  }
   1.251 +};
   1.252 +

mercurial