mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-31 14:15:30 +00:00
146 lines
4.1 KiB
JavaScript
146 lines
4.1 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
"use strict";
|
|
|
|
var SelectHelper = {
|
|
_uiBusy: false,
|
|
|
|
handleEvent: function(aEvent) {
|
|
this.handleClick(aEvent.target);
|
|
},
|
|
|
|
handleClick: function(aTarget) {
|
|
// if we're busy looking at a select we want to eat any clicks that
|
|
// come to us, but not to process them
|
|
if (this._uiBusy || !this._isMenu(aTarget) || aTarget.disabled)
|
|
return;
|
|
|
|
this._uiBusy = true;
|
|
this.show(aTarget);
|
|
this._uiBusy = false;
|
|
},
|
|
|
|
show: function(aElement) {
|
|
let list = this.getListForElement(aElement);
|
|
|
|
let p = new Prompt({
|
|
window: aElement.contentDocument
|
|
});
|
|
|
|
if (aElement.multiple) {
|
|
p.addButton({
|
|
label: Strings.browser.GetStringFromName("selectHelper.closeMultipleSelectDialog")
|
|
}).setMultiChoiceItems(list);
|
|
} else {
|
|
p.setSingleChoiceItems(list);
|
|
}
|
|
|
|
p.show((function(data) {
|
|
let selected = data.button;
|
|
if (selected == -1)
|
|
return;
|
|
|
|
if (aElement instanceof Ci.nsIDOMXULMenuListElement) {
|
|
if (aElement.selectedIndex != selected) {
|
|
aElement.selectedIndex = selected;
|
|
this.fireOnCommand(aElement);
|
|
}
|
|
} else if (aElement instanceof HTMLSelectElement) {
|
|
let changed = false;
|
|
if (!Array.isArray(selected)) {
|
|
let temp = [];
|
|
for (let i = 0; i <= list.length; i++) {
|
|
temp[i] = (i == selected);
|
|
}
|
|
selected = temp;
|
|
}
|
|
|
|
let i = 0;
|
|
this.forOptions(aElement, function(aNode) {
|
|
if (aNode.selected != selected[i]) {
|
|
changed = true;
|
|
aNode.selected = selected[i];
|
|
}
|
|
i++
|
|
});
|
|
|
|
if (changed)
|
|
this.fireOnChange(aElement);
|
|
}
|
|
}).bind(this));
|
|
},
|
|
|
|
_isMenu: function(aElement) {
|
|
return (aElement instanceof HTMLSelectElement ||
|
|
aElement instanceof Ci.nsIDOMXULMenuListElement);
|
|
},
|
|
|
|
getListForElement: function(aElement) {
|
|
let index = 0;
|
|
let items = [];
|
|
this.forOptions(aElement, function(aNode, aOptions, aParent) {
|
|
let item = {
|
|
label: aNode.text || aNode.label,
|
|
header: aOptions.isGroup,
|
|
disabled: aNode.disabled,
|
|
id: index,
|
|
selected: aNode.selected
|
|
}
|
|
|
|
if (aParent) {
|
|
item.child = true;
|
|
item.disabled = item.disabled || aParent.disabled;
|
|
}
|
|
items.push(item);
|
|
|
|
index++;
|
|
});
|
|
return items;
|
|
},
|
|
|
|
forOptions: function(aElement, aFunction, aParent = null) {
|
|
let element = aElement;
|
|
if (aElement instanceof Ci.nsIDOMXULMenuListElement)
|
|
element = aElement.menupopup;
|
|
let children = element.children;
|
|
let numChildren = children.length;
|
|
|
|
// if there are no children in this select, we add a dummy row so that at least something appears
|
|
if (numChildren == 0)
|
|
aFunction.call(this, { label: "" }, { isGroup: false }, aParent);
|
|
|
|
for (let i = 0; i < numChildren; i++) {
|
|
let child = children[i];
|
|
if (child instanceof HTMLOptionElement ||
|
|
child instanceof Ci.nsIDOMXULSelectControlItemElement) {
|
|
aFunction.call(this, child, { isGroup: false }, aParent);
|
|
} else if (child instanceof HTMLOptGroupElement) {
|
|
aFunction.call(this, child, { isGroup: true });
|
|
this.forOptions(child, aFunction, child);
|
|
|
|
}
|
|
}
|
|
},
|
|
|
|
fireOnChange: function(aElement) {
|
|
let evt = aElement.ownerDocument.createEvent("Events");
|
|
evt.initEvent("change", true, true, aElement.defaultView, 0,
|
|
false, false,
|
|
false, false, null);
|
|
setTimeout(function() {
|
|
aElement.dispatchEvent(evt);
|
|
}, 0);
|
|
},
|
|
|
|
fireOnCommand: function(aElement) {
|
|
let evt = aElement.ownerDocument.createEvent("XULCommandEvent");
|
|
evt.initCommandEvent("command", true, true, aElement.defaultView, 0,
|
|
false, false,
|
|
false, false, null);
|
|
setTimeout(function() {
|
|
aElement.dispatchEvent(evt);
|
|
}, 0);
|
|
}
|
|
};
|