
/********************** FMD WEB FRAMEWORK - UTILITY FUNCTIONS **********************/
/* Version: 3.0                                                                    */
/* Copyright (c) 2005 Flying Machine Development, Inc All Rights Reserved          */
/* Contact: info@flyingmachine.com                                                 */
/***********************************************************************************/

/********************************** Collection object ******************************/

  function Collection()
  {
    var self=new Object();
    self.keys = new Array();
    self.length = 0;

    self.clear=function()
    {
      for(var n=0;n<this.length;n++)
      {
        delete this[n];
        delete this.keys[n];
      }
      this.length=0;
    }
  
    self.isMember=function(key)
    {
      var n=0;
      for (n=0;n<this.length;n++)
      {
        if(this.keys[n] == key)
        {
          return true;
        }
      }
      return false;
    }
  
    self.add=function(key, value)
    {
       this[key] = value;
       for (var n=0;n<this.length;n++)
       {
         if(this.keys[n] == key) break;
       }
       this[n]=this[key];
       this.keys[n] = key;
       if(n>=this.length)this.length++;
       return this[key];
    }
  
    self.sort=function(fx)
    {
  
      var cSort=new collection();
      var aSort=new Array()
      if(!fx)
      {
        for(var n=0;n<this.length;n++)
        {
          aSort[n]=this.keys[n];
        }
        aSort.sort();
        for(var n=0;n<aSort.length;n++)
        {
          cSort.add(aSort[n], this[aSort[n]])
        }
      }
      else
      {
        for(var n=0;n<this.length;n++)
        {
          aSort[n]=new Array(this.keys[n], this[n])
        }
        aSort.sort(fx);
        for(var n=0;n<aSort.length;n++)
        {
          cSort.add(aSort[n][0], this[aSort[n][0]])
        }
      }
      
      return cSort;
    }

    return self;
  }
  

/***********************************************************************************/
/***********************************************************************************/
/***********************************************************************************/
/********************************** OLD FUNCTIONS **********************************/
/***********************************************************************************/
/***********************************************************************************/
/***********************************************************************************/



/********************************* browser functions *******************************/

  DOM_SUPPORT = (document.getElementById)?1:0;
  BRWSR_NS4 = (document.layers)?1:0;
  BRWSR_IE = (document.all)?1:0;
  BRWSR_IE4 = BRWSR_IE && !DOM_SUPPORT;
  BRWSR_MOZ = !BRWSR_IE && DOM_SUPPORT;
  BRWSR_OTHER = !BRWSR_IE && !BRWSR_NS4 && !BRWSR_MOZ;
  OS_MAC = (navigator.appVersion.indexOf("Mac")>=0);
  OS_WIN = (navigator.appVersion.indexOf("Win")>=0);
  OS_OTHER = (!OS_MAC&&!OS_WIN);
 
  document.browserID=(BRWSR_NS4)?"NS4":(BRWSR_IE4)?"IE4":(BRWSR_MOZ)?"MOZ":(BRWSR_IE)?"IE":"OTHER";

  function isBrowser(b){if(b.indexOf("|") >=0){var a=b.split("|"); 
    for(var i=0;i<a.length;i++){ if(document.browserID==a[i].toUpperCase()) return true;}}
    if(document.browserID==b) return true; return false;
  }

