/*
** This software is part of a product of Xias by U. Kalatchoff & A. Z'Graggen
** Copying and reusing this software without prior authorization of Xias is explicitely
** forbidden. (contact: info@xias.ch)
*/


/*
** Some useful extensions to ECMA and DOM in IE and other browsers
**
** Last modified: 13.12.2005
**
*/

var x_runtime=new Object();
x_getClient();

if(x_runtime.clientInfo.app=='IE' && x_runtime.clientInfo.ver<=5.5){
   Function.prototype.call=x_callFunction;
   Array.prototype.pop=x_popArray;
   Array.prototype.push=x_pushArray;
   Array.prototype.shift=x_shiftArray;
   Array.prototype.unshift=x_unshiftArray;
   Array.prototype.splice=x_spliceArray;
   // dom
   if(!document.defaultView)document.defaultView=document.parentWindow;
}

// trick to merge NodeList to Array
Array.prototype.addNodeList=function(nodeList){
   for(var i=0;i<nodeList.length;i++){
      this.push(nodeList[i]);
   }
}

window.x_runtime.winClickListener= x_runtime.clientInfo.app=='IE' ? document : window;
window.x_runtime.winClickListener.winObject=window;


/*
** Client sniffer
*/

function x_getClient(){
  x_runtime.clientInfo=new Object();
  if(navigator.userAgent.indexOf('Opera')!=-1){
    x_runtime.clientInfo.app='Opera';
    if(navigator.appVersion.indexOf('Opera 8.')!=-1)x_runtime.clientInfo.ver=8;
    else x_runtime.clientInfo.ver=0;
  }
  else if(navigator.userAgent.indexOf('MSIE')!=-1){
    x_runtime.clientInfo.app='IE';
    if(navigator.appVersion.indexOf('MSIE 7.')!=-1)x_runtime.clientInfo.ver=7;
    else if(navigator.appVersion.indexOf('MSIE 6.')!=-1)x_runtime.clientInfo.ver=6;
    else if(navigator.appVersion.indexOf('MSIE 5.5')!=-1)x_runtime.clientInfo.ver=5.5;
    else if(navigator.appVersion.indexOf('MSIE 5.')!=-1)x_runtime.clientInfo.ver=5;
    else x_runtime.clientInfo.ver=0;
  }
  else if(navigator.userAgent.indexOf('Gecko')!=-1){
    x_runtime.clientInfo.app='Gecko';
    if(navigator.appVersion.indexOf('rv:1.8')!=-1)x_runtime.clientInfo.ver=1.8;
    else if(navigator.appVersion.indexOf('rv:1.7')!=-1)x_runtime.clientInfo.ver=1.7;
    else x_runtime.clientInfo.ver=0;
  }
}

/*
** add event listener (to elements and to objects)
*/
function x_addEventListener(obj,type,listener){
   //if(type=='DOMFocusIn')htmlEvtType='focus';
   //if(type=='DOMFocusOut')htmlEvtType='blur';
   var listenersName=type.toLowerCase()+'Listeners';
   if(typeof(obj[listenersName])=='undefined')obj[listenersName]=new Array();
   var el=obj[listenersName];
   var handlerName='on'+type.toLowerCase();
   var handler=obj[handlerName];
   // save handler set via attribute
   if(/*typeof(handler)!='undefined' && */handler && !handler.xel){
      handler.type=type;
      el.push(handler);
   }
   el.push(listener);
   obj[handlerName]=new Function('\
      var evt=(arguments.length!=0 ? arguments[0] : null);\
      if(this.childNodes)evt=x_getDomEvent(evt,x_getDomRootNode(this).defaultView);\
      var el=this["'+listenersName+'"];\
      for(var i=0;i<el.length;i++)el[i].call(this,evt);\
   ');
   obj[handlerName].xel=true;
}

/*
** generate dom compliant event (partial)
*/
function x_getDomEvent(evt){
   if(x_runtime.clientInfo.app=='IE'){
      var e= arguments.length==1 || !arguments[1]? event : arguments[1].event;
      e.target=e.srcElement;
      return e;
   }
   else return evt;
}

/*
** get the document root node
*/
function x_getDomRootNode(node){
   if(node.ownerDocument)return node.ownerDocument;
   while(node.parentNode!=null)node=node.parentNode;
   return node;
}

/*
** set style rule
*/
function x_addStyleRule(docNode,selector,style){
   if(docNode.styleSheets){
      var styleSheet=docNode.styleSheets[docNode.styleSheets.length-1];
      if(styleSheet.addRule)styleSheet.addRule(selector,style);
      else if(styleSheet.insertRule)
         styleSheet.insertRule(selector+'{'+style+'}',styleSheet.cssRules.length);
   }
}

