toolkit/content/widgets/button.xml

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:2feba91414b5
1 <?xml version="1.0"?>
2 <!-- This Source Code Form is subject to the terms of the Mozilla Public
3 - License, v. 2.0. If a copy of the MPL was not distributed with this
4 - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
5
6
7 <bindings id="buttonBindings"
8 xmlns="http://www.mozilla.org/xbl"
9 xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
10 xmlns:xbl="http://www.mozilla.org/xbl">
11
12 <binding id="button-base" extends="chrome://global/content/bindings/general.xml#basetext" role="xul:button">
13 <implementation implements="nsIDOMXULButtonElement">
14 <property name="type"
15 onget="return this.getAttribute('type');"
16 onset="this.setAttribute('type', val); return val;"/>
17
18 <property name="dlgType"
19 onget="return this.getAttribute('dlgtype');"
20 onset="this.setAttribute('dlgtype', val); return val;"/>
21
22 <property name="group"
23 onget="return this.getAttribute('group');"
24 onset="this.setAttribute('group', val); return val;"/>
25
26 <property name="open" onget="return this.hasAttribute('open');">
27 <setter><![CDATA[
28 if (this.boxObject instanceof
29 Components.interfaces.nsIMenuBoxObject) {
30 this.boxObject.openMenu(val);
31 } else {
32 // Fall back to just setting the attribute
33 if (val) {
34 this.setAttribute('open', 'true');
35 } else {
36 this.removeAttribute('open');
37 }
38 }
39 return val;
40 ]]></setter>
41 </property>
42
43 <property name="checked" onget="return this.hasAttribute('checked');">
44 <setter><![CDATA[
45 if (this.type == "checkbox") {
46 this.checkState = val ? 1 : 0;
47 } else if (this.type == "radio" && val) {
48 var sibs = this.parentNode.getElementsByAttribute("group", this.group);
49 for (var i = 0; i < sibs.length; ++i)
50 sibs[i].removeAttribute("checked");
51 }
52
53 if (val)
54 this.setAttribute("checked", "true");
55 else
56 this.removeAttribute("checked");
57
58 return val;
59 ]]></setter>
60 </property>
61
62 <property name="checkState">
63 <getter><![CDATA[
64 var state = this.getAttribute("checkState");
65 if (state == "")
66 return this.checked ? 1 : 0;
67 else
68 return state == "0" ? 0 : (state == "2" ? 2 : 1);
69 ]]></getter>
70 <setter><![CDATA[
71 this.setAttribute("checkState", val);
72 return val;
73 ]]></setter>
74 </property>
75
76 <property name="autoCheck"
77 onget="return this.getAttribute('autoCheck') == 'true';"
78 onset="this.setAttribute('autoCheck', val); return val;"/>
79
80 <method name ="filterButtons">
81 <parameter name="node"/>
82 <body>
83 <![CDATA[
84 // if the node isn't visible, don't descend into it.
85 var cs = node.ownerDocument.defaultView.getComputedStyle(node, null);
86 if (cs.visibility != "visible" || cs.display == "none") {
87 return NodeFilter.FILTER_REJECT;
88 }
89 // but it may be a popup element, in which case we look at "state"...
90 if (cs.display == "-moz-popup" && node.state != "open") {
91 return NodeFilter.FILTER_REJECT;
92 }
93 // OK - the node seems visible, so it is a candidate.
94 if (node.localName == "button" && node.accessKey && !node.disabled)
95 return NodeFilter.FILTER_ACCEPT;
96 return NodeFilter.FILTER_SKIP;
97 ]]>
98 </body>
99 </method>
100
101 <method name="fireAccessKeyButton">
102 <parameter name="aSubtree"/>
103 <parameter name="aAccessKeyLower"/>
104 <body>
105 <![CDATA[
106 var iterator = aSubtree.ownerDocument.createTreeWalker(aSubtree,
107 NodeFilter.SHOW_ELEMENT,
108 this.filterButtons);
109 while (iterator.nextNode()) {
110 var test = iterator.currentNode;
111 if (test.accessKey.toLowerCase() == aAccessKeyLower &&
112 !test.disabled && !test.collapsed && !test.hidden) {
113 test.focus();
114 test.click();
115 return true;
116 }
117 }
118 return false;
119 ]]>
120 </body>
121 </method>
122
123 <method name="_handleClick">
124 <body>
125 <![CDATA[
126 if (!this.disabled &&
127 (this.autoCheck || !this.hasAttribute("autoCheck"))) {
128
129 if (this.type == "checkbox") {
130 this.checked = !this.checked;
131 } else if (this.type == "radio") {
132 this.checked = true;
133 }
134 }
135 ]]>
136 </body>
137 </method>
138 </implementation>
139
140 <handlers>
141 <!-- While it would seem we could do this by handling oncommand, we can't
142 because any external oncommand handlers might get called before ours,
143 and then they would see the incorrect value of checked. Additionally
144 a command attribute would redirect the command events anyway.-->
145 <handler event="click" button="0" action="this._handleClick();"/>
146 <handler event="keypress" key=" " action="this._handleClick();"/>
147
148 <handler event="keypress">
149 <![CDATA[
150 if (this.boxObject instanceof Components.interfaces.nsIMenuBoxObject) {
151 if (this.open)
152 return;
153 } else {
154 if (event.keyCode == KeyEvent.DOM_VK_UP ||
155 (event.keyCode == KeyEvent.DOM_VK_LEFT &&
156 document.defaultView.getComputedStyle(this.parentNode, "")
157 .direction == "ltr") ||
158 (event.keyCode == KeyEvent.DOM_VK_RIGHT &&
159 document.defaultView.getComputedStyle(this.parentNode, "")
160 .direction == "rtl")) {
161 event.preventDefault();
162 window.document.commandDispatcher.rewindFocus();
163 return;
164 }
165
166 if (event.keyCode == KeyEvent.DOM_VK_DOWN ||
167 (event.keyCode == KeyEvent.DOM_VK_RIGHT &&
168 document.defaultView.getComputedStyle(this.parentNode, "")
169 .direction == "ltr") ||
170 (event.keyCode == KeyEvent.DOM_VK_LEFT &&
171 document.defaultView.getComputedStyle(this.parentNode, "")
172 .direction == "rtl")) {
173 event.preventDefault();
174 window.document.commandDispatcher.advanceFocus();
175 return;
176 }
177 }
178
179 if (event.keyCode || event.charCode <= 32 || event.altKey ||
180 event.ctrlKey || event.metaKey)
181 return; // No printable char pressed, not a potential accesskey
182
183 // Possible accesskey pressed
184 var charPressedLower = String.fromCharCode(event.charCode).toLowerCase();
185
186 // If the accesskey of the current button is pressed, just activate it
187 if (this.accessKey.toLowerCase() == charPressedLower) {
188 this.click();
189 return;
190 }
191
192 // Search for accesskey in the list of buttons for this doc and each subdoc
193 // Get the buttons for the main document and all sub-frames
194 for (var frameCount = -1; frameCount < window.top.frames.length; frameCount++) {
195 var doc = (frameCount == -1)? window.top.document:
196 window.top.frames[frameCount].document
197 if (this.fireAccessKeyButton(doc.documentElement, charPressedLower))
198 return;
199 }
200
201 // Test anonymous buttons
202 var dlg = window.top.document;
203 var buttonBox = dlg.getAnonymousElementByAttribute(dlg.documentElement,
204 "anonid", "buttons");
205 if (buttonBox)
206 this.fireAccessKeyButton(buttonBox, charPressedLower);
207 ]]>
208 </handler>
209 </handlers>
210 </binding>
211
212 <binding id="button" display="xul:button"
213 extends="chrome://global/content/bindings/button.xml#button-base">
214 <resources>
215 <stylesheet src="chrome://global/skin/button.css"/>
216 </resources>
217
218 <content>
219 <children includes="observes|template|menupopup|panel|tooltip"/>
220 <xul:hbox class="box-inherit button-box" xbl:inherits="align,dir,pack,orient"
221 align="center" pack="center" flex="1" anonid="button-box">
222 <children>
223 <xul:image class="button-icon" xbl:inherits="src=image"/>
224 <xul:label class="button-text" xbl:inherits="value=label,accesskey,crop"/>
225 </children>
226 </xul:hbox>
227 </content>
228 </binding>
229
230 <binding id="menu" display="xul:menu"
231 extends="chrome://global/content/bindings/button.xml#button">
232 <content>
233 <children includes="observes|template|menupopup|panel|tooltip"/>
234 <xul:hbox class="box-inherit button-box" xbl:inherits="align,dir,pack,orient"
235 align="center" pack="center" flex="1">
236 <children>
237 <xul:hbox class="box-inherit" xbl:inherits="align,dir,pack,orient"
238 align="center" pack="center" flex="1">
239 <xul:image class="button-icon" xbl:inherits="src=image"/>
240 <xul:label class="button-text" xbl:inherits="value=label,accesskey,crop"/>
241 </xul:hbox>
242 <xul:dropmarker class="button-menu-dropmarker" xbl:inherits="open,disabled,label"/>
243 </children>
244 </xul:hbox>
245 </content>
246
247 <handlers>
248 <handler event="keypress" keycode="VK_RETURN" action="this.open = true;"/>
249 <handler event="keypress" key=" " action="this.open = true;"/>
250 </handlers>
251 </binding>
252
253 <binding id="menu-button-base"
254 extends="chrome://global/content/bindings/button.xml#button-base">
255 <implementation implements="nsIDOMEventListener">
256 <constructor>
257 this.init();
258 </constructor>
259
260 <method name="init">
261 <body>
262 <![CDATA[
263 var btn = document.getAnonymousElementByAttribute(this, "anonid", "button");
264 if (!btn)
265 throw "XBL binding for <button type=\"menu-button\"/> binding must contain an element with anonid=\"button\"";
266
267 var menubuttonParent = this;
268 btn.addEventListener("mouseover", function() {
269 if (!this.disabled)
270 menubuttonParent.buttonover = true;
271 }, true);
272 btn.addEventListener("mouseout", function() {
273 menubuttonParent.buttonover = false;
274 }, true);
275 btn.addEventListener("mousedown", function() {
276 if (!this.disabled) {
277 menubuttonParent.buttondown = true;
278 document.addEventListener("mouseup", menubuttonParent, true);
279 }
280 }, true);
281 ]]>
282 </body>
283 </method>
284
285 <property name="buttonover" onget="return this.getAttribute('buttonover');">
286 <setter>
287 <![CDATA[
288 var v = val || val == "true";
289 if (!v && this.buttondown) {
290 this.buttondown = false;
291 this._pendingActive = true;
292 }
293 else {
294 if (this._pendingActive) {
295 this.buttondown = true;
296 this._pendingActive = false;
297 }
298 }
299
300 if (v)
301 this.setAttribute("buttonover", "true");
302 else
303 this.removeAttribute("buttonover");
304 return val;
305 ]]>
306 </setter>
307 </property>
308
309 <property name="buttondown" onget="return this.getAttribute('buttondown') == 'true';">
310 <setter>
311 <![CDATA[
312 if (val || val == "true")
313 this.setAttribute("buttondown", "true");
314 else
315 this.removeAttribute("buttondown");
316 return val;
317 ]]>
318 </setter>
319 </property>
320
321 <field name="_pendingActive">false</field>
322
323 <method name="handleEvent">
324 <parameter name="aEvent"/>
325 <body>
326 <![CDATA[
327 this._pendingActive = false;
328 this.buttondown = false;
329 document.removeEventListener("mouseup", this, true);
330 ]]>
331 </body>
332 </method>
333
334 </implementation>
335
336 <handlers>
337 <handler event="keypress" keycode="VK_RETURN">
338 if (event.originalTarget == this)
339 this.open = true;
340 </handler>
341 <handler event="keypress" key=" ">
342 if (event.originalTarget == this)
343 this.open = true;
344 </handler>
345 </handlers>
346 </binding>
347
348 <binding id="menu-button" display="xul:menu"
349 extends="chrome://global/content/bindings/button.xml#menu-button-base">
350 <resources>
351 <stylesheet src="chrome://global/skin/button.css"/>
352 </resources>
353
354 <content>
355 <children includes="observes|template|menupopup|panel|tooltip"/>
356 <xul:button class="box-inherit button-menubutton-button"
357 anonid="button" flex="1" allowevents="true"
358 xbl:inherits="disabled,crop,image,label,accesskey,command,
359 buttonover,buttondown,align,dir,pack,orient">
360 <children/>
361 </xul:button>
362 <xul:dropmarker class="button-menubutton-dropmarker" xbl:inherits="open,disabled,label"/>
363 </content>
364 </binding>
365
366 <binding id="button-image" display="xul:button"
367 extends="chrome://global/content/bindings/button.xml#button">
368 <content>
369 <xul:image class="button-image-icon" xbl:inherits="src=image"/>
370 </content>
371 </binding>
372
373 <binding id="button-repeat" display="xul:autorepeatbutton"
374 extends="chrome://global/content/bindings/button.xml#button"/>
375
376 </bindings>

mercurial