diff options
Diffstat (limited to 'toolkit/content/widgets/button.xml')
-rw-r--r-- | toolkit/content/widgets/button.xml | 389 |
1 files changed, 389 insertions, 0 deletions
diff --git a/toolkit/content/widgets/button.xml b/toolkit/content/widgets/button.xml new file mode 100644 index 0000000000..89d9d86c6d --- /dev/null +++ b/toolkit/content/widgets/button.xml @@ -0,0 +1,389 @@ +<?xml version="1.0"?> +<!-- 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/. --> + + +<bindings id="buttonBindings" + xmlns="http://www.mozilla.org/xbl" + xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + xmlns:xbl="http://www.mozilla.org/xbl"> + + <binding id="button-base" extends="chrome://global/content/bindings/general.xml#basetext" role="xul:button"> + <implementation implements="nsIDOMXULButtonElement"> + <property name="type" + onget="return this.getAttribute('type');" + onset="this.setAttribute('type', val); return val;"/> + + <property name="dlgType" + onget="return this.getAttribute('dlgtype');" + onset="this.setAttribute('dlgtype', val); return val;"/> + + <property name="group" + onget="return this.getAttribute('group');" + onset="this.setAttribute('group', val); return val;"/> + + <property name="open" onget="return this.hasAttribute('open');"> + <setter><![CDATA[ + if (this.boxObject instanceof MenuBoxObject) { + this.boxObject.openMenu(val); + } else if (val) { + // Fall back to just setting the attribute + this.setAttribute('open', 'true'); + } else { + this.removeAttribute('open'); + } + return val; + ]]></setter> + </property> + + <property name="checked" onget="return this.hasAttribute('checked');"> + <setter><![CDATA[ + if (this.type == "checkbox") { + this.checkState = val ? 1 : 0; + } else if (this.type == "radio" && val) { + var sibs = this.parentNode.getElementsByAttribute("group", this.group); + for (var i = 0; i < sibs.length; ++i) + sibs[i].removeAttribute("checked"); + } + + if (val) + this.setAttribute("checked", "true"); + else + this.removeAttribute("checked"); + + return val; + ]]></setter> + </property> + + <property name="checkState"> + <getter><![CDATA[ + var state = this.getAttribute("checkState"); + if (state == "") + return this.checked ? 1 : 0; + if (state == "0") + return 0; + if (state == "2") + return 2; + return 1; + ]]></getter> + <setter><![CDATA[ + this.setAttribute("checkState", val); + return val; + ]]></setter> + </property> + + <property name="autoCheck" + onget="return this.getAttribute('autoCheck') == 'true';" + onset="this.setAttribute('autoCheck', val); return val;"/> + + <method name ="filterButtons"> + <parameter name="node"/> + <body> + <![CDATA[ + // if the node isn't visible, don't descend into it. + var cs = node.ownerDocument.defaultView.getComputedStyle(node, null); + if (cs.visibility != "visible" || cs.display == "none") { + return NodeFilter.FILTER_REJECT; + } + // but it may be a popup element, in which case we look at "state"... + if (cs.display == "-moz-popup" && node.state != "open") { + return NodeFilter.FILTER_REJECT; + } + // OK - the node seems visible, so it is a candidate. + if (node.localName == "button" && node.accessKey && !node.disabled) + return NodeFilter.FILTER_ACCEPT; + return NodeFilter.FILTER_SKIP; + ]]> + </body> + </method> + + <method name="fireAccessKeyButton"> + <parameter name="aSubtree"/> + <parameter name="aAccessKeyLower"/> + <body> + <![CDATA[ + var iterator = aSubtree.ownerDocument.createTreeWalker(aSubtree, + NodeFilter.SHOW_ELEMENT, + this.filterButtons); + while (iterator.nextNode()) { + var test = iterator.currentNode; + if (test.accessKey.toLowerCase() == aAccessKeyLower && + !test.disabled && !test.collapsed && !test.hidden) { + test.focus(); + test.click(); + return true; + } + } + return false; + ]]> + </body> + </method> + + <method name="_handleClick"> + <body> + <![CDATA[ + if (!this.disabled && + (this.autoCheck || !this.hasAttribute("autoCheck"))) { + + if (this.type == "checkbox") { + this.checked = !this.checked; + } else if (this.type == "radio") { + this.checked = true; + } + } + ]]> + </body> + </method> + </implementation> + + <handlers> + <!-- While it would seem we could do this by handling oncommand, we can't + because any external oncommand handlers might get called before ours, + and then they would see the incorrect value of checked. Additionally + a command attribute would redirect the command events anyway.--> + <handler event="click" button="0" action="this._handleClick();"/> + <handler event="keypress" key=" "> + <![CDATA[ + this._handleClick(); + // Prevent page from scrolling on the space key. + event.preventDefault(); + ]]> + </handler> + + <handler event="keypress"> + <![CDATA[ + if (this.boxObject instanceof MenuBoxObject) { + if (this.open) + return; + } else { + if (event.keyCode == KeyEvent.DOM_VK_UP || + (event.keyCode == KeyEvent.DOM_VK_LEFT && + document.defaultView.getComputedStyle(this.parentNode, "") + .direction == "ltr") || + (event.keyCode == KeyEvent.DOM_VK_RIGHT && + document.defaultView.getComputedStyle(this.parentNode, "") + .direction == "rtl")) { + event.preventDefault(); + window.document.commandDispatcher.rewindFocus(); + return; + } + + if (event.keyCode == KeyEvent.DOM_VK_DOWN || + (event.keyCode == KeyEvent.DOM_VK_RIGHT && + document.defaultView.getComputedStyle(this.parentNode, "") + .direction == "ltr") || + (event.keyCode == KeyEvent.DOM_VK_LEFT && + document.defaultView.getComputedStyle(this.parentNode, "") + .direction == "rtl")) { + event.preventDefault(); + window.document.commandDispatcher.advanceFocus(); + return; + } + } + + if (event.keyCode || event.charCode <= 32 || event.altKey || + event.ctrlKey || event.metaKey) + return; // No printable char pressed, not a potential accesskey + + // Possible accesskey pressed + var charPressedLower = String.fromCharCode(event.charCode).toLowerCase(); + + // If the accesskey of the current button is pressed, just activate it + if (this.accessKey.toLowerCase() == charPressedLower) { + this.click(); + return; + } + + // Search for accesskey in the list of buttons for this doc and each subdoc + // Get the buttons for the main document and all sub-frames + for (var frameCount = -1; frameCount < window.top.frames.length; frameCount++) { + var doc = (frameCount == -1)? window.top.document: + window.top.frames[frameCount].document + if (this.fireAccessKeyButton(doc.documentElement, charPressedLower)) + return; + } + + // Test anonymous buttons + var dlg = window.top.document; + var buttonBox = dlg.getAnonymousElementByAttribute(dlg.documentElement, + "anonid", "buttons"); + if (buttonBox) + this.fireAccessKeyButton(buttonBox, charPressedLower); + ]]> + </handler> + </handlers> + </binding> + + <binding id="button" display="xul:button" + extends="chrome://global/content/bindings/button.xml#button-base"> + <resources> + <stylesheet src="chrome://global/skin/button.css"/> + </resources> + + <content> + <children includes="observes|template|menupopup|panel|tooltip"/> + <xul:hbox class="box-inherit button-box" xbl:inherits="align,dir,pack,orient" + align="center" pack="center" flex="1" anonid="button-box"> + <children> + <xul:image class="button-icon" xbl:inherits="src=image"/> + <xul:label class="button-text" xbl:inherits="value=label,accesskey,crop"/> + </children> + </xul:hbox> + </content> + </binding> + + <binding id="menu" display="xul:menu" + extends="chrome://global/content/bindings/button.xml#button"> + <content> + <children includes="observes|template|menupopup|panel|tooltip"/> + <xul:hbox class="box-inherit button-box" xbl:inherits="align,dir,pack,orient" + align="center" pack="center" flex="1"> + <children> + <xul:hbox class="box-inherit" xbl:inherits="align,dir,pack,orient" + align="center" pack="center" flex="1"> + <xul:image class="button-icon" xbl:inherits="src=image"/> + <xul:label class="button-text" xbl:inherits="value=label,accesskey,crop"/> + </xul:hbox> + <xul:dropmarker class="button-menu-dropmarker" xbl:inherits="open,disabled,label"/> + </children> + </xul:hbox> + </content> + + <handlers> + <handler event="keypress" keycode="VK_RETURN" action="this.open = true;"/> + <handler event="keypress" key=" "> + <![CDATA[ + this.open = true; + // Prevent page from scrolling on the space key. + event.preventDefault(); + ]]> + </handler> + </handlers> + </binding> + + <binding id="menu-button-base" + extends="chrome://global/content/bindings/button.xml#button-base"> + <implementation implements="nsIDOMEventListener"> + <constructor> + this.init(); + </constructor> + + <method name="init"> + <body> + <![CDATA[ + var btn = document.getAnonymousElementByAttribute(this, "anonid", "button"); + if (!btn) + throw "XBL binding for <button type=\"menu-button\"/> binding must contain an element with anonid=\"button\""; + + var menubuttonParent = this; + btn.addEventListener("mouseover", function() { + if (!this.disabled) + menubuttonParent.buttonover = true; + }, true); + btn.addEventListener("mouseout", function() { + menubuttonParent.buttonover = false; + }, true); + btn.addEventListener("mousedown", function() { + if (!this.disabled) { + menubuttonParent.buttondown = true; + document.addEventListener("mouseup", menubuttonParent, true); + } + }, true); + ]]> + </body> + </method> + + <property name="buttonover" onget="return this.getAttribute('buttonover');"> + <setter> + <![CDATA[ + var v = val || val == "true"; + if (!v && this.buttondown) { + this.buttondown = false; + this._pendingActive = true; + } + else if (this._pendingActive) { + this.buttondown = true; + this._pendingActive = false; + } + + if (v) + this.setAttribute("buttonover", "true"); + else + this.removeAttribute("buttonover"); + return val; + ]]> + </setter> + </property> + + <property name="buttondown" onget="return this.getAttribute('buttondown') == 'true';"> + <setter> + <![CDATA[ + if (val || val == "true") + this.setAttribute("buttondown", "true"); + else + this.removeAttribute("buttondown"); + return val; + ]]> + </setter> + </property> + + <field name="_pendingActive">false</field> + + <method name="handleEvent"> + <parameter name="aEvent"/> + <body> + <![CDATA[ + this._pendingActive = false; + this.buttondown = false; + document.removeEventListener("mouseup", this, true); + ]]> + </body> + </method> + + </implementation> + + <handlers> + <handler event="keypress" keycode="VK_RETURN"> + if (event.originalTarget == this) + this.open = true; + </handler> + <handler event="keypress" key=" "> + if (event.originalTarget == this) { + this.open = true; + // Prevent page from scrolling on the space key. + event.preventDefault(); + } + </handler> + </handlers> + </binding> + + <binding id="menu-button" display="xul:menu" + extends="chrome://global/content/bindings/button.xml#menu-button-base"> + <resources> + <stylesheet src="chrome://global/skin/button.css"/> + </resources> + + <content> + <children includes="observes|template|menupopup|panel|tooltip"/> + <xul:button class="box-inherit button-menubutton-button" + anonid="button" flex="1" allowevents="true" + xbl:inherits="disabled,crop,image,label,accesskey,command, + buttonover,buttondown,align,dir,pack,orient"> + <children/> + </xul:button> + <xul:dropmarker class="button-menubutton-dropmarker" xbl:inherits="open,disabled,label"/> + </content> + </binding> + + <binding id="button-image" display="xul:button" + extends="chrome://global/content/bindings/button.xml#button"> + <content> + <xul:image class="button-image-icon" xbl:inherits="src=image"/> + </content> + </binding> + + <binding id="button-repeat" display="xul:autorepeatbutton" + extends="chrome://global/content/bindings/button.xml#button"/> + +</bindings> |