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

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

mercurial