// twobirds AJAX lib V 2.5.0 Author: 2002- Frank Thuerigen / phpbuero.de

// namespace for lib, DO NOT CHANGE
var tb = function() {
 return {};
 }();

tb.timer=(function(){
 //private
 var myTimer=false;
 
 function d(pId){
  if ( !tb.timer.t[pId] ) return;
  clearTimeout( myTimer );
  tb.timer.t[pId].f=null;
  delete tb.timer.t[pId].f;
  tb.timer.t[pId]=null;
  delete tb.timer.t[pId];
  for ( var x in tb.timer.t) {
   myTimer = window.setTimeout( to, calcNext() );
   break;
   }
  }

 function a(pCb, pMs) {
  clearTimeout( myTimer );
  var myId=tb.misc.getid(),
      myT=pMs+(new Date()).getTime()
  tb.timer.t[myId]={ f: pCb, t: myT };
  myTimer = window.setTimeout( to, calcNext() );
  return myId;
  }

 function calcNext() {
  var myT = (new Date()).getTime();
  var myNext = 10000000 + myT;
  for ( var i in tb.timer.t ) {
   var myI = tb.timer.t[i];
   if ( myI.t && myNext > myI.t ) {
    myNext = myI.t;
    }
   }
  myNext = myNext - myT;
  return ( myNext<10 ? 10 : myNext );
  }

 function to(){
  for(var i in tb.timer.t){
   var myT=(new Date()).getTime();
   if(tb.timer.t[i].t<=myT){
    var myE=tb.timer.t[i].f;
    if ( !tb.timer.stopped ) {
     tb.misc.exec( myE );
     d(i);
     }
    }
   }
  for ( var x in tb.timer.t) {
   myTimer = window.setTimeout( to, calcNext() );
   break;
   }
  }

 return { // public 
  t: {},
  stopped: false,
  stop: function() {
   clearTimeout(myTimer);
   tb.timer.stopped = true;
   },
  start: function() {
   tb.timer.stopped = false;
   myTimer = window.setTimeout(timeout,0);
   },
  add: function(pCb, pMs){
   pCb = pCb || tb.misc.nop;
   pMs = pMs || 50;
   return a(pCb, pMs);
   },
  abort:function(pId){
   pId = pId ? d(pId) : null;
   }
  };
 })();

tb.interval=(function(){
 //private
 var myTimer = false;
 var myIndicator = 0;
 
 function d(pId){
  if ( !tb.interval.i[pId] ) return;
  tb.timer.abort( myTimer );
  if ( tb.interval.i[pId][4] === true ) {
   myIndicator--;
   if ( myIndicator < 1 ) {
    if ( document.getElementById( '_processing') ) { 
     document.getElementById( '_processing' ).style.visibility = 'hidden';
     }
    }
   }
  tb.interval.i[pId].cb = null;
  delete tb.interval.i[pId].cb;
  tb.interval.i[pId] = null;
  delete tb.interval.i[pId];
  
  for ( var x in tb.interval.i) {
   myTimer = tb.timer.add( 
    ito, 
    calcNext() 
    );
   break;
   }
  }

 function a(pCb, pMs, pTimeoutMs, pIn ) {
  tb.timer.abort( myTimer );
  var myId=tb.misc.getid(),
      myTime=(new Date()).getTime(),
      myT=myTime+pMs,
      myTo=( !isNaN( pTimeoutMs ) ? parseInt( pTimeoutMs / pMs ) : -1 );
  tb.interval.i[myId] = { cb: pCb, i: pMs, t: myT, to: myTo, b: pIn };
  if ( pIn === true ) { 
   myIndicator++;
   document.getElementById( '_processing' ).style.visibility = 'visible';  
   }
  myTimer = tb.timer.add( 
   ito, 
   calcNext()
   );
  return myId;
  }

 function calcNext() {
  var myT = (new Date()).getTime(),
      myNext = 10000000 + myT;
  for ( var i in tb.interval.i ) {
   if ( myNext > tb.interval.i[i].t ) {
    myNext = tb.interval.i[i].t;
    }
   }
  myNext = myNext - myT;
  return ( myNext<10 ? 10 : myNext );
  }
   
 function ito() {
  for ( var i in tb.interval.i ) {
   var myI = tb.interval.i[i],
       myT=(new Date()).getTime();
   if ( myI.to === 0 ) {
    d(i);
    }
   else if ( myI.to < myT ) {
    tb.interval.i[i].to = myT + myI.i;
    if ( myI.to !== -1 ) {
     tb.interval.i[i].to--;
     }
    if ( tb.interval.stopped !== true ) {
     tb.misc.exec( myI.cb );
     }
    }
   }
  for ( var x in tb.interval.i) {
   myTimer = tb.timer.add( 
    ito, 
    calcNext()
    );
   break;
   }
  }

 return { //public
  i: {},
  stopped: false,
  stop: function() {
   document.getElementById( '_processing' ).style.visibility = 'hidden';
   tb.interval.stopped = true;
   },
  start: function() {
   tb.interval.stopped = false;
   if ( myIndicator > 0 ) {
    if ( document.getElementById( '_processing') ) { 
     document.getElementById( '_processing' ).style.visibility = 'visible';
     }
    }
   for ( var x in tb.interval.i) {
    myTimer = tb.timer.add( 
     (function(){ return function(){ ito(); }})(), 
     10 
     );
    break;
    }
   },
  add: function(pCb, pMs, pTimeoutMs, pIn){
   pCb = pCb || tb.misc.nop;
   pMs = pMs || 10;
   pIn = ( pIn && pIn === true ? true : false );
   return a(pCb, pMs, pTimeoutMs, pIn);
   },
  abort: function(pId){
   pId = pId ? d(pId) : null;
   }
  };
 })();
 