/*********************************** menu utils **********************************/


  function menuMouseHndlr(e)
  {
    if(e){document.menuEvent=e;} else{document.menuEvent=event;}
  }

  function showMenu(m, x, y){ var mnu=findElement(m);
    if(document.curMenu) hideElement(document.curMenu);document.curMenu=mnu;
    if(DOM_SUPPORT && !isBrowser("IE")){;mnu.addEventListener("mouseout",menuMouseHndlr,true);} 
    positionElement(mnu,x,y);
    if(mnu.style){mnu.style.zIndex = 999;}else{mnu.zIndex=999;}
    showElement(mnu);
  }

  function showMenuRelative(r, m, x, y){var mnu=findElement(m); var relobj=findElement(r);
    if(document.curMenu) hideElement(document.curMenu);document.curMenu=mnu;
    if(DOM_SUPPORT && !isBrowser("IE")){;mnu.addEventListener("mouseout",menuMouseHndlr,true);}
    positionElement(mnu,getElementLeft(relobj)+x,getElementTop(relobj)+y);
    if(mnu.style){mnu.style.zIndex = 999;}else{mnu.zIndex=999;}
    showElement(mnu);
  }

  function xshowMenuRelative(a, m, dx, dy){var mnu=findElement(m); 
    if(document.curMenu) hideElement(document.curMenu);document.curMenu=mnu;
    if(DOM_SUPPORT && !isBrowser("IE")){x.addEventListener("mouseout",menuMouseHndlr,true);} 
    positionElement(m,getElementLeft(a)+dx,getElementTop(a)+dy);
    if(mnu.style){mnu.style.zIndex = 999;}else{mnu.zIndex=999;}
    showElement(mnu);
  }

  function getMenuTop(mnu){
    if(!isBrowser("NS4")){var y=mnu.offsetTop;var p=mnu; 
    while(p=p.offsetParent){y+=p.offsetTop}} else{var y=mnu.y} return y;
  }

  function getMenuLeft(mnu){
    if(!isBrowser("NS4")){var x=mnu.offsetLeft;var p=mnu; 
    while(p=p.offsetParent){x+=p.offsetLeft}} else{var x=mnu.x;} return x;
  }

  function getMenuRight(mnu){
    var x=getMenuLeft(mnu) + mnu.offsetWidth;
    return x;
  }

  function getMenuBottom(mnu){
    var x=getMenuTop(mnu) + mnu.offsetHeight;
    return x;
  }

  function isInsideMenu(mnu, x, y, d){return((x-2)>getMenuLeft(mnu) && (x+2)<getMenuRight(mnu) && (y-2)>getMenuTop(mnu) && (y+2)<getMenuBottom(mnu));}

  function getMenuMouseX(){if(document.menuEvent){if(document.menuEvent.pageX) return document.menuEvent.pageX; 
    return document.menuEvent.clientX;}else{if(!isBrowser("IE")) return event.pageX; else return event.clientX;}
  }

  function getMenuMouseY(){if(document.menuEvent){if(document.menuEvent.pageY) return document.menuEvent.pageY; 
    return document.menuEvent.clientY;}else{if(!isBrowser("IE")) return event.pageY; else return event.clientY;}
  }

  function hideMenu(m){if(!isBrowser("NS4")){var mnu=findElement(m);hideElement(mnu);}
    if(DOM_SUPPORT && !isBrowser("IE")){mnu.removeEventListener("mouseout",menuEventHndlr,false);}
  }


/*********************************** string utils **********************************/

  String.prototype.trim = function(){
    return this.replace(/(^\s*)|(\s*$)/g, "");
  }
  
  String.prototype.toTitleCase = function(){
    var s,c; c = this.charAt(0); s = c.toUpperCase();      
    for (n=1; n< this.length; n++) {c = this.charAt(n); if (this.charAt(n-1) == " "){
    s=  s+c.toUpperCase();} else {s=s+c.toLowerCase();}}return s;
  }
  
  String.prototype.URIencode = function(){
    return escape(this);
  }
  
  String.prototype.URIdecode = function(){
    return unescape(this);
  }
  
/*********************************** number utils **********************************/
  
  Number.prototype.round = function(a){
    a=(!a?0:a);return Math.round(this * Math.pow(10,a))/Math.pow(10,a);
  }
  
  Number.prototype.toCurrency = function(){
    var c=this.round() + '';c=(c.charAt(0)=='.'?'0'+c:c);if (c.charAt(c.length-3)=='.'){
    return c;}else if(c.charAt(c.length-2)=='.'){return c+'0';} else {return c+'.00';}
  }
  
