3
<bindings id="radioBindings"
4
xmlns="http://www.mozilla.org/xbl"
5
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
6
xmlns:xbl="http://www.mozilla.org/xbl">
8
<binding id="radiogroup">
10
<stylesheet src="chrome://global/skin/radio.css"/>
13
<implementation implements="nsIDOMXULSelectControlElement, nsIAccessibleProvider">
14
<property name="accessible">
17
var accService = Components.classes["@mozilla.org/accessibilityService;1"].getService(Components.interfaces.nsIAccessibilityService);
18
return accService.createXULRadioGroupAccessible(this);
23
<property name="value" onset="this.setAttribute('value',val); return val;"
24
onget="return this.getAttribute('value');"/>
25
<property name="disabled">
28
if (this.getAttribute('disabled') == 'true')
30
var children = this._getRadioChildren();
31
for (var i = 0; i < children.length; ++i) {
32
if (!children[i].hidden && !children[i].collapsed && !children[i].disabled)
41
this.setAttribute('disabled', 'true');
43
this.removeAttribute('disabled');
44
var children = this._getRadioChildren();
45
for (var i = 0; i < children.length; ++i) {
46
children[i].disabled = val;
53
<property name="selectedIndex">
56
var children = this._getRadioChildren();
57
for (var i = 0; i < children.length; ++i) {
58
if (children[i].selected)
66
this.selectedItem = this._getRadioChildren()[val];
72
<property name="selectedItem">
75
var children = this._getRadioChildren();
76
for (var i = 0; i < children.length; ++i) {
77
if (children[i].selected)
85
var focused = this.getAttribute("focused") == "true";
86
var alreadySelected = false;
89
alreadySelected = val.getAttribute("selected") == "true";
90
val.setAttribute("focused", focused);
91
val.setAttribute("selected", "true");
92
this.value = val.value;
95
// uncheck all other group nodes
96
var children = this._getRadioChildren();
97
for (var i = 0; i < children.length; ++i) {
98
if (children[i] != val) {
99
children[i].removeAttribute("selected");
100
children[i].removeAttribute("focused");
104
var event = document.createEvent("Events");
105
event.initEvent("select", false, true);
106
this.dispatchEvent(event);
108
if (!alreadySelected && focused) {
109
// Only report if actual change
110
var myEvent = document.createEvent("Events");
111
myEvent.initEvent("RadioStateChange", true, true);
112
val.dispatchEvent(myEvent);
120
<property name="focusedItem">
123
var children = this._getRadioChildren();
124
for (var i = 0; i < children.length; ++i) {
125
if (children[i].getAttribute("focused") == "true")
133
if (val) val.setAttribute("focused", "true");
135
// unfocus all other group nodes
136
var children = this._getRadioChildren();
137
for (var i = 0; i < children.length; ++i) {
138
if (children[i] != val)
139
children[i].removeAttribute("focused");
146
<method name="checkAdjacentElement">
147
<parameter name="aNextFlag"/>
150
var currentElement = this.focusedItem;
152
var children = this._getRadioChildren();
153
for (i = 0; i < children.length; ++i ) {
154
if (children[i] == currentElement)
161
if (++i == children.length)
166
while (children[i].hidden || children[i].collapsed || children[i].disabled);
167
// XXX check for display/visibility props too
169
this.selectedItem = children[i];
170
children[i].doCommand();
179
while (children[i].hidden || children[i].collapsed || children[i].disabled);
180
// XXX check for display/visibility props too
182
this.selectedItem = children[i];
183
children[i].doCommand();
188
<field name="mRadioChildren">null</field>
189
<method name="_getRadioChildren">
192
if (this.mRadioChildren)
193
return this.mRadioChildren;
195
// Don't store the collected child nodes immediately,
196
// collecting the child nodes could trigger constructors
197
// which would blow away our list.
198
var radioChildren = [];
199
function _filterRadioGroup(aNode) {
200
switch (aNode.localName) {
201
case "radio": return NodeFilter.FILTER_ACCEPT;
203
case "radiogroup": return NodeFilter.FILTER_REJECT;
204
default: return NodeFilter.FILTER_SKIP;
207
var iterator = this.ownerDocument.createTreeWalker(this, NodeFilter.SHOW_ELEMENT, _filterRadioGroup, true);
208
while (iterator.nextNode())
209
radioChildren.push(iterator.currentNode);
210
return this.mRadioChildren = radioChildren;
215
<method name="appendItem">
216
<parameter name="label"/>
217
<parameter name="value"/>
220
var XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
221
var radio = document.createElementNS(XULNS, "radio");
222
radio.setAttribute("label", label);
223
radio.setAttribute("value", value);
224
this.appendChild(radio);
230
<method name="insertItemAt">
231
<parameter name="index"/>
232
<parameter name="label"/>
233
<parameter name="value"/>
236
var XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
237
var radio = document.createElementNS(XULNS, "radio");
238
radio.setAttribute("label", label);
239
radio.setAttribute("value", value);
240
var before = this.childNodes[index];
242
this.insertBefore(radio, before);
244
this.appendChild(radio);
250
<method name="removeItemAt">
251
<parameter name="index"/>
254
var remove = this.childNodes[index];
256
this.removeChild(remove);
264
<handler event="select">
266
//XXXblake this should not be necessary
267
// initEvent was supposed to prevent this from bubbling
268
event.preventBubble();
271
<handler event="mousedown">
273
event.preventDefault();
276
<!-- keyboard navigation -->
277
<!-- Here's how keyboard navigation works in radio groups on Windows:
278
The group takes 'focus'
279
The user is then free to navigate around inside the group
280
using the arrow keys. Accessing previous or following radio buttons
281
is done solely through the arrow keys and not the tab button. Tab
282
takes you to the next widget in the tab order -->
283
<handler event="keypress" key=" " phase="target">
284
this.selectedItem = this.focusedItem;
285
this.selectedItem.doCommand();
287
<handler event="keypress" keycode="VK_UP" phase="target">
288
this.checkAdjacentElement(false);
289
event.preventBubble();
291
<handler event="keypress" keycode="VK_LEFT" phase="target">
292
this.checkAdjacentElement(false);
293
event.preventBubble();
295
<handler event="keypress" keycode="VK_DOWN" phase="target">
296
this.checkAdjacentElement(true);
297
event.preventBubble();
299
<handler event="keypress" keycode="VK_RIGHT" phase="target">
300
this.checkAdjacentElement(true);
301
event.preventBubble();
304
<!-- set a focused attribute on the selected item when the group
305
receives focus so that we can style it as if it were focused even though
306
it is not (Windows platform behaviour is for the group to receive focus,
308
<handler event="focus" phase="target">
310
this.setAttribute("focused", "true");
311
if (this.focusedItem)
314
var val = this.selectedItem;
315
if (!val || val.disabled || val.hidden || val.collapsed) {
316
var children = this._getRadioChildren();
317
for (var i = 0; i < children.length; ++i) {
318
if (!children[i].hidden && !children[i].collapsed && !children[i].disabled) {
324
this.focusedItem = val;
327
<handler event="blur" phase="target">
328
this.removeAttribute("focused");
329
this.focusedItem = null;
334
<binding id="radio" extends="chrome://global/content/bindings/general.xml#control-item">
336
<stylesheet src="chrome://global/skin/radio.css"/>
340
<xul:image class="radio-check" xbl:inherits="disabled,selected"/>
341
<xul:hbox class="radio-label-box" flex="1">
342
<xul:image class="radio-icon" xbl:inherits="src"/>
343
<xul:label class="radio-label" xbl:inherits="xbl:text=label,accesskey,crop" flex="1"/>
347
<implementation implements="nsIDOMXULSelectControlItemElement, nsIAccessibleProvider">
350
// Just clear out the parent's cached list of radio children
351
this.radioGroup.mRadioChildren = null;
356
var radioList = this.radioGroup.mRadioChildren;
359
for (var i = 0; i < radioList.length; ++i) {
360
if (radioList[i] == this) {
361
radioList.splice(i, 1);
367
<property name="accessible">
370
var accService = Components.classes["@mozilla.org/accessibilityService;1"].getService(Components.interfaces.nsIAccessibilityService);
371
return accService.createXULRadioButtonAccessible(this);
375
<property name="selected" readonly="true">
378
return this.hasAttribute('selected');
382
<property name="radioGroup">
385
var parent = this.parentNode;
387
if (parent.localName == "radiogroup")
389
parent = parent.parentNode;
397
<handler event="click" button="0">
400
this.radioGroup.selectedItem = this;
404
<handler event="mousedown" button="0">
407
this.radioGroup.focusedItem = this;