tb.wait = (function(){

 function d(pId){
  if ( !tb.wait.w[pId] ) return;
  tb.wait.w[pId].cd = null;
  delete tb.wait.w[pId].cd;
  tb.wait.w[pId].cb = null;
  delete tb.wait.w[pId].cb;
  tb.wait.w[pId] = null;
  delete tb.wait.w[pId];
  }

 function a( pCd, pCb, pMs, pTimeoutMs, pIn ) {
  var myId = tb.misc.getid();
  
  tb.wait.w[myId] = { cd: pCd, cb: pCb, p: '', b: pIn };
  tb.wait.w[myId].p = tb.interval.add(
   function(){ wto(myId); },
   pMs,
   pTimeoutMs,
   pIn
   );
   
  return myId; 
  }
  
 function wto( pId ) {
  if ( !tb.wait.w[pId] ) return;
  var myW = tb.wait.w[pId],
      myI = myW.p,
      myT = (new Date()).getTime();
  //tb.log.add( 'wait cd... ');
  if ( tb.misc.test( myW.cd ) === true ) {
   //tb.log.add( 'wait cb... ');
   tb.interval.abort( myI );
   if ( tb.wait.stopped !== true ) {
    try {
     tb.misc.exec( myW.cb );
     d(pId);
     }
    catch (e) {
     }
    }
   }
  }

 return {
  // public
  w: {},
  stopped: false,
  stop: function() {
   tb.wait.stopped = true;
   },
  start: function() {
   tb.wait.stopped = false;
   },
  add: function( pCd, pCb, pMs, pTimeoutMs, pIn ) {
   pCd = pCd || 'true';
   pCb = pCb || tb.misc.nop;
   pMs = pMs || 10;
   pIn = ( pIn && pIn === true ? true : false );
   var r = a( pCd, pCb, pMs, pTimeoutMs, pIn );
   return r;
   },
  abort: function( pId ) {
   pId = pId ? d(pId) : null;
   }
  };
 })();