/*
** get absolute left and top positions
*/
function x_getLeftPos(elt){
   var leftPos=0;
   if(x_runtime.clientInfo.app=='IE'){
      return elt.getClientRects()[0].left-2;
   }
   else if(elt.offsetParent){
      while(elt.offsetParent){
         leftPos+=elt.offsetLeft;
         elt=elt.offsetParent;
      }
   }
   return leftPos;
}
function x_getTopPos(elt){
   var topPos=0;
   if(x_runtime.clientInfo.app=='IE'){
      return elt.getClientRects()[0].top-2;
   }
   else if(elt.offsetParent){
      while(elt.offsetParent){
         topPos+=elt.offsetTop;
         elt=elt.offsetParent;
      }
   }
   return topPos;
}
function x_getWidth(elt){
   var cs=null;
   if(elt.currentStyle)cs=elt.currentStyle;
   else cs=getComputedStyle(elt,null);
   return (cs?parseInt(cs.marginLeft):0)+elt.offsetWidth+(cs?parseInt(cs.marginRight):0);
}
function x_getHeight(elt){
   var cs=null;
   if(elt.currentStyle)cs=elt.currentStyle;
   else cs=getComputedStyle(elt,null);
   return (cs?parseInt(cs.marginTop):0)+elt.offsetHeight+(cs?parseInt(cs.marginBottom):0);
}

/*
** interface calls (for variable arguments)
*/
function x_callInterfaceFunction(thisObj,funcName,args){
   x_runtime.ifcObj=thisObj;
   x_runtime.ifcArgs=args;
   var argsString='';
   for(var i=0;i<args.length;i++)argsString+=',x_runtime.ifcArgs['+i+']';
   eval('x_runtime.ifcReturn=x_runtime.ifcObj.'+funcName+'('+argsString.substr(1)+');');
   if(x_runtime.ifcReturn)return x_runtime.ifcReturn;
}

/*
** test if a given element is parent von elt
*/
function hasParent(elt,reqParent){
   while(elt.parentNode!=null){
      elt=elt.parentNode;
      if(elt==reqParent)return true;
   }
   return false;
}


/*
** Functions to extend the ECMA Script language support
** ----------------------------------------------------
*/

/* Function Object:
** call method (for IE < 5.5)
*/
function x_callFunction(){
   var functionToCallString=this.toString();
   x_runtime.cfString=functionToCallString.substr(9,functionToCallString.indexOf('(')-9);
   var argsString='(';
   if(arguments.length>0){
      if(arguments[0]){
         x_runtime.cfObj=arguments[0];
         eval('x_runtime.cfObj.cfTempFunction='+this.toString());
         x_runtime.cfString='x_runtime.cfObj.cfTempFunction';
      }
      if(arguments.length>1){
        x_runtime.cfArgs=arguments;
        argsString+='x_runtime.cfArgs[1]';
        if(arguments.length>2)
           for(var i=2;i<aruguments.length;i++)
              argsString+=',x_runtime.cfArgs['+i+']';
      }
   }
   argsString+=');';
   eval(x_runtime.cfString+argsString);
}

/* Array object:
** Pop (take last from array) method of Array object
*/
function x_popArray(){
   var last=this[this.length-1];
   this.length--;
   return last;
}

/* Array object:
** Push (add items at end) method of Array object
*/
function x_pushArray(){
   for(var i=0;i<arguments.length;i++){
      this[this.length]=arguments[i];
   }
   return this.length;
}

/* Array object:
** Shift (take first) method of Array object
*/
function x_shiftArray(){
   var first=this[0];
   for(var i=0;i<this.length-1;i++){
      this[i]=this[i+1];
   }
   this.length-=1;
   return first;
}

/* Array object:
** Unhift (add items at the biginning) method of Array object
*/
function x_unshiftArray(){
   this.length+=arguments.length;
   for(var i=this.length-1;i>arguments.length-1;i--){
      this[i]=this[i-arguments.length];
   }
   for(var i=0;i<arguments.length;i++){
      this[i]=arguments[i];
   }
   return this.length;
}

/* Array Object:
** Splice: remove and add elements from/to array
** (negative i and n not implemented)
**    returns: removed elts
*/
function x_spliceArray(i,n){
   var elts=null;
   if(n>=0 && n<=this.length-i){
      var p=arguments.length-2-n;
      elts=this.slice(i,i+n);
      var l=this.length+p;
      if(p<0){
         for(var j=i;j<l;j++)
            this[j]=this[j-p];
         this.length=this.length+p;
      }
      else if(p>0){
         this.length=this.length+p;
         for(var j=l-1;j>=i+p;j--)
            this[j]=this[j-p];
      }
      if(arguments.length>2){
         for(var j=0;j<arguments.length-2;j++)
            this[i+j]=arguments[j+2];
      }
   }
   return elts;
}
