1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/content/widgets/button.xml Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,376 @@ 1.4 +<?xml version="1.0"?> 1.5 +<!-- This Source Code Form is subject to the terms of the Mozilla Public 1.6 + - License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> 1.8 + 1.9 + 1.10 +<bindings id="buttonBindings" 1.11 + xmlns="http://www.mozilla.org/xbl" 1.12 + xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" 1.13 + xmlns:xbl="http://www.mozilla.org/xbl"> 1.14 + 1.15 + <binding id="button-base" extends="chrome://global/content/bindings/general.xml#basetext" role="xul:button"> 1.16 + <implementation implements="nsIDOMXULButtonElement"> 1.17 + <property name="type" 1.18 + onget="return this.getAttribute('type');" 1.19 + onset="this.setAttribute('type', val); return val;"/> 1.20 + 1.21 + <property name="dlgType" 1.22 + onget="return this.getAttribute('dlgtype');" 1.23 + onset="this.setAttribute('dlgtype', val); return val;"/> 1.24 + 1.25 + <property name="group" 1.26 + onget="return this.getAttribute('group');" 1.27 + onset="this.setAttribute('group', val); return val;"/> 1.28 + 1.29 + <property name="open" onget="return this.hasAttribute('open');"> 1.30 + <setter><![CDATA[ 1.31 + if (this.boxObject instanceof 1.32 + Components.interfaces.nsIMenuBoxObject) { 1.33 + this.boxObject.openMenu(val); 1.34 + } else { 1.35 + // Fall back to just setting the attribute 1.36 + if (val) { 1.37 + this.setAttribute('open', 'true'); 1.38 + } else { 1.39 + this.removeAttribute('open'); 1.40 + } 1.41 + } 1.42 + return val; 1.43 + ]]></setter> 1.44 + </property> 1.45 + 1.46 + <property name="checked" onget="return this.hasAttribute('checked');"> 1.47 + <setter><![CDATA[ 1.48 + if (this.type == "checkbox") { 1.49 + this.checkState = val ? 1 : 0; 1.50 + } else if (this.type == "radio" && val) { 1.51 + var sibs = this.parentNode.getElementsByAttribute("group", this.group); 1.52 + for (var i = 0; i < sibs.length; ++i) 1.53 + sibs[i].removeAttribute("checked"); 1.54 + } 1.55 + 1.56 + if (val) 1.57 + this.setAttribute("checked", "true"); 1.58 + else 1.59 + this.removeAttribute("checked"); 1.60 + 1.61 + return val; 1.62 + ]]></setter> 1.63 + </property> 1.64 + 1.65 + <property name="checkState"> 1.66 + <getter><![CDATA[ 1.67 + var state = this.getAttribute("checkState"); 1.68 + if (state == "") 1.69 + return this.checked ? 1 : 0; 1.70 + else 1.71 + return state == "0" ? 0 : (state == "2" ? 2 : 1); 1.72 + ]]></getter> 1.73 + <setter><![CDATA[ 1.74 + this.setAttribute("checkState", val); 1.75 + return val; 1.76 + ]]></setter> 1.77 + </property> 1.78 + 1.79 + <property name="autoCheck" 1.80 + onget="return this.getAttribute('autoCheck') == 'true';" 1.81 + onset="this.setAttribute('autoCheck', val); return val;"/> 1.82 + 1.83 + <method name ="filterButtons"> 1.84 + <parameter name="node"/> 1.85 + <body> 1.86 + <![CDATA[ 1.87 + // if the node isn't visible, don't descend into it. 1.88 + var cs = node.ownerDocument.defaultView.getComputedStyle(node, null); 1.89 + if (cs.visibility != "visible" || cs.display == "none") { 1.90 + return NodeFilter.FILTER_REJECT; 1.91 + } 1.92 + // but it may be a popup element, in which case we look at "state"... 1.93 + if (cs.display == "-moz-popup" && node.state != "open") { 1.94 + return NodeFilter.FILTER_REJECT; 1.95 + } 1.96 + // OK - the node seems visible, so it is a candidate. 1.97 + if (node.localName == "button" && node.accessKey && !node.disabled) 1.98 + return NodeFilter.FILTER_ACCEPT; 1.99 + return NodeFilter.FILTER_SKIP; 1.100 + ]]> 1.101 + </body> 1.102 + </method> 1.103 + 1.104 + <method name="fireAccessKeyButton"> 1.105 + <parameter name="aSubtree"/> 1.106 + <parameter name="aAccessKeyLower"/> 1.107 + <body> 1.108 + <![CDATA[ 1.109 + var iterator = aSubtree.ownerDocument.createTreeWalker(aSubtree, 1.110 + NodeFilter.SHOW_ELEMENT, 1.111 + this.filterButtons); 1.112 + while (iterator.nextNode()) { 1.113 + var test = iterator.currentNode; 1.114 + if (test.accessKey.toLowerCase() == aAccessKeyLower && 1.115 + !test.disabled && !test.collapsed && !test.hidden) { 1.116 + test.focus(); 1.117 + test.click(); 1.118 + return true; 1.119 + } 1.120 + } 1.121 + return false; 1.122 + ]]> 1.123 + </body> 1.124 + </method> 1.125 + 1.126 + <method name="_handleClick"> 1.127 + <body> 1.128 + <![CDATA[ 1.129 + if (!this.disabled && 1.130 + (this.autoCheck || !this.hasAttribute("autoCheck"))) { 1.131 + 1.132 + if (this.type == "checkbox") { 1.133 + this.checked = !this.checked; 1.134 + } else if (this.type == "radio") { 1.135 + this.checked = true; 1.136 + } 1.137 + } 1.138 + ]]> 1.139 + </body> 1.140 + </method> 1.141 + </implementation> 1.142 + 1.143 + <handlers> 1.144 + <!-- While it would seem we could do this by handling oncommand, we can't 1.145 + because any external oncommand handlers might get called before ours, 1.146 + and then they would see the incorrect value of checked. Additionally 1.147 + a command attribute would redirect the command events anyway.--> 1.148 + <handler event="click" button="0" action="this._handleClick();"/> 1.149 + <handler event="keypress" key=" " action="this._handleClick();"/> 1.150 + 1.151 + <handler event="keypress"> 1.152 + <![CDATA[ 1.153 + if (this.boxObject instanceof Components.interfaces.nsIMenuBoxObject) { 1.154 + if (this.open) 1.155 + return; 1.156 + } else { 1.157 + if (event.keyCode == KeyEvent.DOM_VK_UP || 1.158 + (event.keyCode == KeyEvent.DOM_VK_LEFT && 1.159 + document.defaultView.getComputedStyle(this.parentNode, "") 1.160 + .direction == "ltr") || 1.161 + (event.keyCode == KeyEvent.DOM_VK_RIGHT && 1.162 + document.defaultView.getComputedStyle(this.parentNode, "") 1.163 + .direction == "rtl")) { 1.164 + event.preventDefault(); 1.165 + window.document.commandDispatcher.rewindFocus(); 1.166 + return; 1.167 + } 1.168 + 1.169 + if (event.keyCode == KeyEvent.DOM_VK_DOWN || 1.170 + (event.keyCode == KeyEvent.DOM_VK_RIGHT && 1.171 + document.defaultView.getComputedStyle(this.parentNode, "") 1.172 + .direction == "ltr") || 1.173 + (event.keyCode == KeyEvent.DOM_VK_LEFT && 1.174 + document.defaultView.getComputedStyle(this.parentNode, "") 1.175 + .direction == "rtl")) { 1.176 + event.preventDefault(); 1.177 + window.document.commandDispatcher.advanceFocus(); 1.178 + return; 1.179 + } 1.180 + } 1.181 + 1.182 + if (event.keyCode || event.charCode <= 32 || event.altKey || 1.183 + event.ctrlKey || event.metaKey) 1.184 + return; // No printable char pressed, not a potential accesskey 1.185 + 1.186 + // Possible accesskey pressed 1.187 + var charPressedLower = String.fromCharCode(event.charCode).toLowerCase(); 1.188 + 1.189 + // If the accesskey of the current button is pressed, just activate it 1.190 + if (this.accessKey.toLowerCase() == charPressedLower) { 1.191 + this.click(); 1.192 + return; 1.193 + } 1.194 + 1.195 + // Search for accesskey in the list of buttons for this doc and each subdoc 1.196 + // Get the buttons for the main document and all sub-frames 1.197 + for (var frameCount = -1; frameCount < window.top.frames.length; frameCount++) { 1.198 + var doc = (frameCount == -1)? window.top.document: 1.199 + window.top.frames[frameCount].document 1.200 + if (this.fireAccessKeyButton(doc.documentElement, charPressedLower)) 1.201 + return; 1.202 + } 1.203 + 1.204 + // Test anonymous buttons 1.205 + var dlg = window.top.document; 1.206 + var buttonBox = dlg.getAnonymousElementByAttribute(dlg.documentElement, 1.207 + "anonid", "buttons"); 1.208 + if (buttonBox) 1.209 + this.fireAccessKeyButton(buttonBox, charPressedLower); 1.210 + ]]> 1.211 + </handler> 1.212 + </handlers> 1.213 + </binding> 1.214 + 1.215 + <binding id="button" display="xul:button" 1.216 + extends="chrome://global/content/bindings/button.xml#button-base"> 1.217 + <resources> 1.218 + <stylesheet src="chrome://global/skin/button.css"/> 1.219 + </resources> 1.220 + 1.221 + <content> 1.222 + <children includes="observes|template|menupopup|panel|tooltip"/> 1.223 + <xul:hbox class="box-inherit button-box" xbl:inherits="align,dir,pack,orient" 1.224 + align="center" pack="center" flex="1" anonid="button-box"> 1.225 + <children> 1.226 + <xul:image class="button-icon" xbl:inherits="src=image"/> 1.227 + <xul:label class="button-text" xbl:inherits="value=label,accesskey,crop"/> 1.228 + </children> 1.229 + </xul:hbox> 1.230 + </content> 1.231 + </binding> 1.232 + 1.233 + <binding id="menu" display="xul:menu" 1.234 + extends="chrome://global/content/bindings/button.xml#button"> 1.235 + <content> 1.236 + <children includes="observes|template|menupopup|panel|tooltip"/> 1.237 + <xul:hbox class="box-inherit button-box" xbl:inherits="align,dir,pack,orient" 1.238 + align="center" pack="center" flex="1"> 1.239 + <children> 1.240 + <xul:hbox class="box-inherit" xbl:inherits="align,dir,pack,orient" 1.241 + align="center" pack="center" flex="1"> 1.242 + <xul:image class="button-icon" xbl:inherits="src=image"/> 1.243 + <xul:label class="button-text" xbl:inherits="value=label,accesskey,crop"/> 1.244 + </xul:hbox> 1.245 + <xul:dropmarker class="button-menu-dropmarker" xbl:inherits="open,disabled,label"/> 1.246 + </children> 1.247 + </xul:hbox> 1.248 + </content> 1.249 + 1.250 + <handlers> 1.251 + <handler event="keypress" keycode="VK_RETURN" action="this.open = true;"/> 1.252 + <handler event="keypress" key=" " action="this.open = true;"/> 1.253 + </handlers> 1.254 + </binding> 1.255 + 1.256 + <binding id="menu-button-base" 1.257 + extends="chrome://global/content/bindings/button.xml#button-base"> 1.258 + <implementation implements="nsIDOMEventListener"> 1.259 + <constructor> 1.260 + this.init(); 1.261 + </constructor> 1.262 + 1.263 + <method name="init"> 1.264 + <body> 1.265 + <![CDATA[ 1.266 + var btn = document.getAnonymousElementByAttribute(this, "anonid", "button"); 1.267 + if (!btn) 1.268 + throw "XBL binding for <button type=\"menu-button\"/> binding must contain an element with anonid=\"button\""; 1.269 + 1.270 + var menubuttonParent = this; 1.271 + btn.addEventListener("mouseover", function() { 1.272 + if (!this.disabled) 1.273 + menubuttonParent.buttonover = true; 1.274 + }, true); 1.275 + btn.addEventListener("mouseout", function() { 1.276 + menubuttonParent.buttonover = false; 1.277 + }, true); 1.278 + btn.addEventListener("mousedown", function() { 1.279 + if (!this.disabled) { 1.280 + menubuttonParent.buttondown = true; 1.281 + document.addEventListener("mouseup", menubuttonParent, true); 1.282 + } 1.283 + }, true); 1.284 + ]]> 1.285 + </body> 1.286 + </method> 1.287 + 1.288 + <property name="buttonover" onget="return this.getAttribute('buttonover');"> 1.289 + <setter> 1.290 + <![CDATA[ 1.291 + var v = val || val == "true"; 1.292 + if (!v && this.buttondown) { 1.293 + this.buttondown = false; 1.294 + this._pendingActive = true; 1.295 + } 1.296 + else { 1.297 + if (this._pendingActive) { 1.298 + this.buttondown = true; 1.299 + this._pendingActive = false; 1.300 + } 1.301 + } 1.302 + 1.303 + if (v) 1.304 + this.setAttribute("buttonover", "true"); 1.305 + else 1.306 + this.removeAttribute("buttonover"); 1.307 + return val; 1.308 + ]]> 1.309 + </setter> 1.310 + </property> 1.311 + 1.312 + <property name="buttondown" onget="return this.getAttribute('buttondown') == 'true';"> 1.313 + <setter> 1.314 + <![CDATA[ 1.315 + if (val || val == "true") 1.316 + this.setAttribute("buttondown", "true"); 1.317 + else 1.318 + this.removeAttribute("buttondown"); 1.319 + return val; 1.320 + ]]> 1.321 + </setter> 1.322 + </property> 1.323 + 1.324 + <field name="_pendingActive">false</field> 1.325 + 1.326 + <method name="handleEvent"> 1.327 + <parameter name="aEvent"/> 1.328 + <body> 1.329 + <![CDATA[ 1.330 + this._pendingActive = false; 1.331 + this.buttondown = false; 1.332 + document.removeEventListener("mouseup", this, true); 1.333 + ]]> 1.334 + </body> 1.335 + </method> 1.336 + 1.337 + </implementation> 1.338 + 1.339 + <handlers> 1.340 + <handler event="keypress" keycode="VK_RETURN"> 1.341 + if (event.originalTarget == this) 1.342 + this.open = true; 1.343 + </handler> 1.344 + <handler event="keypress" key=" "> 1.345 + if (event.originalTarget == this) 1.346 + this.open = true; 1.347 + </handler> 1.348 + </handlers> 1.349 + </binding> 1.350 + 1.351 + <binding id="menu-button" display="xul:menu" 1.352 + extends="chrome://global/content/bindings/button.xml#menu-button-base"> 1.353 + <resources> 1.354 + <stylesheet src="chrome://global/skin/button.css"/> 1.355 + </resources> 1.356 + 1.357 + <content> 1.358 + <children includes="observes|template|menupopup|panel|tooltip"/> 1.359 + <xul:button class="box-inherit button-menubutton-button" 1.360 + anonid="button" flex="1" allowevents="true" 1.361 + xbl:inherits="disabled,crop,image,label,accesskey,command, 1.362 + buttonover,buttondown,align,dir,pack,orient"> 1.363 + <children/> 1.364 + </xul:button> 1.365 + <xul:dropmarker class="button-menubutton-dropmarker" xbl:inherits="open,disabled,label"/> 1.366 + </content> 1.367 + </binding> 1.368 + 1.369 + <binding id="button-image" display="xul:button" 1.370 + extends="chrome://global/content/bindings/button.xml#button"> 1.371 + <content> 1.372 + <xul:image class="button-image-icon" xbl:inherits="src=image"/> 1.373 + </content> 1.374 + </binding> 1.375 + 1.376 + <binding id="button-repeat" display="xul:autorepeatbutton" 1.377 + extends="chrome://global/content/bindings/button.xml#button"/> 1.378 + 1.379 +</bindings>