tb.observer = (function(){

 function d(pO){
  var myO=window,
      myA = (pO.i).split('~~~');
  myA.pop();
  myA = myA[0].split('~~');
  if ( myA[0].charAt(0) != '~' ) {
   while ( myA.length > 0 ){
    myO=myO[ myA.shift() ];
    }
   }
  else {
   try {
    myO = document.getElementById( myA[0].slice(1) );
    }
   catch (e) {
    return;
    }
   }
  if ( typeof pO.p != 'undefined' ) { // cancel a certain watched callback
   //tb.log.add( 'delete cb function: ( '+pO.p+' ) ');
   tb.observer.w[ pO.i ].c[pO.o][pO.p] = null;
   delete tb.observer.w[ pO.i ].c[pO.o][pO.p];
   if ( tb.misc.equals( {}, tb.observer.w[ pO.i ].c['once'] ) &&
        tb.misc.equals( {}, tb.observer.w[ pO.i ].c['cont'] ) ) {
    pO.p = null;
    delete pO.p;
    }
   }
  if ( typeof pO.p == 'undefined' ) { // unwatch object completely
   //tb.log.add( 'unwatch completely: ( '+pO.i+' ) ');
   if ( !tb.observer.w[pO.i] ) return;
   if ( typeof Object.prototype.watch == 'function' ) { // mozilla
    myO.unwatch( tb.observer.w[pO.i].e );
    }
   else {
    tb.wait.abort( tb.observer.w[pO.i].p );
    }
   tb.observer.w[pO.i] = null;
   delete tb.observer.w[pO.i];
   }
  }

 function a( pO, pE, pCb, pMs, pTimeoutMs, pOnce ){
  var myId = (( pO+'~~~'+pE ).replace( /\./g, '~~')).replace( /#/g, '~'),
      myOnce = ( ( typeof pOnce != 'undefined' && pOnce===false ) ? 'cont' : 'once' ),
      myO = window,
      myA = pO.split('.');
  if ( myA[0].charAt(0) !== '#' ) {
   while ( myA.length > 0 ){
    myO=myO[ myA.shift() ];
    }
   }
  else {
   try {
    myO = document.getElementById( myA[0].slice(1) );
    }
   catch (e) {
    return;
    }
   }
  var myOldVal = myO[pE];
  //tb.log.add( 'myO[pE] = '+myOldVal );
  if ( !tb.observer.w[ myId ] ) { // not yet observed
   tb.observer.w[ myId ] = {
    o: pO,
    e: pE,
    v: myOldVal,
    c: { once: {}, // once callbacks
      cont: {} // continued watch callbacks
      },
    p: 0 // will be wait ptr for non-mozilla browsers
    }; 
   if ( typeof Object.prototype.watch == 'function' && ( typeof pMs == 'undefined' || pMs === null ) ) { // mozilla
    //tb.log.add( 'mozilla watch() observer: ( '+(typeof(myO))+' ) '+pO+'.'+pE+' = '+myO[pE] );
    myO.watch( 
     pE, 
     function( pId, pOld, pNew ){ myO[pId]=pNew; tb.observer.notify( myId ); return pNew; } 
     );
    }
   else { // other browsers
    //tb.log.add( 'tb.wait observer: ' + pMs );
    tb.observer.w[ myId ].p = tb.wait.add(
     function(){ return ( tb.misc.equals( tb.observer.w[ myId ].v, myO[tb.observer.w[ myId ].e] ) === false ? true : false ); },
     function(){ tb.timer.add( function(){ tb.observer.notify( myId ); } ); },
     pMs,
     pTimeoutMs
     );
    }
   }
  var myCbId = tb.misc.getid();
  tb.observer.w[ myId ].c[myOnce][ myCbId ] = pCb; 
  var r = { "i": myId, "o": myOnce, "p": myCbId };
  if ( typeof Object.prototype.watch == 'function' && pTimeoutMs && !isNaN( pTimeoutMs ) ) { // mozilla
   //tb.log.add( 'tb.wait observer: timeout = ' + pTimeoutMs );
   var f=(function(){ var myR=r; return function(){ tb.observer.unobserve( myR ); } })();
   tb.timer.add( f, pTimeoutMs );
   }
  //tb.log.add( 'tb.wait observer: return = ' + (tb.misc.enumerate( r )).join(';') );
  return r;
  }
  
 return {
  w: {},
  observe: function( pO, pE, pCb, pMs, pTimeoutMs, pOnce ) {
   if ( !pO || !pE || !pCb ) return false;
   if ( typeof pOnce == 'undefined' || pOnce !== false ) {
    pOnce=true;
    }
   return a( pO, pE, pCb, pMs, pTimeoutMs, pOnce );
   },
  unobserve: function( pO ) {
   d(pO);
   },
  notify: function( pId ) {
   //tb.log.add( ' notify starts: '+pId );
   if ( !tb.observer.w[ pId ] ) return;
   for (var i in tb.observer.w[ pId ].c['once']) {
    //tb.log.add( ' notify once cb-s ('+(typeof tb.observer.w[ pId ].c['once'][i])+') '+i+' execute.' );
    tb.observer.w[ pId ].c['once'][i]();
    tb.observer.w[ pId ].c['once'][i] = null;
    delete tb.observer.w[ pId ].c['once'][i];
    //tb.log.add( ' deleted '+i );
    }
   for (var i in tb.observer.w[ pId ].c['cont']) {
    //tb.log.add( ' notify cont cb-s '+i );
    tb.observer.w[ pId ].c['cont'][i]();
    }
   if ( tb.misc.equals( {}, tb.observer.w[ pId ].c['cont'] )===true ) {
    d( { "i": pId } );
    } 
   }
  }
 })();
 
tb.cache = (function(){
 //private
 function d( pId ) {
  tb.cache.c[pId] = null;
  delete tb.cache.c[pId];
  }

 function a( pWhat ) {
  var myId=tb.misc.getid();
  tb.cache.c[myId] = [ pWhat ];
  return myId;
  }

 // public
 return {
  c: {}, 
  set: function ( pId, pContent ) {
   if ( pId ) {
    tb.cache.c[pId] = pContent;
    }
   else {
    return a( pContent );
    }
   },
  get: function ( pId ) {
   return tb.cache.c[pId] || false ;
   },
  extract: function ( pId ) {
   var r = tb.cache.c[pId];
   pId = pId ? d(pId) : null;
   return r || false;
   }
  };
 })();

tb.misc = (function(){
 //private
 function cl( pObj ) {
  var myObj = {};
  for ( var i in pObj ) {
   myObj[i] = pObj[i];
   }
  return myObj;
  }

 return { // public

  nop: function() {
   },

  wait: function ( pCondition, pCallback, pFrequency ) { // compatibility function
   if ( isNaN( pFrequency ) === true ) {
    pFrequency = 100;
    }
   var myResult = ( pCondition 
    ? ( typeof pCondition == 'string' 
        ? eval( pCondition )
        : ( typeof pCondition == 'function'
            ? pCondition()
            : true
          )
      )
    : true
    )
   if ( myResult === false ) {
    var myToFunction = function() { tb.misc.wait( pCondition, pCallback, pFrequency ); };
    tb.timer.add( myToFunction, pFrequency );
    }
   else {
    ( pCallback 
    ? ( typeof pCallback == 'string' 
        ? eval( pCallback )
        : ( typeof pCallback == 'function'
            ? pCallback()
            : true
          )
      )
    : true
    )
    }
   },
  
  purge: function(d) { // thx doug crockford
   //tb.log.add( 'purge' )
   var a = d.attributes, i, l, n;
   if (a) {
    //tb.log.add( 'purge a' )
    l = a.length;
    for (i = 0; i < l; i += 1) {
     n = a[i].name;
     if (typeof d[n] === 'function') {
      d[n] = null; // donīt DELETE it - IE master fup.
      }
     }
    //tb.log.add( 'purge a ( '+i+' elements )' )
    }
   a = d.childNodes;
   if (a) {
    //tb.log.add( 'purge a_children' )
    l = a.length;
    for (i = 0; i < l; i += 1) {
     tb.misc.purge(d.childNodes[i]);
     }
    }
   },

  enumerate: function( pObj ) {
   if ( pObj && typeof pObj == 'object') {
    var myArray = [];
    for ( var i in pObj ) {
     if ( pObj.hasOwnProperty(i) ) {
      myArray.push( [ i, pObj[i] ] );
      }
     }
    return myArray;
    }
   },
 
  propcount: function( pObj ) {
   if ( pObj && typeof pObj == 'object') {
    var j = 0;
    for ( var i in pObj ) {
     if ( pObj.hasOwnProperty(i) ) {
      j++;
      }
     }
    return j;
    }
   },
 
  equals: function(pA, pB){
   var ret=true, 
       i, 
       j=0;
   if ( typeof pA != 'undefined' && typeof pB != 'undefined' ) {
    if ( typeof pA != typeof pB ) return false;
    switch ( typeof pA ) {
     case 'object':
      if ( tb.misc.propcount( pA ) === tb.misc.propcount( pB ) ) {
       for ( j in pA ) {
        if ( !pB[j] ) {
         return false;
         }
        else {
         ret=( ret===false ? false : tb.misc.equals( pA[j], pB[j] ) );
         if ( ret===false ) return false;
         }
        }
       }
      else {
       return false;
       }
      break;
     case 'array':
      i = pA.length;
      while ( ret===true && j < i ) {
       ret=tb.misc.equals( pA[j], pB[j] );
       if ( ret===false ) return false;
       j++;
       }
      break;
     default:
      if ( typeof pA != typeof pB ) return false;
      ret=( ( pA || 'undefined' ) !== ( pB || 'undefined' ) ? false : true );
      break;
     }
    }
   return ret;
   },

  clone: function( pObj ) {
   cl( pObj );
   },
  
  cloneObj: function( pObj ) { // compatibility function
   cl( pObj );
   },
  
  getid: function() {
   var myDate = new Date();
   return '_'+myDate.getTime()+'_'+Math.random().toString().replace( /\./, '');
   },

  instance: function( pParent, pChild ) {
   var c = new Function();
   c.prototype = pChild;
   var p = new c();
   p.prototype = pParent;
   return p;
   },

  test: function( pCd ) {
   if ( typeof pCd != 'undefined' ) {
    if ( typeof pCd == 'function' ) {
     try { 
      var r = pCd();
      pCd = null;
      delete pCd;
      }
     catch(e){
      }
     return r;
     }
    else if ( typeof pCd == 'string' && pCd.length > 0 ) {
     try{
      var r = eval( '( '+pCd+' )' );
      }
     catch (e) {
      }
     return r;
     }
    }
   },

  exec: function( pCb ) {
   if ( typeof pCb != 'undefined' ) {
    if ( typeof pCb == 'function' ) {
     try { 
      pCb(); 
      pCb = null;
      delete pCb;
      }
     catch(e){
      }
     }
    else if ( typeof pCb == 'string' && pCb.length > 0 ) {
     try{
      var r = eval( '(function(){ '+pCb+'; })()' );
      }
     catch (e) {
      }
     }
    }
   }
  }
 })();

tb.request = (function(){
 // private
 var count=0,
     interval=30,
     msoft=[ 'MSXML2.XMLHTTP.5.0', 'MSXML2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP' ];
 
 function addhandler( pId, pCb ) {
  tb.cache.set( pId, pCb );
  }
  
 function getConnection( pId ) {
  var myObj = {};
  var myHttp;
  try {
   myHttp = new XMLHttpRequest();
   myObj = { connection:myHttp, identifier:pId };
   }
  catch(e) {
   for(var i=0; i<msoft.length; ++i){
    try {
     myHttp = new ActiveXObject( msoft[i] );
     myObj = { connection:myHttp, identifier:pId };
     }
    catch(e){
     }
    }
   }
  finally {
   return myObj;
   }
  }
 
 function handlereadystate( pReq, pCallback, pStateChange, pFailure ) {
  var myConnection = this;
  var myReq = pReq;
  var myPoll = tb.interval.add(
   (function(){
    var myreadystate=0;
    return function(){
     if ( myReq.connection.readyState !== myreadystate ) {
      myreadystate = myReq.connection.readyState;
      pStateChange();
      }
     if( myReq.connection.readyState==4 ){
      handleTransactionResponse( pReq, pCallback, pFailure );
      tb.interval.abort( myPoll );
      }
     };
    })(),
   tb.request.interval 
   );
  }

 function handleTransactionResponse( pReq, pCallback, pFailure ) {
  try{
   var httpStatus = pReq.connection.status;
   }
  catch(e){
   var httpStatus = 13030;
   }
  if( httpStatus >= 200 && httpStatus < 300 ){
   var responseObject = createResponseObject( pReq, pCallback.argument);
   try {
    pCallback.apply(pCallback, [responseObject.responseXml, responseObject.responseText, responseObject]);
    }
   catch (e) {
    }
   }
  else {
   pFailure(); 
   }
  release(pReq);
  }

 function createResponseObject(pObj, pCallbackArg) {
  var myObj = {};
  myObj.tId = pObj.identifier;
  myObj.status = pObj.connection.status;
  myObj.statusText = pObj.connection.statusText;
  myObj.allResponseHeaders = pObj.connection.getAllResponseHeaders();
  myObj.responseText = pObj.connection.responseText;
  myObj.responseXML = pObj.connection.responseXML;
  if(pCallbackArg){
   myObj.argument = pCallbackArg;
   }
  return myObj;
  }

 function release( pReq ) {
  tb.request.dec();
  pReq.connection = null;
  delete pReq.connection;
  pReq = null;
  delete pReq;
  }  

 return { // public
  cachable: false,
  
  inc: function(){
   count += 1;
   if ( document.getElementById( '_loading') ) { 
    document.getElementById( '_loading' ).style.visibility = 'visible';
    }
   },

  dec: function(){
   count -= 1;
   if ( count < 1) {
    if ( document.getElementById( '_loading' ) ) {
     document.getElementById( '_loading' ).style.visibility = 'hidden';
     }
    }
   },
 
  add: function ( pOptions ) {
   var myIndex = tb.misc.getid(),
       myUid = 'tb'+myIndex,
       myXmlreq = false,
       myMethod = ( pOptions.method ? pOptions.method.toUpperCase() : false ) || 'POST',
       myUrl = pOptions.url,
       myParms = '';
       
   for ( var i in pOptions.parms ) { // concat parameter string
    myParms += ( ( myParms.length > 0 ? '&' : '' ) + i + '=' + pOptions.parms[i] );
    }
      
   var myResponseXmlHandler = pOptions.success || tb.misc.nop,
       myFailureHandler = pOptions.failure || tb.misc.nop,
       myStateHandler = pOptions.statechange || tb.misc.nop,
       myIsCachable = pOptions.cachable  || false,
       myIsAsync = pOptions.async || true;
   
   tb.request.inc();

   if ( myIsCachable === false ) { // proxy disable
    if ( myUrl.indexOf( '/?/' ) > -1 ) { // its a CakePHP service, POST only.
     myMethod = 'POST';
     if ( myParms === null || myParms === '') {
      myParms = 'tbUid='+myUid;
      }
     else { // parms given
      myParms = myParms+'&tbUid='+myUid;
      }
     }
    else {
     myUrl += ( myUrl.indexOf('?') < 0 ? '?' : '&' ) +'tbUid='+myUid;
     }
    }
   
   myXmlreq = getConnection( myUid );
   if ( myXmlreq ) {
    if ( myMethod == 'GET' && myParms !== '' ) {
     myUrl = myUrl + '&' + myParms;
     }
    if ( myMethod == 'POST' ) {
     myXmlreq.connection.open('POST', myUrl, myIsAsync);
     }
    else {
     myXmlreq.connection.open('GET', myUrl, myIsAsync);
     } 
    if ( myIsAsync === true ) {
     handlereadystate( myXmlreq, myResponseXmlHandler, myStateHandler, myFailureHandler, myUrl);
     }
    if ( myMethod == 'POST' ) {
     if ( myParms !== '' ) {
      myXmlreq.connection.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
      myXmlreq.connection.send(myParms);
      }
     else {
      myXmlreq.connection.send(null);
      }
     }
    else {
     myXmlreq.connection.send(null);
     }
    if ( myIsAsync === false ) {
     tb.request.dec();
     if ( myXmlreq.connection.status >= 200 && myXmlreq.connection.status < 300 ) {
      myResponseXmlHandler( myXmlreq.connection.responseXML, myXmlreq.connection.responseText);
      }
     else {
      myFailureHandler();
      }
     }
    if ( myMethod == 'POST' ) {
     return myXmlreq;
     }
    else {
     return null;
     }
    }
   else {
    return false;
    }
   },
   
  abort: function( pReq ) {
   release( pReq );
   }
  };   
 })();