/*
** 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
**
*/

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;
   document.body.ownerDocument=document;
   document.body.parentNode.ownerDocument=document;
}

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

x_runtime.winClickListener= typeof window.onclick=='undefined' ? document : 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;
   if(node.document)return node.document;
   if(node.body)return node;
   while(node.parentNode && !node.ownerDocument)node=node.parentNode;
   if(node.ownerDocument)node=node.ownerDocument;
   else alert('Problem by getting document object. Retrieved '+node.tagName);
   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);
         return styleSheet.rules.length-1;
      }
      if(styleSheet.insertRule){
         styleSheet.insertRule(selector+'{'+style+'}',styleSheet.cssRules.length);
         return styleSheet.cssRules.length-1;
      }
   }
}
function x_removeStyleRule(docNode,ruleNr){
   if(docNode.styleSheets){
      var styleSheet=docNode.styleSheets[docNode.styleSheets.length-1];
      if(styleSheet.deleteRule)styleSheet.deleteRule(ruleNr);
      else if(styleSheet.removeRule)styleSheet.removeRule(ruleNr);
   }
}

// viewport dimensions  (adapted from quirksmode.org)
function x_getInnerWidth(){
   if(self.innerHeight) // all except Explorer
     return self.innerWidth;
   else if(document.documentElement && document.documentElement.clientHeight)
      // Explorer 6 Strict Mode
      return document.documentElement.clientWidth;
   else if(document.body) // other Explorers
      return document.body.clientWidth;
}
function x_getInnerHeight(){
   if(self.innerHeight) // all except Explorer
     return self.innerHeight;
   else if(document.documentElement && document.documentElement.clientHeight)
      // Explorer 6 Strict Mode
      return document.documentElement.clientHeight;
   else if(document.body) // other Explorers
      return document.body.clientHeight;
}

// viewport scrolling (adapted from quirksmode.org)
function x_getScrollLeft(){
   var winObject=(arguments[0]?arguments[0]:window);
   if(winObject.self.pageYOffset) // all except Explorer
      return winObject.self.pageXOffset;
   else if(winObject.document.documentElement && winObject.document.documentElement.scrollTop)
      // Explorer 6 Strict
      return winObject.document.documentElement.scrollLeft;
   else if(winObject.document.body) // all other Explorers
      return winObject.document.body.scrollLeft;
}
function x_getScrollTop(){
   var winObject=(arguments[0]?arguments[0]:window);
   if(winObject.self.pageYOffset) // all except Explorer
      return winObject.self.pageYOffset;
   else if(winObject.document.documentElement && winObject.document.documentElement.scrollTop)
      // Explorer 6 Strict
      return winObject.document.documentElement.scrollTop;
   else if(winObject.document.body) // all other Explorers
      return winObject.document.body.scrollTop;
}

/*
** get absolute left and top positions
*/
function x_getLeftPos(elt){
   var leftPos=0;
   if(x_runtime.clientInfo.app=='IE'){
      return elt.getBoundingClientRect().left-(x_runtime.clientInfo.ver==5? 2 : 0);
   }
   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.getBoundingClientRect().top-(x_runtime.clientInfo.ver==5? 2 : 0);
   }
   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;
}

// debug function
function x_dump(msg){
   if(!x_runtime.consoleElt){
      var ce=document.createElement('div');
      ce.style.position='absolute';
      ce.style.width='300px';
      ce.style.height='200px';
      ce.style.bottom='0px';
      ce.style.right='0px';
      ce.style.border='1px solid black';
      ce.style.padding='2px';
      ce.style.overflow='auto';
      document.body.appendChild(ce);
      x_runtime.consoleElt=ce;
   }
   var msgElt=document.createElement('div');
   msgElt.appendChild(document.createTextNode(msg));
   x_runtime.consoleElt.appendChild(msgElt);
}

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


/*
** Auxiliary objets and functions
** (window and display mangement,...)
**
** Last modified: 17.10.2005
**
*/

// Fix Mask for window
/*function createWindowMask(){

}
x_runtime.mask=createWindowMask(document);
*/


// Dialog Object
x_runtime.dialogs=new Object();
x_runtime.dialogCounter=0;

function Dialog(dialog){
   this.elt=typeof(dialog)=='object' ? dialog : document.getElementById(dialog);
   this.winObject= arguments.length==1 ? window : arguments[1];
   if(this.elt.id==''){
      this.elt.id='dialog'+x_runtime.dialogCounter;
      x_runtime.dialogCounter++;
   }
   this.id=this.elt.id;
   x_runtime.dialogs[this.id]=this;
   this.onshow=null;
   this.onhide=null;
}


// own methods

Dialog.prototype.show=function(){
   // args[0]: positionment, [1,2]: x,y
   var position=(arguments[0] ? arguments[0] : 'centered');
   var runtime=this.winObject.x_runtime;
   if(runtime.actualDialog && runtime.actualDialog!=this){
      runtime.actualDialog.hide();
   }
   runtime.actualDialog=this;
   var elt=this.elt;
   if(elt.style.visibility!='visible'){
      if(position=='custom'){
         elt.style.left=(arguments[1] ? arguments[1]+'px' : '0px');
         elt.style.top=(arguments[2] ? arguments[2]+'px' : '0px');
      }
      else fixInWindow(this.winObject,elt,'centered');
      x_runtime.blockClickEvents=true;
      setTimeout('x_runtime.blockClickEvents=false;',100);
      runtime.winClickListener.onclick=tempClickHandler;
      elt.style.visibility='visible';
      setTimeout('x_focusFirstDialogInput(x_runtime.dialogs["'+this.id+'"]);',100);
   }
   if(this.onshow)this.onshow();
   return false;
}
   function x_focusFirstDialogInput(dialog){
      var elts=dialog.elt.getElementsByTagName('input');
      if(elts.length>0)elts[0].focus();
   }

Dialog.prototype.hide=function(){
   if(this.winObject.x_runtime){
      this.elt.style.visibility='hidden';
      this.winObject.x_runtime.winClickListener.onclick=null;
      this.winObject.x_runtime.actualDialog=null;
      if(this.onhide)this.onhide();
   }
}

// function to temporarily capture all win events
// - to be part fo Dialog Object?
// - to be replaced with a mask system?
function tempClickHandler(evt){
   if(this.winObject){
      var runtime=this.winObject.x_runtime;
      if(!x_runtime.blockClickEvents){
         evt=x_getDomEvent(evt,this.winObject);
         var elt=runtime.actualDialog.elt;
         if(elt.style.visibility=='visible'){
            if(!hasParent(evt.target,elt) && evt.target!=elt){// if click not on dialog
               runtime.actualDialog.hide();
            }
         }
      }
   }
}

// Function to place an element in a fixed position
function fixInWindow(winObject,elt){
   // args[1,2]:where
   var position='centered';
   /*if(arguments.length>1){
      position=
   }*/
   var xPos=Math.floor(document.body.clientWidth-elt.offsetWidth)/2+x_getScrollLeft(winObject);
   var yPos=Math.floor(document.body.clientHeight-elt.offsetHeight)/2+x_getScrollTop(winObject);
   elt.style.left=xPos+'px';
   elt.style.top=yPos+'px';
}