var radioStates=new Array();
/**
 * @param object  inElem : the DOM element to use
 * @param boolean deep   : optional; whether or not to disable radios
 *                         buttons in child elements; defaults to true
 * @requires             : function getElemsInElem
 * @requires             : function toggleRadioButton
 */
function makeRadiosUncheckable(inElem,deep) {
   if (typeof deep=="undefined") {
      deep=true;
   }
   var radios=getElemsInElem(inElem,"tagName=/input/i&type=/radio/i",deep,true);
   for (var i=0;i<radios.length;i++) {
      if (radios[i].checked) {
         radioStates[radios[i].name]=radios[i].value;
      } else if (typeof radioStates[radios[i].name]=="undefined") {
         radioStates[radios[i].name]=false;
      }
   }
}
/**
 * @param object elem : The radio input element which need to be 'toggled'
 */
function toggleRadioButton(elem) {
   if (radioStates[elem.name]==elem.value) {
      radioStates[elem.name]=false;
      elem.checked=false;
   } else {
      radioStates[elem.name]=elem.value;
      elem.checked=true;
   }
}
/**
 * @param  object  inElem   : The DOM element to be searched
 * @param  string  attrSets : A string containing the search terms in the
 *                            format "term1=value1&term2=value2"
 * @param  boolean deep     : optional; whether or not to search
 *                          : recursively; defalut is true
 * @param  boolean reg      : if the search values should be evaluated as
 *                            regular expressions; default is false
 * @return object           : an Array containing all matched elements
 * @requires                : function elemHasAttribute
 * @requires                : function elemGetAttribute
 * @requires                : function parseRegExp
 */
function getElemsInElem(inElem,attrSets,deep,reg) {
   if (typeof deep=="undefined") {
      deep=true;
   }
   if (typeof reg=="undefined") {
      reg=false;
   }
   if (typeof attrSets!="object") {
      var sets=(""+attrSets).split("&");
      attrSets=new Array();
      for (var i=0; i<sets.length; i++) {
         var index=sets[i].indexOf("=");
         var value=sets[i].substring(index+1);
         attrSets[sets[i].substring(0,index)]=reg?parseRegExp(value):value;
      }
   }
   var elems=new Array();
   for (var i=0; i<inElem.childNodes.length; i++) {
      var elem=inElem.childNodes[i];
      if (elem.nodeType==3) {continue;} // Node.TEXT_NODE
      var isElem=true;
      for (var attr in attrSets) {
         if (!elemHasAttribute(elem,attr)) {
            isElem=false;
            break;
         } else {
            var value=elemGetAttribute(elem,attr);
            if (!(reg?attrSets[attr].test(value):value==attrSets[attr])) {
               isElem=false;
               break;
            }
         }
      }
      if (isElem) {
         elems[elems.length]=elem;
      }
      if (deep&&elem.childNodes.length>0) {
         var childElems=getElemsInElem(elem,attrSets,deep,reg);
         for (var j=0; j<childElems.length; j++) {
            elems[elems.length]=childElems[j];
         }
      }
   }
   return elems;
}
/**
 * @param  string str : A string containing a regular expression
 * @return object     : A RegExp object on success or null otherwise
 */
function parseRegExp(str) {
   var start=str.indexOf("/");
   var end=str.lastIndexOf("/");
   if (start==end) {return null;}
   var reg=str.substring(start+1,end);
   var flags=str.substring(end+1);
   return new RegExp(reg,flags);
}
/**
 * @param  object  elem : the DOM element to be tested
 * @param  string  attr : the attribute to test for
 * @return boolean      : true if the attribute exists, false otherwise
 */
function elemHasAttribute(elem,attr) {
   var isset;
   try {
      eval("isset=typeof elem."+attr+"!='undefined';");
   } catch (e) {
      try {
         isset=elem.hasAttribute(attr);
      } catch (e) {
         isset=false;
      }
   }
   return isset;
}
/**
 * @param  object  elem : the DOM element to be used
 * @param  string  attr : the attribute to get
 * @return boolean      : the value of the attribute or null on error
 */
function elemGetAttribute(elem,attr) {
   try {
      return eval("elem."+attr);
   } catch (e) {
      return null;
   }
}
