browser/metro/base/content/helperui/SelectHelperUI.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 "use strict";
michael@0 6
michael@0 7 /**
michael@0 8 * SelectHelperUI: Provides an interface for making a choice in a list.
michael@0 9 * Supports simultaneous selection of choices and group headers.
michael@0 10 */
michael@0 11 var SelectHelperUI = {
michael@0 12 _list: null,
michael@0 13
michael@0 14 get _container() {
michael@0 15 delete this._container;
michael@0 16 return this._container = document.getElementById("select-container");
michael@0 17 },
michael@0 18
michael@0 19 get _listbox() {
michael@0 20 delete this._listbox;
michael@0 21 return this._listbox = document.getElementById("select-commands");
michael@0 22 },
michael@0 23
michael@0 24 get _menuPopup() {
michael@0 25 let popup = document.getElementById("select-popup");
michael@0 26 delete this._menuPopup;
michael@0 27 return this._menuPopup = new MenuPopup(this._container, popup);
michael@0 28 },
michael@0 29
michael@0 30 show: function selectHelperShow(aList, aTitle, aRect) {
michael@0 31 if (this._list) {
michael@0 32 this.reset();
michael@0 33 }
michael@0 34
michael@0 35 this._list = aList;
michael@0 36
michael@0 37 this._listbox.setAttribute("seltype", aList.multiple ? "multiple" : "single");
michael@0 38
michael@0 39 let firstSelected = null;
michael@0 40
michael@0 41 // Using a fragment prevent us to hang on huge list
michael@0 42 let fragment = document.createDocumentFragment();
michael@0 43 let choices = aList.choices;
michael@0 44 let selectedItems = [];
michael@0 45 for (let i = 0; i < choices.length; i++) {
michael@0 46 let choice = choices[i];
michael@0 47 let item = document.createElement("richlistitem");
michael@0 48 let label = document.createElement("label");
michael@0 49
michael@0 50 item.setAttribute("class", "option-command listitem-iconic");
michael@0 51 item.setAttribute("flex", "1");
michael@0 52 item.setAttribute("crop", "center");
michael@0 53 label.setAttribute("value", choice.text);
michael@0 54 item.appendChild(label);
michael@0 55 item.setAttribute("oldstate", "false");
michael@0 56 choice.disabled ? item.setAttribute("disabled", "true")
michael@0 57 : item.removeAttribute("disabled");
michael@0 58
michael@0 59 fragment.appendChild(item);
michael@0 60
michael@0 61 if (choice.group) {
michael@0 62 item.classList.add("optgroup");
michael@0 63 continue;
michael@0 64 }
michael@0 65
michael@0 66 item.optionIndex = choice.optionIndex;
michael@0 67 item.choiceIndex = i;
michael@0 68
michael@0 69 if (choice.inGroup) {
michael@0 70 item.classList.add("in-optgroup");
michael@0 71 }
michael@0 72
michael@0 73 if (choice.selected) {
michael@0 74 firstSelected = firstSelected || item;
michael@0 75 selectedItems.push(item);
michael@0 76 }
michael@0 77 }
michael@0 78 this._listbox.appendChild(fragment);
michael@0 79
michael@0 80 this._container.addEventListener("click", this, false);
michael@0 81 window.addEventListener("MozPrecisePointer", this, false);
michael@0 82 this._menuPopup.show(this._positionOptions(aRect));
michael@0 83
michael@0 84 // Setup pre-selected items. Note, this has to happen after show.
michael@0 85 this._listbox.clearSelection();
michael@0 86 for (let item of selectedItems) {
michael@0 87 this._listbox.addItemToSelection(item);
michael@0 88 item.setAttribute("oldstate", "true");
michael@0 89 }
michael@0 90 this._listbox.ensureElementIsVisible(firstSelected);
michael@0 91 },
michael@0 92
michael@0 93 reset: function selectHelperReset() {
michael@0 94 this._updateControl();
michael@0 95 while (this._listbox.hasChildNodes())
michael@0 96 this._listbox.removeChild(this._listbox.lastChild);
michael@0 97 this._list = null;
michael@0 98 },
michael@0 99
michael@0 100 hide: function selectHelperHide() {
michael@0 101 if (!this._list)
michael@0 102 return;
michael@0 103
michael@0 104 this._container.removeEventListener("click", this, false);
michael@0 105 window.removeEventListener("MozPrecisePointer", this, false);
michael@0 106 this._menuPopup.hide();
michael@0 107 this.reset();
michael@0 108 },
michael@0 109
michael@0 110 _positionOptions: function _positionOptions(aRect) {
michael@0 111 let browser = Browser.selectedBrowser;
michael@0 112 let p0 = browser.ptBrowserToClient(aRect.left, aRect.top);
michael@0 113 let p1 = browser.ptBrowserToClient(aRect.right, aRect.bottom);
michael@0 114
michael@0 115 return {
michael@0 116 xPos: p0.x,
michael@0 117 yPos: p1.y,
michael@0 118 bottomAligned: false,
michael@0 119 leftAligned: true
michael@0 120 };
michael@0 121 },
michael@0 122
michael@0 123 _updateControl: function _selectHelperUpdateControl() {
michael@0 124 Browser.selectedBrowser.messageManager.sendAsyncMessage("FormAssist:ChoiceChange", { });
michael@0 125 },
michael@0 126
michael@0 127 handleEvent: function selectHelperHandleEvent(aEvent) {
michael@0 128 switch (aEvent.type) {
michael@0 129 case "MozPrecisePointer":
michael@0 130 this.hide();
michael@0 131 break;
michael@0 132 case "click":
michael@0 133 let item = aEvent.target;
michael@0 134 if (item && item.hasOwnProperty("optionIndex")) {
michael@0 135 if (this._list.multiple) {
michael@0 136 // item.selected is always true here since that's how richlistbox handles
michael@0 137 // mouse click events. We track our own state so that we can toggle here
michael@0 138 // on click events. Iniial 'oldstate' values are setup in show above.
michael@0 139 if (item.getAttribute("oldstate") == "true") {
michael@0 140 item.setAttribute("oldstate", "false");
michael@0 141 } else {
michael@0 142 item.setAttribute("oldstate", "true");
michael@0 143 }
michael@0 144 // Fix up selected items - richlistbox will clear selection on click events
michael@0 145 // so we need to set selection on the items the user has previously chosen.
michael@0 146 this._listbox.clearSelection();
michael@0 147 for (let node of this._listbox.childNodes) {
michael@0 148 if (node.getAttribute("oldstate") == "true") {
michael@0 149 this._listbox.addItemToSelection(node);
michael@0 150 }
michael@0 151 }
michael@0 152 }
michael@0 153 // Let the form element know we've added or removed a selected item.
michael@0 154 this.onSelect(item.optionIndex, item.selected);
michael@0 155 }
michael@0 156 break;
michael@0 157 }
michael@0 158 },
michael@0 159
michael@0 160 onSelect: function selectHelperOnSelect(aIndex, aSelected) {
michael@0 161 Browser.selectedBrowser.messageManager.sendAsyncMessage("FormAssist:ChoiceSelect", {
michael@0 162 index: aIndex,
michael@0 163 selected: aSelected
michael@0 164 });
michael@0 165 if (!this._list.multiple) {
michael@0 166 this.hide();
michael@0 167 }
michael@0 168 }
michael@0 169 };

mercurial