2007-03-22 10:30:00 -07:00
|
|
|
<?xml version="1.0"?>
|
2012-05-21 04:12:37 -07:00
|
|
|
<!-- 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/. -->
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
<bindings id="menulistBindings"
|
|
|
|
xmlns="http://www.mozilla.org/xbl"
|
|
|
|
xmlns:html="http://www.w3.org/1999/xhtml"
|
|
|
|
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
|
|
|
xmlns:xbl="http://www.mozilla.org/xbl">
|
|
|
|
|
|
|
|
<binding id="menulist-base" extends="chrome://global/content/bindings/general.xml#basecontrol">
|
|
|
|
<resources>
|
2009-03-12 07:16:33 -07:00
|
|
|
<stylesheet src="chrome://global/content/menulist.css"/>
|
2007-03-22 10:30:00 -07:00
|
|
|
<stylesheet src="chrome://global/skin/menulist.css"/>
|
|
|
|
</resources>
|
|
|
|
</binding>
|
|
|
|
|
|
|
|
<binding id="menulist" display="xul:menu"
|
|
|
|
extends="chrome://global/content/bindings/menulist.xml#menulist-base">
|
|
|
|
<content sizetopopup="pref">
|
|
|
|
<xul:hbox class="menulist-label-box" flex="1">
|
|
|
|
<xul:image class="menulist-icon" xbl:inherits="src=image,src"/>
|
|
|
|
<xul:label class="menulist-label" xbl:inherits="value=label,crop,accesskey" crop="right" flex="1"/>
|
|
|
|
</xul:hbox>
|
2009-03-13 05:23:26 -07:00
|
|
|
<xul:dropmarker class="menulist-dropmarker" type="menu" xbl:inherits="disabled,open"/>
|
2007-03-22 10:30:00 -07:00
|
|
|
<children includes="menupopup"/>
|
|
|
|
</content>
|
|
|
|
|
|
|
|
<handlers>
|
|
|
|
<handler event="command" phase="capturing"
|
|
|
|
action="if (event.target.parentNode.parentNode == this) this.selectedItem = event.target;"/>
|
|
|
|
|
|
|
|
<handler event="popupshowing">
|
|
|
|
<![CDATA[
|
2011-09-09 22:40:05 -07:00
|
|
|
if (event.target.parentNode == this) {
|
|
|
|
this.menuBoxObject.activeChild = null;
|
|
|
|
if (this.selectedItem)
|
|
|
|
// Not ready for auto-setting the active child in hierarchies yet.
|
|
|
|
// For now, only do this when the outermost menupopup opens.
|
|
|
|
this.menuBoxObject.activeChild = this.mSelectedInternal;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
]]>
|
|
|
|
</handler>
|
|
|
|
|
2009-05-01 05:24:49 -07:00
|
|
|
<handler event="keypress" modifiers="shift any" group="system">
|
2007-03-22 10:30:00 -07:00
|
|
|
<![CDATA[
|
2011-12-08 01:21:32 -08:00
|
|
|
if (!event.defaultPrevented &&
|
2007-11-15 17:30:23 -08:00
|
|
|
(event.keyCode == KeyEvent.DOM_VK_UP ||
|
|
|
|
event.keyCode == KeyEvent.DOM_VK_DOWN ||
|
|
|
|
event.keyCode == KeyEvent.DOM_VK_PAGE_UP ||
|
|
|
|
event.keyCode == KeyEvent.DOM_VK_PAGE_DOWN ||
|
|
|
|
event.keyCode == KeyEvent.DOM_VK_HOME ||
|
|
|
|
event.keyCode == KeyEvent.DOM_VK_END ||
|
|
|
|
event.keyCode == KeyEvent.DOM_VK_BACK_SPACE ||
|
|
|
|
event.charCode > 0)) {
|
|
|
|
// Moving relative to an item: start from the currently selected item
|
2007-03-22 10:30:00 -07:00
|
|
|
this.menuBoxObject.activeChild = this.mSelectedInternal;
|
2008-03-28 01:34:40 -07:00
|
|
|
if (this.menuBoxObject.handleKeyPress(event)) {
|
2007-03-22 10:30:00 -07:00
|
|
|
this.menuBoxObject.activeChild.doCommand();
|
2008-03-28 01:34:40 -07:00
|
|
|
event.preventDefault();
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
]]>
|
|
|
|
</handler>
|
|
|
|
</handlers>
|
|
|
|
|
2007-09-29 20:40:05 -07:00
|
|
|
<implementation implements="nsIDOMXULMenuListElement, nsIAccessibleProvider, nsIDOMEventListener">
|
2007-03-22 10:30:00 -07:00
|
|
|
<constructor>
|
|
|
|
this.setInitialSelection()
|
|
|
|
</constructor>
|
|
|
|
|
|
|
|
<method name="setInitialSelection">
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
var popup = this.menupopup;
|
|
|
|
if (popup) {
|
|
|
|
var arr = popup.getElementsByAttribute('selected', 'true');
|
|
|
|
|
|
|
|
var editable = this.editable;
|
|
|
|
var value = this.value;
|
|
|
|
if (!arr.item(0) && value)
|
|
|
|
arr = popup.getElementsByAttribute(editable ? 'label' : 'value', value);
|
|
|
|
|
|
|
|
if (arr.item(0))
|
|
|
|
this.selectedItem = arr[0];
|
|
|
|
else if (!editable)
|
|
|
|
this.selectedIndex = 0;
|
|
|
|
}
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<property name="value" onget="return this.getAttribute('value');">
|
|
|
|
<setter>
|
|
|
|
<![CDATA[
|
2008-01-14 20:42:13 -08:00
|
|
|
// if the new value is null, we still need to remove the old value
|
2008-01-17 20:29:17 -08:00
|
|
|
if (val == null)
|
2008-01-14 20:42:13 -08:00
|
|
|
return this.selectedItem = val;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
var arr = null;
|
|
|
|
var popup = this.menupopup;
|
|
|
|
if (popup)
|
|
|
|
arr = popup.getElementsByAttribute('value', val);
|
|
|
|
|
|
|
|
if (arr && arr.item(0))
|
|
|
|
this.selectedItem = arr[0];
|
2008-01-17 20:29:17 -08:00
|
|
|
else {
|
|
|
|
this.selectedItem = null;
|
2007-03-22 10:30:00 -07:00
|
|
|
this.setAttribute('value', val);
|
2008-01-17 20:29:17 -08:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
return val;
|
|
|
|
]]>
|
|
|
|
</setter>
|
|
|
|
</property>
|
|
|
|
|
|
|
|
<property name="inputField" readonly="true" onget="return null;"/>
|
|
|
|
|
|
|
|
<property name="crop" onset="this.setAttribute('crop',val); return val;"
|
|
|
|
onget="return this.getAttribute('crop');"/>
|
|
|
|
<property name="image" onset="this.setAttribute('image',val); return val;"
|
|
|
|
onget="return this.getAttribute('image');"/>
|
|
|
|
<property name="label" readonly="true" onget="return this.getAttribute('label');"/>
|
|
|
|
<property name="description" onset="this.setAttribute('description',val); return val;"
|
|
|
|
onget="return this.getAttribute('description');"/>
|
|
|
|
<property name="editable" onset="this.setAttribute('editable',val); return val;"
|
|
|
|
onget="return this.getAttribute('editable') == 'true';"/>
|
|
|
|
|
|
|
|
<property name="open" onset="this.menuBoxObject.openMenu(val);
|
|
|
|
return val;"
|
|
|
|
onget="return this.hasAttribute('open');"/>
|
|
|
|
|
|
|
|
<property name="itemCount" readonly="true"
|
|
|
|
onget="return this.menupopup ? this.menupopup.childNodes.length : 0"/>
|
|
|
|
|
|
|
|
<property name="menupopup" readonly="true">
|
|
|
|
<getter>
|
|
|
|
<![CDATA[
|
|
|
|
var popup = this.firstChild;
|
|
|
|
while (popup && popup.localName != "menupopup")
|
|
|
|
popup = popup.nextSibling;
|
|
|
|
return popup;
|
|
|
|
]]>
|
|
|
|
</getter>
|
|
|
|
</property>
|
|
|
|
|
|
|
|
<field name="menuBoxObject" readonly="true">
|
|
|
|
this.boxObject.QueryInterface(Components.interfaces.nsIMenuBoxObject)
|
|
|
|
</field>
|
|
|
|
|
|
|
|
<field name="mSelectedInternal">
|
|
|
|
null
|
|
|
|
</field>
|
|
|
|
|
|
|
|
<method name="contains">
|
|
|
|
<parameter name="item"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
if (!item)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
var parent = item.parentNode;
|
|
|
|
return (parent && parent.parentNode == this);
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<property name="selectedIndex">
|
|
|
|
<getter>
|
|
|
|
<![CDATA[
|
|
|
|
// Quick and dirty. We won't deal with hierarchical menulists yet.
|
|
|
|
if (!this.selectedItem ||
|
|
|
|
!this.mSelectedInternal.parentNode ||
|
|
|
|
this.mSelectedInternal.parentNode.parentNode != this)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
var children = this.mSelectedInternal.parentNode.childNodes;
|
|
|
|
var i = children.length;
|
|
|
|
while (i--)
|
|
|
|
if (children[i] == this.mSelectedInternal)
|
|
|
|
break;
|
|
|
|
|
|
|
|
return i;
|
|
|
|
]]>
|
|
|
|
</getter>
|
|
|
|
<setter>
|
|
|
|
<![CDATA[
|
|
|
|
var popup = this.menupopup;
|
2009-08-14 14:16:02 -07:00
|
|
|
if (popup && 0 <= val) {
|
|
|
|
if (val < popup.childNodes.length)
|
|
|
|
this.selectedItem = popup.childNodes[val];
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
else
|
|
|
|
this.selectedItem = null;
|
2009-08-14 14:16:02 -07:00
|
|
|
return val;
|
2007-03-22 10:30:00 -07:00
|
|
|
]]>
|
|
|
|
</setter>
|
|
|
|
</property>
|
|
|
|
|
|
|
|
<property name="selectedItem">
|
|
|
|
<getter>
|
|
|
|
<![CDATA[
|
|
|
|
return this.mSelectedInternal;
|
|
|
|
]]>
|
|
|
|
</getter>
|
|
|
|
<setter>
|
|
|
|
<![CDATA[
|
|
|
|
var oldval = this.mSelectedInternal;
|
|
|
|
if (oldval == val)
|
|
|
|
return val;
|
|
|
|
|
|
|
|
if (val && !this.contains(val))
|
|
|
|
return val;
|
|
|
|
|
|
|
|
if (oldval) {
|
|
|
|
oldval.removeAttribute('selected');
|
2007-09-29 20:40:05 -07:00
|
|
|
if (document instanceof Components.interfaces.nsIDOMXULDocument) {
|
|
|
|
document.removeBroadcastListenerFor(oldval, this, "value");
|
|
|
|
document.removeBroadcastListenerFor(oldval, this, "label");
|
|
|
|
document.removeBroadcastListenerFor(oldval, this, "image");
|
|
|
|
document.removeBroadcastListenerFor(oldval, this, "description");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
oldval.removeEventListener("DOMAttrModified", this, false);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
this.mSelectedInternal = val;
|
|
|
|
if (val) {
|
|
|
|
val.setAttribute('selected', 'true');
|
|
|
|
this.setAttribute('value', val.getAttribute('value'));
|
|
|
|
this.setAttribute('image', val.getAttribute('image'));
|
|
|
|
this.setAttribute('label', val.getAttribute('label'));
|
|
|
|
this.setAttribute('description', val.getAttribute('description'));
|
2007-09-29 20:40:05 -07:00
|
|
|
// DOMAttrModified listeners slow down setAttribute calls within
|
|
|
|
// the document, see bug 395496
|
|
|
|
if (document instanceof Components.interfaces.nsIDOMXULDocument) {
|
|
|
|
document.addBroadcastListenerFor(val, this, "value");
|
|
|
|
document.addBroadcastListenerFor(val, this, "label");
|
|
|
|
document.addBroadcastListenerFor(val, this, "image");
|
|
|
|
document.addBroadcastListenerFor(val, this, "description");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
val.addEventListener("DOMAttrModified", this, false);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
this.removeAttribute('value');
|
|
|
|
this.removeAttribute('image');
|
|
|
|
this.removeAttribute('label');
|
|
|
|
this.removeAttribute('description');
|
|
|
|
}
|
|
|
|
|
|
|
|
var event = document.createEvent("Events");
|
|
|
|
event.initEvent("select", true, true);
|
|
|
|
this.dispatchEvent(event);
|
|
|
|
|
|
|
|
var event = document.createEvent("Events");
|
|
|
|
event.initEvent("ValueChange", true, true);
|
|
|
|
this.dispatchEvent(event);
|
|
|
|
|
|
|
|
return val;
|
|
|
|
]]>
|
|
|
|
</setter>
|
|
|
|
</property>
|
|
|
|
|
2007-09-29 20:40:05 -07:00
|
|
|
<method name="handleEvent">
|
|
|
|
<parameter name="aEvent"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
if (aEvent.type == "DOMAttrModified" &&
|
|
|
|
aEvent.target == this.mSelectedInternal) {
|
|
|
|
var attrName = aEvent.attrName;
|
|
|
|
switch (attrName) {
|
|
|
|
case "value":
|
|
|
|
case "label":
|
|
|
|
case "image":
|
|
|
|
case "description":
|
|
|
|
this.setAttribute(attrName, aEvent.newValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
<method name="getIndexOfItem">
|
|
|
|
<parameter name="item"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
var popup = this.menupopup;
|
|
|
|
if (popup) {
|
|
|
|
var children = popup.childNodes;
|
|
|
|
var i = children.length;
|
|
|
|
while (i--)
|
|
|
|
if (children[i] == item)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="getItemAtIndex">
|
|
|
|
<parameter name="index"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
var popup = this.menupopup;
|
|
|
|
if (popup) {
|
|
|
|
var children = popup.childNodes;
|
|
|
|
if (index >= 0 && index < children.length)
|
|
|
|
return children[index];
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="appendItem">
|
|
|
|
<parameter name="label"/>
|
|
|
|
<parameter name="value"/>
|
|
|
|
<parameter name="description"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
|
|
|
var popup = this.menupopup ||
|
|
|
|
this.appendChild(document.createElementNS(XULNS, "menupopup"));
|
|
|
|
var item = document.createElementNS(XULNS, "menuitem");
|
|
|
|
item.setAttribute("label", label);
|
|
|
|
item.setAttribute("value", value);
|
|
|
|
if (description)
|
|
|
|
item.setAttribute("description", description);
|
|
|
|
|
|
|
|
popup.appendChild(item);
|
|
|
|
return item;
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="insertItemAt">
|
|
|
|
<parameter name="index"/>
|
|
|
|
<parameter name="label"/>
|
|
|
|
<parameter name="value"/>
|
|
|
|
<parameter name="description"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
|
|
|
var popup = this.menupopup ||
|
|
|
|
this.appendChild(document.createElementNS(XULNS, "menupopup"));
|
|
|
|
var item = document.createElementNS(XULNS, "menuitem");
|
|
|
|
item.setAttribute("label", label);
|
|
|
|
item.setAttribute("value", value);
|
|
|
|
if (description)
|
|
|
|
item.setAttribute("description", description);
|
|
|
|
|
|
|
|
if (index >= 0 && index < popup.childNodes.length)
|
|
|
|
popup.insertBefore(item, popup.childNodes[index]);
|
|
|
|
else
|
|
|
|
popup.appendChild(item);
|
|
|
|
return item;
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="removeItemAt">
|
|
|
|
<parameter name="index"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
var popup = this.menupopup;
|
|
|
|
if (popup && 0 <= index && index < popup.childNodes.length) {
|
|
|
|
var remove = popup.childNodes[index];
|
|
|
|
popup.removeChild(remove);
|
|
|
|
return remove;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="removeAllItems">
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
this.selectedItem = null;
|
|
|
|
var popup = this.menupopup;
|
|
|
|
if (popup)
|
|
|
|
this.removeChild(popup);
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<property name="accessibleType" readonly="true">
|
|
|
|
<getter>
|
|
|
|
<![CDATA[
|
2012-03-23 06:04:02 -07:00
|
|
|
// Droppable is currently used for the Firefox bookmarks dialog only
|
2007-03-22 10:30:00 -07:00
|
|
|
return (this.getAttribute("droppable") == "false") ?
|
|
|
|
Components.interfaces.nsIAccessibleProvider.XULTextBox :
|
|
|
|
Components.interfaces.nsIAccessibleProvider.XULCombobox;
|
|
|
|
]]>
|
|
|
|
</getter>
|
|
|
|
</property>
|
|
|
|
|
|
|
|
<destructor>
|
|
|
|
<![CDATA[
|
2007-09-21 09:09:45 -07:00
|
|
|
if (this.mSelectedInternal) {
|
2007-09-29 20:40:05 -07:00
|
|
|
if (document instanceof Components.interfaces.nsIDOMXULDocument) {
|
|
|
|
document.removeBroadcastListenerFor(this.mSelectedInternal, this, "value");
|
|
|
|
document.removeBroadcastListenerFor(this.mSelectedInternal, this, "label");
|
|
|
|
document.removeBroadcastListenerFor(this.mSelectedInternal, this, "image");
|
|
|
|
document.removeBroadcastListenerFor(this.mSelectedInternal, this, "description");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
this.mSelectedInternal.removeEventListener("DOMAttrModified", this, false);
|
2007-09-21 09:09:45 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
]]>
|
|
|
|
</destructor>
|
|
|
|
</implementation>
|
|
|
|
</binding>
|
|
|
|
|
|
|
|
<binding id="menulist-editable" extends="chrome://global/content/bindings/menulist.xml#menulist">
|
|
|
|
<content sizetopopup="pref">
|
2008-01-14 02:20:59 -08:00
|
|
|
<xul:hbox class="menulist-editable-box textbox-input-box" xbl:inherits="context,disabled,readonly,focused" flex="1">
|
2011-04-22 18:36:24 -07:00
|
|
|
<html:input class="menulist-editable-input" anonid="input" allowevents="true"
|
2010-12-11 00:38:31 -08:00
|
|
|
xbl:inherits="value=label,value,disabled,tabindex,readonly,placeholder"/>
|
2007-03-22 10:30:00 -07:00
|
|
|
</xul:hbox>
|
2008-01-26 21:11:15 -08:00
|
|
|
<xul:dropmarker class="menulist-dropmarker" type="menu"
|
2009-03-13 05:23:26 -07:00
|
|
|
xbl:inherits="open,disabled,parentfocused=focused"/>
|
2007-03-22 10:30:00 -07:00
|
|
|
<children includes="menupopup"/>
|
|
|
|
</content>
|
|
|
|
|
|
|
|
<implementation>
|
|
|
|
<method name="_selectInputFieldValueInList">
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
if (this.hasAttribute("disableautoselect"))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Find and select the menuitem that matches inputField's "value"
|
|
|
|
var arr = null;
|
|
|
|
var popup = this.menupopup;
|
|
|
|
|
|
|
|
if (popup)
|
|
|
|
arr = popup.getElementsByAttribute('label', this.inputField.value);
|
|
|
|
|
|
|
|
this.setSelectionInternal(arr ? arr.item(0) : null);
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="setSelectionInternal">
|
|
|
|
<parameter name="val"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
// This is called internally to set selected item
|
|
|
|
// without triggering infinite loop
|
|
|
|
// when using selectedItem's setter
|
|
|
|
if (this.mSelectedInternal == val)
|
|
|
|
return val;
|
|
|
|
|
|
|
|
if (this.mSelectedInternal)
|
|
|
|
this.mSelectedInternal.removeAttribute('selected');
|
|
|
|
|
|
|
|
this.mSelectedInternal = val;
|
|
|
|
|
|
|
|
if (val)
|
|
|
|
val.setAttribute('selected', 'true');
|
|
|
|
|
|
|
|
//Do NOT change the "value", which is owned by inputField
|
|
|
|
return val;
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<field name="mInputField">null</field>
|
|
|
|
|
|
|
|
<property name="inputField" readonly="true">
|
|
|
|
<getter><![CDATA[
|
|
|
|
if (!this.mInputField)
|
|
|
|
this.mInputField = document.getAnonymousElementByAttribute(this, "anonid", "input");
|
|
|
|
return this.mInputField;
|
|
|
|
]]></getter>
|
|
|
|
</property>
|
|
|
|
|
|
|
|
<property name="label" onset="this.inputField.value = val; return val;"
|
|
|
|
onget="return this.inputField.value;"/>
|
|
|
|
|
|
|
|
<property name="value" onget="return this.inputField.value;">
|
|
|
|
<setter>
|
|
|
|
<![CDATA[
|
|
|
|
// Override menulist's value setter to refer to the inputField's value
|
|
|
|
// (Allows using "menulist.value" instead of "menulist.inputField.value")
|
|
|
|
this.inputField.value = val;
|
|
|
|
this.setAttribute('value', val);
|
|
|
|
this.setAttribute('label', val);
|
|
|
|
this._selectInputFieldValueInList();
|
|
|
|
return val;
|
|
|
|
]]>
|
|
|
|
</setter>
|
|
|
|
</property>
|
|
|
|
|
|
|
|
<property name="selectedItem">
|
|
|
|
<getter>
|
|
|
|
<![CDATA[
|
|
|
|
// Make sure internally-selected item
|
|
|
|
// is in sync with inputField.value
|
|
|
|
this._selectInputFieldValueInList();
|
|
|
|
return this.mSelectedInternal;
|
|
|
|
]]>
|
|
|
|
</getter>
|
|
|
|
<setter>
|
|
|
|
<![CDATA[
|
|
|
|
var oldval = this.mSelectedInternal;
|
|
|
|
if (oldval == val)
|
|
|
|
return val;
|
|
|
|
|
|
|
|
if (val && !this.contains(val))
|
|
|
|
return val;
|
|
|
|
|
|
|
|
// This doesn't touch inputField.value or "value" and "label" attributes
|
|
|
|
this.setSelectionInternal(val);
|
|
|
|
if (val) {
|
|
|
|
// Editable menulist uses "label" as its "value"
|
|
|
|
var label = val.getAttribute('label');
|
|
|
|
this.inputField.value = label;
|
|
|
|
this.setAttribute('value', label);
|
|
|
|
this.setAttribute('label', label);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
this.inputField.value = "";
|
|
|
|
this.removeAttribute('value');
|
|
|
|
this.removeAttribute('label');
|
|
|
|
}
|
|
|
|
|
|
|
|
var event = document.createEvent("Events");
|
|
|
|
event.initEvent("select", true, true);
|
|
|
|
this.dispatchEvent(event);
|
|
|
|
|
|
|
|
var event = document.createEvent("Events");
|
|
|
|
event.initEvent("ValueChange", true, true);
|
|
|
|
this.dispatchEvent(event);
|
|
|
|
|
|
|
|
return val;
|
|
|
|
]]>
|
|
|
|
</setter>
|
|
|
|
</property>
|
|
|
|
<property name="disableautoselect"
|
|
|
|
onset="if (val) this.setAttribute('disableautoselect','true');
|
|
|
|
else this.removeAttribute('disableautoselect'); return val;"
|
|
|
|
onget="return this.hasAttribute('disableautoselect');"/>
|
|
|
|
|
|
|
|
<property name="editor" readonly="true">
|
|
|
|
<getter><![CDATA[
|
|
|
|
const nsIDOMNSEditableElement = Components.interfaces.nsIDOMNSEditableElement;
|
|
|
|
return this.inputField.QueryInterface(nsIDOMNSEditableElement).editor;
|
|
|
|
]]></getter>
|
|
|
|
</property>
|
|
|
|
|
2007-09-21 15:57:18 -07:00
|
|
|
<property name="readOnly" onset="this.inputField.readOnly = val;
|
|
|
|
if (val) this.setAttribute('readonly', 'true');
|
|
|
|
else this.removeAttribute('readonly'); return val;"
|
|
|
|
onget="return this.inputField.readOnly;"/>
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
<method name="select">
|
|
|
|
<body>
|
|
|
|
this.inputField.select();
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
</implementation>
|
|
|
|
|
|
|
|
<handlers>
|
|
|
|
<handler event="focus" phase="capturing">
|
|
|
|
<![CDATA[
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 11:00:39 -07:00
|
|
|
this.setAttribute('focused','true');
|
2007-03-22 10:30:00 -07:00
|
|
|
]]>
|
|
|
|
</handler>
|
|
|
|
|
|
|
|
<handler event="blur" phase="capturing">
|
|
|
|
<![CDATA[
|
|
|
|
this.removeAttribute('focused');
|
|
|
|
]]>
|
|
|
|
</handler>
|
|
|
|
|
|
|
|
<handler event="popupshowing">
|
|
|
|
<![CDATA[
|
|
|
|
// editable menulists elements aren't in the focus order,
|
|
|
|
// so when the popup opens we need to force the focus to the inputField
|
|
|
|
if (event.target.parentNode == this) {
|
|
|
|
if (document.commandDispatcher.focusedElement != this.inputField)
|
|
|
|
this.inputField.focus();
|
|
|
|
|
2011-09-09 22:40:05 -07:00
|
|
|
this.menuBoxObject.activeChild = null;
|
2007-03-22 10:30:00 -07:00
|
|
|
if (this.selectedItem)
|
|
|
|
// Not ready for auto-setting the active child in hierarchies yet.
|
|
|
|
// For now, only do this when the outermost menupopup opens.
|
|
|
|
this.menuBoxObject.activeChild = this.mSelectedInternal;
|
|
|
|
}
|
|
|
|
]]>
|
|
|
|
</handler>
|
|
|
|
|
|
|
|
<handler event="keypress">
|
|
|
|
<![CDATA[
|
|
|
|
// open popup if key is up arrow, down arrow, or F4
|
|
|
|
if (!event.ctrlKey && !event.shiftKey) {
|
|
|
|
if (event.keyCode == KeyEvent.DOM_VK_UP ||
|
|
|
|
event.keyCode == KeyEvent.DOM_VK_DOWN ||
|
|
|
|
(event.keyCode == KeyEvent.DOM_VK_F4 && !event.altKey)) {
|
|
|
|
event.preventDefault();
|
|
|
|
this.open = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]]>
|
|
|
|
</handler>
|
|
|
|
</handlers>
|
|
|
|
</binding>
|
|
|
|
|
|
|
|
<binding id="menulist-compact" display="xul:menu"
|
|
|
|
extends="chrome://global/content/bindings/menulist.xml#menulist">
|
|
|
|
<content sizetopopup="false">
|
2009-03-13 05:23:26 -07:00
|
|
|
<xul:dropmarker class="menulist-dropmarker" type="menu" xbl:inherits="disabled,open"/>
|
2007-03-22 10:30:00 -07:00
|
|
|
<xul:image class="menulist-icon" xbl:inherits="src=image,src"/>
|
|
|
|
<xul:label class="menulist-label" xbl:inherits="value=label,crop,accesskey" crop="right" flex="1"/>
|
|
|
|
<children includes="menupopup"/>
|
|
|
|
</content>
|
|
|
|
</binding>
|
|
|
|
|
|
|
|
<binding id="menulist-description" display="xul:menu"
|
|
|
|
extends="chrome://global/content/bindings/menulist.xml#menulist">
|
|
|
|
<content sizetopopup="pref">
|
|
|
|
<xul:hbox class="menulist-label-box" flex="1">
|
|
|
|
<xul:image class="menulist-icon" xbl:inherits="src=image,src"/>
|
|
|
|
<xul:label class="menulist-label" xbl:inherits="value=label,crop,accesskey" crop="right" flex="1"/>
|
|
|
|
<xul:label class="menulist-label menulist-description" xbl:inherits="value=description" crop="right" flex="10000"/>
|
|
|
|
</xul:hbox>
|
2009-03-13 05:23:26 -07:00
|
|
|
<xul:dropmarker class="menulist-dropmarker" type="menu" xbl:inherits="disabled,open"/>
|
2007-03-22 10:30:00 -07:00
|
|
|
<children includes="menupopup"/>
|
|
|
|
</content>
|
|
|
|
</binding>
|
|
|
|
</bindings>
|