/*********************************** image utils ***********************************/
  
  function preloadImages() {
    var d=document; if(d.images){ if(!d.p) d.p=new Array();
    var i,j=d.p.length,a=preloadImages.arguments; for(i=0; i<a.length; i++)
    if (a[i].indexOf("#")!=0){ d.p[j]=new Image; d.p[j++].src=a[i];}}
  }
  
  // ** make swap image and restore capable of storing multiple "swapped" images in 
  // different registers.
  
  function swapImage() {
    var i,j=0,x,a=swapImage.arguments; document.sr=new Array; for(i=0;i<(a.length-2);i+=3)
    if ((x=findElement(a[i]))){document.sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}
  }
  
  function swapImgRestore() {
    var i,x,a=document.sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
  }

  function setImage(n, i) {
    var e; if ((e=findElement(n))){e.src=i;}
  }
  
  function rotateImages() {
    var i,a=rotateImages.arguments;x=findElement(a[0]);if(!x.timer){
    x.images=new Array();for(i=2;i<a.length;i++){x.images[i-2]=a[i];}x.timer=a[1];x.curImage=-1;}
    x.curImage++;if(x.curImage==x.images.length)x.curImage=0;x.src=x.images[x.curImage];
    setTimeout('rotateImages("' + x.name + '")',x.timer);
  }
  
/******************************* querystring utils *********************************/
  
  function getArgs() {
    var args=new Object();var query=location.search.substring(1);
    var pairs=query.split("&");for(var i = 0; i < pairs.length; i++) {
  	var pos = pairs[i].indexOf('='); 	if (pos == -1) continue;                 
  	var argname = pairs[i].substring(0,pos).toLowerCase(); var value = pairs[i].substring(pos+1);   
  	args[argname] = value.URIdecode();} return args; 
  }
  
  function getArg(argname)
  {
    argname=argname.toLowerCase().replace(" ","+");var args = getArgs();if(args[argname]){
    return args[argname].replace(/\+/g," ");}else{return "";}
  }
  
/****************************** positioning utils **********************************/


  function findElement(n, d) {
    var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
      d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
    if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
    for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=findElement(n,d.layers[i].document); 
    if(!x && document.getElementById) x=document.getElementById(n); return x;
  }

  function positionElement(e, x, y){if(e.moveToAbsolute){e.moveToAbsolute(x,y);}else if(e.style.left)
  {e.style.left=(x + "px");e.style.top=(y + "px")}else{e.left=x;e.top=y;}
  }   

  function getElementTop(e){
    if(e.offsetTop){var y=e.offsetTop;var p=e;while(p=p.offsetParent){
    y+=p.offsetTop}}else if(e.y){var y=e.y}else{y=0}return y;
  }

  function getElementLeft(e){
    if(e.offsetLeft){var x=e.offsetLeft;var p=e;while(p=p.offsetParent){
    x+=p.offsetLeft}}else if(e.x){var x=e.x;}else{x=0}return x;
  }

  function showElement(e){e.visibility='show';if(e.style)e.style.visibility='visible';}

  function hideElement(e){e.visibility = 'hide';if(e.style)e.style.visibility = 'hidden';}   

  function resizeElement(e, x, y, d){e.width=x;e.height=y;e.style.width=x;e.style.height=y;}   

  function writeHTML(n, s, d){
    var e=findElement(n,d);if(e.open){e.open();e.document.write(s);e.close();
    } else{e.innerHTML = s;}
  }

  function setColor(n, c){var e=findElement(n);e.backgroundcolor=c;e.style.backgroundColor=c;}

  function getElementRight(e){var x=getElementLeft(e) + e.offsetWidth;return x;}

  function getElementBottom(e){var y=getElementTop(e) + e.offsetHeight;return y;}

  function isInside(e, x, y, d){
    return((x-2)>getElementLeft(e) && (x+2)<getElementRight(e) && (y-2)>getElementTop(e)
    && (y+2)<getElementBottom(e));
  }

  function getEventPageX(){if(document.domEvent) return document.domEvent.clientX; 
    if(event.pageX)return event.pageX;else return event.clientX;
  }
  function getEventPageY(){if(document.domEvent) return document.domEvent.clientY; 
    if(event.pageY)return event.pageY;else return event.clientY;
  }

/******************************* error functions ***********************************/
    
  function suppressErrors(m,u,l){return true;}
  
  function showErrors(m,u,l){return false;}
  

