mobile/android/chrome/content/SelectHelper.js

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:06f971ddfa1d
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 file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
4 "use strict";
5
6 var SelectHelper = {
7 _uiBusy: false,
8
9 handleEvent: function(aEvent) {
10 this.handleClick(aEvent.target);
11 },
12
13 handleClick: function(aTarget) {
14 // if we're busy looking at a select we want to eat any clicks that
15 // come to us, but not to process them
16 if (this._uiBusy || !this._isMenu(aTarget) || aTarget.disabled)
17 return;
18
19 this._uiBusy = true;
20 this.show(aTarget);
21 this._uiBusy = false;
22 },
23
24 show: function(aElement) {
25 let list = this.getListForElement(aElement);
26
27 let p = new Prompt({
28 window: aElement.contentDocument
29 });
30
31 if (aElement.multiple) {
32 p.addButton({
33 label: Strings.browser.GetStringFromName("selectHelper.closeMultipleSelectDialog")
34 }).setMultiChoiceItems(list);
35 } else {
36 p.setSingleChoiceItems(list);
37 }
38
39 p.show((function(data) {
40 let selected = data.list;
41
42 if (aElement instanceof Ci.nsIDOMXULMenuListElement) {
43 if (aElement.selectedIndex != selected[0]) {
44 aElement.selectedIndex = selected[0];
45 this.fireOnCommand(aElement);
46 }
47 } else if (aElement instanceof HTMLSelectElement) {
48 let changed = false;
49 let i = 0;
50 this.forOptions(aElement, function(aNode) {
51 if (aNode.selected && selected.indexOf(i) == -1) {
52 changed = true;
53 aNode.selected = false;
54 } else if (!aNode.selected && selected.indexOf(i) != -1) {
55 changed = true;
56 aNode.selected = true;
57 }
58 i++;
59 });
60
61 if (changed)
62 this.fireOnChange(aElement);
63 }
64 }).bind(this));
65 },
66
67 _isMenu: function(aElement) {
68 return (aElement instanceof HTMLSelectElement ||
69 aElement instanceof Ci.nsIDOMXULMenuListElement);
70 },
71
72 getListForElement: function(aElement) {
73 let index = 0;
74 let items = [];
75 this.forOptions(aElement, function(aNode, aOptions, aParent) {
76 let item = {
77 label: aNode.text || aNode.label,
78 header: aOptions.isGroup,
79 disabled: aNode.disabled,
80 id: index,
81 selected: aNode.selected
82 }
83
84 if (aParent) {
85 item.child = true;
86 item.disabled = item.disabled || aParent.disabled;
87 }
88 items.push(item);
89
90 index++;
91 });
92 return items;
93 },
94
95 forOptions: function(aElement, aFunction, aParent = null) {
96 let element = aElement;
97 if (aElement instanceof Ci.nsIDOMXULMenuListElement)
98 element = aElement.menupopup;
99 let children = element.children;
100 let numChildren = children.length;
101
102 // if there are no children in this select, we add a dummy row so that at least something appears
103 if (numChildren == 0)
104 aFunction.call(this, { label: "" }, { isGroup: false }, aParent);
105
106 for (let i = 0; i < numChildren; i++) {
107 let child = children[i];
108 if (child instanceof HTMLOptionElement ||
109 child instanceof Ci.nsIDOMXULSelectControlItemElement) {
110 aFunction.call(this, child, { isGroup: false }, aParent);
111 } else if (child instanceof HTMLOptGroupElement) {
112 aFunction.call(this, child, { isGroup: true });
113 this.forOptions(child, aFunction, child);
114
115 }
116 }
117 },
118
119 fireOnChange: function(aElement) {
120 let evt = aElement.ownerDocument.createEvent("Events");
121 evt.initEvent("change", true, true, aElement.defaultView, 0,
122 false, false,
123 false, false, null);
124 setTimeout(function() {
125 aElement.dispatchEvent(evt);
126 }, 0);
127 },
128
129 fireOnCommand: function(aElement) {
130 let evt = aElement.ownerDocument.createEvent("XULCommandEvent");
131 evt.initCommandEvent("command", true, true, aElement.defaultView, 0,
132 false, false,
133 false, false, null);
134 setTimeout(function() {
135 aElement.dispatchEvent(evt);
136 }, 0);
137 }
138 };

mercurial