home *** CD-ROM | disk | FTP | other *** search
- <?xml version="1.0"?>
-
- <bindings id="radioBindings"
- 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="radiogroup">
- <resources>
- <stylesheet src="chrome://global/skin/radio.css"/>
- </resources>
-
- <implementation implements="nsIDOMXULSelectControlElement, nsIAccessibleProvider">
- <property name="accessible">
- <getter>
- <![CDATA[
- var accService = Components.classes["@mozilla.org/accessibilityService;1"].getService(Components.interfaces.nsIAccessibilityService);
- return accService.createXULRadioGroupAccessible(this);
- ]]>
- </getter>
- </property>
-
- <property name="value" onset="this.setAttribute('value',val); return val;"
- onget="return this.getAttribute('value');"/>
- <property name="disabled">
- <getter>
- <![CDATA[
- return this.getAttribute('disabled') == 'true';
- ]]>
- </getter>
- <setter>
- <![CDATA[
- if (val)
- this.setAttribute('disabled', 'true');
- else
- this.removeAttribute('disabled');
- var children = this._getRadioChildren();
- for (var i = 0; i < children.length; ++i) {
- children[i].disabled = val;
- }
- return val;
- ]]>
- </setter>
- </property>
-
- <property name="selectedItem">
- <getter>
- <![CDATA[
- var children = this._getRadioChildren();
- for (var i = 0; i < children.length; ++i) {
- if (children[i].selected)
- return children[i];
- }
- return null;
- ]]>
- </getter>
- <setter>
- <![CDATA[
- var alreadySelected = val.getAttribute("selected") == "true";
- var focused = false;
- if (this.getAttribute("focused") == "true") {
- val.setAttribute("focused", "true");
- focused = true;
- }
-
- val.setAttribute("selected", "true");
- this.value = val.value;
-
- // uncheck all other group nodes
- var children = this._getRadioChildren();
- for (var i = 0; i < children.length; ++i) {
- if (children[i] != val) {
- children[i].removeAttribute("selected");
- children[i].removeAttribute("focused");
- }
- }
-
- var event = document.createEvent("Events");
- event.initEvent("select", false, true);
- this.dispatchEvent(event);
-
- if (!alreadySelected && focused) {
- // Only report if actual change
- var myEvent = document.createEvent("Events");
- myEvent.initEvent("RadioStateChange", true, true);
- val.dispatchEvent(myEvent);
- }
-
- return val;
- ]]>
- </setter>
- </property>
-
- <property name="focusedItem">
- <getter>
- <![CDATA[
- var children = this._getRadioChildren();
- for (var i = 0; i < children.length; ++i) {
- if (children[i].getAttribute("focused") == "true")
- return children[i];
- }
- return null;
- ]]>
- </getter>
- <setter>
- <![CDATA[
- if (val) val.setAttribute("focused", "true");
-
- // unfocus all other group nodes
- var children = this._getRadioChildren();
- for (var i = 0; i < children.length; ++i) {
- if (children[i] != val)
- children[i].removeAttribute("focused");
- }
- return val;
- ]]>
- </setter>
- </property>
-
- <method name="checkAdjacentElement">
- <parameter name="aNextFlag"/>
- <body>
- <![CDATA[
- var currentElement = this.focusedItem;
- // If focused item isn't a radio button, do nothing!
- // (This allows textbox to work inside a radiogroup)
- if (!currentElement)
- return;
- var index, i;
- var children = this._getRadioChildren();
- for (i = 0; i < children.length; ++i ) {
- if (children[i] == currentElement)
- break;
- }
-
- if (aNextFlag) {
- do {
- index = ++i % children.length;
- if (i > children.length)
- break;
- }
- while (children[index].getAttribute("hidden") == "true" || children[index].disabled);
- // XXX check for collapsed attr and display/visibility props too
-
- this.selectedItem = children[index];
- children[index].doCommand();
- }
- else {
- do {
- index = i > 0 ? --i : (i = children.length - 1);
- if (i == children.length)
- break;
- }
- while (children[index].getAttribute("hidden") == "true" || children[index].disabled);
- // XXX check for collapsed attr and display/visibility props too
-
- this.selectedItem = children[index];
- children[index].doCommand();
- }
- ]]>
- </body>
- </method>
- <field name="mRadioChildren">[]</field>
- <method name="_getRadioChildren">
- <parameter name="aNode">this</parameter>
- <body>
- <![CDATA[
- if (aNode) {
- if (aNode == this && this.mRadioChildren)
- return this.mRadioChildren;
- else if (aNode.localName == "radio") {
- this.mRadioChildren[this.mRadioChildren.length++] = aNode;
- return this.mRadioChildren;
- }
- else if (aNode.localName == "radiogroup" && aNode != this)
- return this.mRadioChildren;
- for (var i = 0; i < aNode.childNodes.length; ++i)
- this._getRadioChildren(aNode.childNodes[i]);
- }
- return this.mRadioChildren;
- ]]>
- </body>
- </method>
-
- <method name="appendItem">
- <parameter name="label"/>
- <parameter name="value"/>
- <body>
- <![CDATA[
- var XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
- var radio = document.createElementNS(XULNS, "radio");
- radio.setAttribute("label", label);
- radio.setAttribute("value", value);
- this.appendChild(radio);
- return radio;
- ]]>
- </body>
- </method>
-
- <method name="insertItemAt">
- <parameter name="index"/>
- <parameter name="label"/>
- <parameter name="value"/>
- <body>
- <![CDATA[
- var XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
- var radio = document.createElementNS(XULNS, "radio");
- radio.setAttribute("label", label);
- radio.setAttribute("value", value);
- var before = this.childNodes[index];
- if (before)
- this.insertBefore(radio, before);
- else
- this.appendChild(radio);
- return radio;
- ]]>
- </body>
- </method>
-
- <method name="removeItemAt">
- <parameter name="index"/>
- <body>
- <![CDATA[
- var remove = this.childNodes[index];
- if (remove)
- this.removeChild(remove);
- return remove;
- ]]>
- </body>
- </method>
- </implementation>
-
- <handlers>
- <handler event="click" button="0">
- <![CDATA[
- if (event.target.localName == "radio" && !event.target.disabled)
- this.selectedItem = event.target;
- event.preventBubble();
- ]]>
- </handler>
- <handler event="select">
- <![CDATA[
- //XXXblake this should not be necessary
- // initEvent was supposed to prevent this from bubbling
- event.preventBubble();
- ]]>
- </handler>
- <handler event="mousedown" button="0">
- <![CDATA[
- if (event.target.localName == "radio" && !event.target.disabled)
- this.focusedItem = event.target;
- event.preventBubble();
- ]]>
- </handler>
-
- <!-- keyboard navigation -->
- <!-- Here's how keyboard navigation works in radio groups on Windows:
- The group takes 'focus'
- The user is then free to navigate around inside the group
- using the arrow keys. Accessing previous or following radio buttons
- is done solely through the arrow keys and not the tab button. Tab
- takes you to the next widget in the tab order -->
- <handler event="keypress" key=" ">
- this.selectedItem = this.focusedItem;
- this.selectedItem.doCommand();
- </handler>
- <handler event="keypress" keycode="VK_UP" phase="target">
- this.checkAdjacentElement(false);
- event.preventBubble();
- </handler>
- <handler event="keypress" keycode="VK_LEFT" phase="target">
- this.checkAdjacentElement(false);
- event.preventBubble();
- </handler>
- <handler event="keypress" keycode="VK_DOWN" phase="target">
- this.checkAdjacentElement(true);
- event.preventBubble();
- </handler>
- <handler event="keypress" keycode="VK_RIGHT" phase="target">
- this.checkAdjacentElement(true);
- event.preventBubble();
- </handler>
-
- <!-- set a focused attribute on the selected item when the group
- receives focus so that we can style it as if it were focused even though
- it is not (Windows platform behaviour is for the group to receive focus,
- not the item -->
- <handler event="focus" phase="target">
- if (event.target == this) {
- this.setAttribute("focused", "true");
- if (!this.focusedItem)
- this.focusedItem = this.selectedItem;
- }
- </handler>
- <handler event="blur" phase="target">
- this.removeAttribute("focused");
- this.focusedItem = null;
- </handler>
- </handlers>
- </binding>
-
- <binding id="radio" extends="chrome://global/content/bindings/general.xml#control-item">
- <resources>
- <stylesheet src="chrome://global/skin/radio.css"/>
- </resources>
-
- <content>
- <xul:image class="radio-check" xbl:inherits="disabled,selected"/>
- <xul:hbox class="radio-label-box" flex="1">
- <xul:image class="radio-icon" xbl:inherits="src"/>
- <xul:label class="radio-label" xbl:inherits="xbl:text=label,accesskey,crop" flex="1"/>
- </xul:hbox>
- </content>
-
- <implementation implements="nsIDOMXULSelectControlItemElement, nsIAccessibleProvider">
- <constructor>
- <![CDATA[
- var parent = this.radioGroup;
- parent.mRadioChildren[parent.mRadioChildren.length++] = this;
- ]]>
- </constructor>
- <destructor>
- <![CDATA[
- var parent = this.radioGroup;
- for (var i = 0; i < parent.mRadioChildren.length; ++i) {
- if (parent.mRadioChildren[i] == this) {
- parent.mRadioChildren.slice(i, i);
- return;
- }
- }
- ]]>
- </destructor>
- <property name="accessible">
- <getter>
- <![CDATA[
- var accService = Components.classes["@mozilla.org/accessibilityService;1"].getService(Components.interfaces.nsIAccessibilityService);
- return accService.createXULRadioButtonAccessible(this);
- ]]>
- </getter>
- </property>
- <property name="selected" readonly="true">
- <getter>
- <![CDATA[
- return this.hasAttribute('selected');
- ]]>
- </getter>
- </property>
- <property name="radioGroup">
- <getter>
- <![CDATA[
- var parent = this.parentNode;
- while (parent) {
- if (parent.localName == "radiogroup")
- return parent;
- parent = parent.parentNode;
- }
- return null;
- ]]>
- </getter>
- </property>
- </implementation>
- <handlers>
- <handler event="click" button="0">
- <![CDATA[
- if (!this.disabled)
- this.radioGroup.selectedItem = this;
- ]]>
- </handler>
-
- <handler event="mousedown" button="0">
- <![CDATA[
- if (!this.disabled)
- this.radioGroup.focusedItem = this;
- ]]>
- </handler>
- </handlers>
- </binding>
- </bindings>