/******************************** date functions ***********************************/

	function curDate()	{
		var days = new Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday");
		var d=new Date();	var day=days[d.getDay()-0];	return day.toUpperCase() + " " + 
		(d.getMonth()+1) + "." + (d.getDate()) + "." + (d.getYear());	
	}


  /******************************** popup functions **********************************/

  function showPopup(u, w, h, r, s)
  {
    var args = 'width=' + w + ',height=' + h + ',top=' + (screen.availHeight-h)*.5
    + ',left=' + (screen.availWidth-w)*.5; if(r) args+=',resizable=yes'; 
    if(s) args+=',scrollbars=yes'; window.open(u, "popup",args);
  }

  /******************************** rollover functions *******************************/

  function showRolloverImage(n, i1, i2, u, cp, t) {
    document.write('<a href="' + u + '"' + (t?' target="' + t + '"':'') +  ' onMouseOut="swapImgRestore()" onMouseOver="swapImage(\'' + n + '\',\'\',\'' + i2 + '\',1)"><img name="' + n + '" src="' + i1 + '" border="0"></a>');
  }

  function showRolloverText() {
    ;
  }

  /********************************* cookie functions ********************************/

   function fixDate(date) 
   {
      var base = new Date(0);
      var skew = base.getTime();
      if (skew > 0)
         date.setTime(date.getTime() - skew);
   }

   function setCookie(name, value, expires, path, domain, secure) 
   {
   		var curCookie = name + "=" + escape(value) +
         ((expires) ? "; expires=" + expires.toGMTString() : "") +
         ((path) ? "; path=" + path : "") +
         ((domain) ? "; domain=" + domain : "") +
         ((secure) ? "; secure" : "");
	
        document.cookie = curCookie;
   }

   function getCookie(name) 
   {
      var prefix = name + "=";
      var cookieStartIndex = document.cookie.indexOf(prefix);
      if (cookieStartIndex == -1)
         return null;
      var cookieEndIndex = document.cookie.indexOf(";", cookieStartIndex +
         prefix.length);
      if (cookieEndIndex == -1)
         cookieEndIndex = document.cookie.length;
      return unescape(document.cookie.substring(cookieStartIndex +
         prefix.length,
   		cookieEndIndex));
   }

  function cookiesEnabled()
  {
    testValue=Math.floor(1000*Math.random());
    setCookie('cookiesEnabled',testValue);
    return(testValue==getCookie('cookiesEnabled')) 
  }

  function saveFormToCookie(sform)
  {   
    var scookie="";
    var f=document.forms[sform];

    for(var n=0;n<f.elements.length;n++)
    {
      if(!f[f[n].name].length || f[n].type.substr(0,6).toLowerCase()=="select")
      {
        if(f[n].type.toLowerCase()=="checkbox" || f[n].type.toLowerCase()=="radio")
        {
          scookie+= "f." + f[n].name + ".checked=" + f[n].checked.toString() + ";";
        }        
        else
        {
          scookie+= "f." + f[n].name + ".value='" + f[n].value.toString() + "';";
        }
      }
      else if(scookie.search(f[n].name)<0)
      {
        for(var i=0;i<f[f[n].name].length;i++)
        {
          if(f[n].type.toLowerCase()=="checkbox" || f[n].type.toLowerCase()=="radio")
          {
            scookie+= "f." + f[n].name + "[" + i + "].checked=" + f[f[n].name][i].checked.toString() + ";";
          }        
          else
          {
            scookie+= "f." + f[n].name + "[" + i + "].value='" + f[f[n].name][i].value.toString() + "';";
          }
        }
      }
    }
    //alert(f.name)
    //alert(scookie)
    setCookie(f.name,scookie);
  }

  function getFormFromCookie(sform)
  {   
    var f=document.forms[sform];
    window.onerror=suppressErrors;
    eval(getCookie(f.name));
    window.onerror=showErrors;
  }
  

