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