home *** CD-ROM | disk | FTP | other *** search
/ PC World 2003 May / PCWorld_2003-05_cd.bin / Komunik / phoenix / chrome / toolkit.jar / content / global / widgets / radio.xml < prev    next >
Extensible Markup Language  |  2002-11-10  |  12KB  |  361 lines

  1. <?xml version="1.0"?>
  2.  
  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">
  7.  
  8.   <binding id="radiogroup">
  9.     <resources>
  10.       <stylesheet src="chrome://global/skin/radio.css"/>
  11.     </resources>
  12.  
  13.     <implementation implements="nsIDOMXULSelectControlElement, nsIAccessibleProvider">
  14.       <property name="accessible">
  15.         <getter>
  16.           <![CDATA[
  17.             var accService = Components.classes["@mozilla.org/accessibilityService;1"].getService(Components.interfaces.nsIAccessibilityService);
  18.             return accService.createXULRadioGroupAccessible(this);
  19.           ]]>
  20.         </getter>
  21.       </property>
  22.  
  23.       <property name="value" onset="this.setAttribute('value',val); return val;"
  24.                              onget="return this.getAttribute('value');"/>
  25.       <property name="disabled">
  26.         <getter>
  27.         <![CDATA[
  28.             return this.getAttribute('disabled') == 'true';
  29.         ]]>
  30.         </getter>
  31.         <setter>
  32.         <![CDATA[
  33.           if (val)
  34.             this.setAttribute('disabled', 'true');
  35.           else
  36.             this.removeAttribute('disabled');
  37.           var children = this._getRadioChildren();
  38.           for (var i = 0; i < children.length; ++i) {
  39.             children[i].disabled = val;
  40.           }
  41.           return val;
  42.         ]]>
  43.         </setter>
  44.       </property>
  45.       
  46.       <property name="selectedItem">
  47.         <getter>
  48.         <![CDATA[
  49.           var children = this._getRadioChildren();
  50.           for (var i = 0; i < children.length; ++i) {
  51.             if (children[i].selected)
  52.               return children[i];
  53.           }
  54.           return null;
  55.         ]]>
  56.         </getter>
  57.         <setter>
  58.         <![CDATA[
  59.           var alreadySelected = val.getAttribute("selected") == "true";
  60.           var focused = false;
  61.           if (this.getAttribute("focused") == "true") {
  62.             val.setAttribute("focused", "true");
  63.             focused = true;
  64.           }
  65.  
  66.           val.setAttribute("selected", "true");
  67.           this.value = val.value;
  68.           
  69.           // uncheck all other group nodes
  70.           var children = this._getRadioChildren();
  71.           for (var i = 0; i < children.length; ++i) {
  72.             if (children[i] != val) {
  73.               children[i].removeAttribute("selected");
  74.               children[i].removeAttribute("focused");
  75.             }
  76.           }
  77.           var event = document.createEvent("Events");          
  78.           event.initEvent("select", false, true);
  79.           this.dispatchEvent(event);
  80.  
  81.           if (!alreadySelected && focused) {
  82.             // Only report if actual change
  83.             var myEvent = document.createEvent("Events");
  84.             myEvent.initEvent("RadioStateChange", true, true);
  85.             val.dispatchEvent(myEvent);
  86.           }
  87.  
  88.           return val;
  89.         ]]>
  90.         </setter>        
  91.       </property>
  92.       
  93.       <property name="focusedItem">
  94.         <getter>
  95.         <![CDATA[
  96.           var children = this._getRadioChildren();
  97.           for (var i = 0; i < children.length; ++i) {
  98.             if (children[i].getAttribute("focused") == "true")
  99.               return children[i];
  100.           }
  101.           return null;
  102.         ]]>
  103.         </getter>
  104.         <setter>
  105.         <![CDATA[
  106.           if (val) val.setAttribute("focused", "true");
  107.           
  108.           // unfocus all other group nodes
  109.           var children = this._getRadioChildren();
  110.           for (var i = 0; i < children.length; ++i) {
  111.             if (children[i] != val)
  112.               children[i].removeAttribute("focused");
  113.           }
  114.           return val;
  115.         ]]>
  116.         </setter>
  117.       </property>
  118.       
  119.       <method name="checkAdjacentElement">
  120.         <parameter name="aNextFlag"/>
  121.         <body>
  122.         <![CDATA[
  123.           var currentElement = this.focusedItem;
  124.           // If focused item isn't a radio button, do nothing!
  125.           // (This allows textbox to work inside a radiogroup)
  126.           if (!currentElement)
  127.             return;
  128.           var index, i;
  129.           var children = this._getRadioChildren();
  130.           for (i = 0; i < children.length; ++i ) {
  131.             if (children[i] == currentElement) 
  132.               break;
  133.           }
  134.           
  135.           if (aNextFlag) {
  136.             do {
  137.               index = ++i % children.length;             
  138.               if (i > children.length)
  139.                 break;
  140.             }
  141.             while (children[index].getAttribute("hidden") == "true" || children[index].disabled);
  142.             // XXX check for collapsed attr and display/visibility props too
  143.  
  144.             this.selectedItem = children[index];
  145.             children[index].doCommand();
  146.           }
  147.           else {              
  148.             do {
  149.               index = i > 0 ? --i : (i = children.length - 1);
  150.               if (i == children.length)
  151.                 break;
  152.             }
  153.             while (children[index].getAttribute("hidden") == "true" || children[index].disabled);
  154.             // XXX check for collapsed attr and display/visibility props too
  155.  
  156.             this.selectedItem = children[index];
  157.             children[index].doCommand();
  158.           }
  159.         ]]>
  160.         </body>
  161.       </method>
  162.       <field name="mRadioChildren">[]</field>
  163.       <method name="_getRadioChildren">
  164.         <parameter name="aNode">this</parameter>
  165.         <body>
  166.         <![CDATA[
  167.           if (aNode) {
  168.             if (aNode == this && this.mRadioChildren)
  169.               return this.mRadioChildren;
  170.             else if (aNode.localName == "radio") {
  171.               this.mRadioChildren[this.mRadioChildren.length++] = aNode;
  172.               return this.mRadioChildren;
  173.             }
  174.             else if (aNode.localName == "radiogroup" && aNode != this)
  175.               return this.mRadioChildren;
  176.             for (var i = 0; i < aNode.childNodes.length; ++i)
  177.               this._getRadioChildren(aNode.childNodes[i]);
  178.           }
  179.           return this.mRadioChildren;
  180.         ]]>
  181.         </body>
  182.       </method>
  183.  
  184.       <method name="appendItem">
  185.         <parameter name="label"/>
  186.         <parameter name="value"/>
  187.         <body>
  188.         <![CDATA[
  189.           var XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
  190.           var radio = document.createElementNS(XULNS, "radio");
  191.           radio.setAttribute("label", label);
  192.           radio.setAttribute("value", value);
  193.           this.appendChild(radio);
  194.           return radio;
  195.         ]]>
  196.         </body>
  197.       </method>
  198.       
  199.       <method name="insertItemAt">
  200.         <parameter name="index"/>
  201.         <parameter name="label"/>
  202.         <parameter name="value"/>
  203.         <body>
  204.         <![CDATA[
  205.           var XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
  206.           var radio = document.createElementNS(XULNS, "radio");
  207.           radio.setAttribute("label", label);
  208.           radio.setAttribute("value", value);
  209.           var before = this.childNodes[index];
  210.           if (before)
  211.             this.insertBefore(radio, before);
  212.           else
  213.             this.appendChild(radio);
  214.           return radio;
  215.         ]]>
  216.         </body>
  217.       </method>
  218.  
  219.       <method name="removeItemAt">
  220.         <parameter name="index"/>
  221.         <body>
  222.         <![CDATA[
  223.           var remove = this.childNodes[index];
  224.           if (remove)
  225.             this.removeChild(remove);
  226.           return remove;
  227.         ]]>
  228.         </body>
  229.       </method>
  230.     </implementation>
  231.     
  232.     <handlers>
  233.       <handler event="click" button="0">
  234.         <![CDATA[
  235.           if (event.target.localName == "radio" && !event.target.disabled) 
  236.             this.selectedItem = event.target;
  237.           event.preventBubble();
  238.          ]]>
  239.       </handler>
  240.       <handler event="select">
  241.         <![CDATA[
  242.           //XXXblake this should not be necessary
  243.           //         initEvent was supposed to prevent this from bubbling
  244.           event.preventBubble();
  245.         ]]>
  246.       </handler>
  247.       <handler event="mousedown" button="0">
  248.         <![CDATA[
  249.           if (event.target.localName == "radio" && !event.target.disabled)
  250.             this.focusedItem = event.target;
  251.           event.preventBubble();
  252.          ]]>
  253.       </handler>
  254.      
  255.       <!-- keyboard navigation -->
  256.       <!-- Here's how keyboard navigation works in radio groups on Windows:
  257.            The group takes 'focus'
  258.            The user is then free to navigate around inside the group
  259.            using the arrow keys. Accessing previous or following radio buttons
  260.            is done solely through the arrow keys and not the tab button. Tab
  261.            takes you to the next widget in the tab order -->
  262.       <handler event="keypress" key=" ">
  263.          this.selectedItem = this.focusedItem;
  264.          this.selectedItem.doCommand();
  265.       </handler>
  266.       <handler event="keypress" keycode="VK_UP" phase="target">
  267.         this.checkAdjacentElement(false);
  268.         event.preventBubble();
  269.       </handler>
  270.       <handler event="keypress" keycode="VK_LEFT" phase="target">
  271.         this.checkAdjacentElement(false);
  272.         event.preventBubble();
  273.       </handler>
  274.       <handler event="keypress" keycode="VK_DOWN" phase="target">
  275.         this.checkAdjacentElement(true);
  276.         event.preventBubble();
  277.       </handler>
  278.       <handler event="keypress" keycode="VK_RIGHT" phase="target">
  279.         this.checkAdjacentElement(true);
  280.         event.preventBubble();
  281.       </handler>
  282.  
  283.       <!-- set a focused attribute on the selected item when the group
  284.            receives focus so that we can style it as if it were focused even though
  285.            it is not (Windows platform behaviour is for the group to receive focus,
  286.            not the item -->
  287.       <handler event="focus" phase="target">
  288.         if (event.target == this) {
  289.           this.setAttribute("focused", "true");
  290.           if (!this.focusedItem)
  291.             this.focusedItem = this.selectedItem;
  292.         }
  293.       </handler>
  294.       <handler event="blur" phase="target">
  295.         this.removeAttribute("focused");
  296.         this.focusedItem = null;
  297.       </handler>
  298.     </handlers>
  299.   </binding>
  300.  
  301.   <binding id="radio" extends="chrome://global/content/bindings/general.xml#control-item">
  302.     <resources>
  303.       <stylesheet src="chrome://global/skin/radio.css"/>
  304.     </resources>
  305.  
  306.     <content>
  307.       <xul:image class="radio-check" xbl:inherits="disabled,selected"/>
  308.       <xul:hbox class="radio-label-box" xbl:inherits="flex">
  309.         <xul:image class="radio-icon" xbl:inherits="src"/>
  310.         <xul:label class="radio-label" xbl:inherits="xbl:text=label,flex,accesskey,crop"/>
  311.       </xul:hbox>
  312.     </content>
  313.  
  314.     <implementation implements="nsIDOMXULSelectControlItemElement, nsIAccessibleProvider">
  315.       <constructor>
  316.         <![CDATA[
  317.           var parent = this.radioGroup;
  318.           parent.mRadioChildren[parent.mRadioChildren.length++] = this;
  319.         ]]>
  320.       </constructor>
  321.       <destructor>
  322.         <![CDATA[
  323.           var parent = this.radioGroup;
  324.           for (var i = 0; i < parent.mRadioChildren.length; ++i) {
  325.             if (parent.mRadioChildren[i] == this) {
  326.               parent.mRadioChildren.slice(i, i);
  327.               return;
  328.             }
  329.           }
  330.         ]]>
  331.       </destructor>
  332.       <property name="accessible">
  333.         <getter>
  334.           <![CDATA[
  335.             var accService = Components.classes["@mozilla.org/accessibilityService;1"].getService(Components.interfaces.nsIAccessibilityService);
  336.             return accService.createXULRadioButtonAccessible(this);
  337.           ]]>
  338.         </getter>
  339.       </property>
  340.       <property name="selected" readonly="true">
  341.         <getter>
  342.           <![CDATA[
  343.             return this.hasAttribute('selected');
  344.           ]]>
  345.         </getter>
  346.       </property>
  347.       <property name="radioGroup">
  348.         <getter>
  349.         <![CDATA[
  350.           var parent = this;
  351.           while (parent = parent.parentNode) {
  352.             if (parent.localName == "radiogroup")
  353.               return parent;
  354.           }
  355.           return null;
  356.         ]]>
  357.         </getter>
  358.       </property>
  359.     </implementation>
  360.   </binding>
  361. </bindings>