/******************************** random functions *******************************/


  function genID(len)
  {
    var szID="";
    
    for(var n=0;n<len;n++)
    {
      
      // determine next byte type (alpha/numeric)
      if(parseInt(2 * Math.random() + 1) == 1)
      {
        szID += String.fromCharCode(parseInt(10 * Math.random()) + 48);
      }
      else
      {
        szID += String.fromCharCode(parseInt(26 * Math.random()) + 65);
      }
         
    }    
    return szID;
  
  }
  function getXMLValue(xml, tagname)
  {
    value='';
    var e=xml.getElementsByTagName(tagname);
    if(e.length>0)
    {
      if(e[0].firstChild)
      {
        value=e[0].firstChild.data;
      }
    }
    return value;
  }

  function getXMLValueFromKey(xml, tagname, keytagname, keyvalue)
  {
    value='';
    for(var n=0;n<xml.length;n++)
    {
      var e=xml[n].getElementsByTagName(keytagname);
      if(e[0].firstChild.data==keyvalue)
      {
        var e=xml[n].getElementsByTagName(tagname);
        if(e[0].firstChild)
        {
          value=e[0].firstChild.data;
          break;
        }
      }
    }
    return value;
  }

  function formToXML(f)
  {
    var xml = '';
    for (e=0;e<f.elements.length;e++) 
    {
      if (f.elements[e].name!='') 
      {
        switch(f.elements[e].type)
        {
        case "checkbox":
          if(f.elements[e].checked)
          {
            xml+='<' + f.elements[e].name + ' datatype="' + f.elements[e].datatype + '" >' + f.elements[e].value + '</' + f.elements[e].name + '>'
          }
          break;    
        case "radio":
          if(f.elements[e].checked)
          {
            xml+='<' + f.elements[e].name + ' datatype="' + f.elements[e].datatype + '" >' + f.elements[e].value + '</' + f.elements[e].name + '>'
          }
          break;    
        case "select-one":
          if(f.elements[e].options.length>0)
          {
            xml+='<' + f.elements[e].name + ' datatype="' + f.elements[e].datatype + '" >' + f.elements[e].options[f.elements[e].selectedIndex].value + '</' + f.elements[e].name + '>'
          }
          break;    
        default:
          xml+='<' + f.elements[e].name + ' datatype="' + f.elements[e].datatype + '" >' + f.elements[e].value + '</' + f.elements[e].name + '>'
          break;    
        }
      }
    }
    return xml
  }


  function formToXMLMultiple(fID, KeyField, FieldList)
  {
    f = document.forms[fID];
    var xml = '';
    var flds=""
    flds=FieldList.split(",")
    flist=" " + FieldList.replace(/,/g," ") + " ";
    for(n=0;n<f.elements.length;n++)
    {
      if(flist.search(" " + f.elements[n].name + " ") <0 && f.elements[n].name!=KeyField)
      {
        xml+=inputToXML(f.elements[n])
      }
    }

    if(f.elements[KeyField].length)
    {
      for(k=0;k<f.elements[KeyField].length;k++)
      {
        xml+='<' + KeyField + '>'    
        for(n=0;n<flds.length;n++)
        {
          if(f.elements[flds[n]][0] && flds[n]!=KeyField)
          {
            xml+=inputToXML(f.elements[flds[n]][k])
          }
        }
        xml+='</' + KeyField + '>'
      }
    }
    else
    {
      xml+='<' + KeyField + '>'    
      for(n=0;n<flds.length;n++)
      {
        xml+=inputToXML(f.elements[flds[n]])
      }
      xml+='</' + KeyField + '>'
    }


    return xml
  }

  function inputToXML(e)
  {
    var xml="";
    switch(e.type)
    {
    case "checkbox":
      if(e.checked)
      {
        xml+='<' + e.name + '>' + e.value + '</' + e.name + '>'
      }
      break;    
    case "radio":
      if(e.checked)
      {
        xml+='<' + e.name + '>' + e.value + '</' + e.name + '>'
      }
      break;    
    case "select-one":
      xml+='<' + e.name + '>' + e.options[e.selectedIndex].value + '</' + e.name + '>'
      break;    
    default:
      xml+='<' + e.name + '>' + e.value + '</' + e.name + '>'
      break;    
    }
    return xml;
  }

  function XMLToForm(fID, xml)
  {
    f = document.forms[fID];
    for(var c=0;c<xml.childNodes.length;c++)
    {
      cN=xml.childNodes[c];
      if(f[cN.tagName] && cN.firstChild)
      {
        if(f[cN.tagName].length > 0 && f[cN.tagName].type !="select-one")
        {
          for(i=0;i<f[cN.tagName].length;i++)
          {
            switch(f[cN.tagName][i].type)
            {
            case "checkbox":
              (cN.firstChild.data=="True"?f[cN.tagName][i].checked=true:f[cN.tagName][i].checked=false)
              break;    
            case "radio":
              (cN.firstChild.data==f[cN.tagName][i].value?f[cN.tagName][i].checked=true:f[cN.tagName][i].checked=false)
              break;    
            default:
              f[cN.tagName][i].value=cN.firstChild.data;
              break;    
            }
          }          
        }
        else
        {
          switch(f[cN.tagName].type)
          {
          case "select-one":
            for(var o=0;o<f[cN.tagName].length;o++)
            {
              if(f[cN.tagName][o].value==cN.firstChild.data)
              {
                f[cN.tagName][o].selected=true;
              }
            }
            break;    
          case "checkbox":
            (cN.firstChild.data=="True"?f[cN.tagName].checked=true:f[cN.tagName].checked=false)
            break;    
          case "radio":
            for(var o=0;o<f[cN.tagName].length;o++)
            {
              if(f[cN.tagName][o].value==cN.firstChild.data)
              {
                f[cN.tagName][o].selected=true;
              }
            }
            break;    
          default:
            f[cN.tagName].value=cN.firstChild.data;
            break;    
          }
        }
      }
    }
  }

  function formatDate(d)
  {
    return (d.getMonth()+1) + "/" + d.getDate() + "/" + d.getYear()    
  }

  function toCurrency(n)
  {
    return "$" + new String(n.toFixed(2)).split("").reverse().join("").replace(/(\d{3})/g,"$1,").split("").reverse().join("").replace(/^,/,"")
  }

  function isDate(d) 
  {
    // validates for dates formatted as mm/dd/yy or mm/dd/yyyy

    var m=d.match(/^(\d{1,2})(\/)(\d{1,2})\2(\d{2,4})$/)
    if(!m) return false;
    if (m[1] > 12 || m[1] < 1) return false;
    if (m[3] > 31 || m[3] < 1) return false; 

    // month len check
    if ((m[1]==4 || m[1]==6 || m[1]==9 || m[1]==11) && m[3]>30) return false;
    
    // leap year feb month len check
    if((m[4] % 4 == 0 && !(m[4] % 100 == 0 || m[4] % 400 == 0)) && m[3]>29) return false;

    // normal year feb month len check
    if (m[1]==2 && m[3]>28) return false;

    return true;
  }

  function isTime(t) {

    // validates for times formatted as hh:mm:ss am/pm, hh:mm am/pm and hh:mm

    if(!t.match(/^(\d{1,2})(\:)(\d{2})\2(\d{2})(\ )\w[AM|PM|am|pm]$/))
    {
      if(!t.match(/^(\d{1,2})(\:)(\d{2})(\ )\w[AM|PM|am|pm]$/))
      {
        if(!t.match(/^(\d{1,2})(\:)(\d{2})$/))
        {
          return false;          
        }
      }
    }

    var m=t.match(/^(\d{1,2})(\:)(\d{2})/)
    if (m[1] > 12) return false;
    if (m[3] > 59) return false; 

    var m=t.match(/^(\d{1,2})(\:)(\d{2})\2(\d{2})/)
    if(m)
    {
      if (m[4] > 59) return false; 
    }
  
    return true;

  }

  function handleServerResponse(xmlDoc)
  {
    var e=xmlDoc.getElementsByTagName("Error");
    if(e.length>0)
    {
      if(getXMLValue(xmlDoc, "Error")=="INVALID_LOGIN")
      {
        me.hide();window.parent.logOut();
      }
    }
  }

  function validateForm(f)
  {
    var sMsg="Invalid Entry"
    for(var n=0;n<f.elements.length;n++)
    {
      var e=f.elements[n];

      var valfail=false;
      if(e.required=="true")
      {
        if(e.options)
        {
          if(e.options[e.selectedIndex].value=="")
            valfail=true;
        }
        else if(e.value=="")
        {
          valfail=true;
        }

        if(valfail)
        {
    	    if(e.message) sMsg=e.message;
    	    alert(sMsg);
          e.focus();
          return false;

        }
      }
    }

    return true;
  }
