/*
  galaxy helper functions
  2007-01-31 (mca) - initial load from DOMhelp.js
  2007-02-02 (mca) - added cookie & qs functions, renamed to galaxy
  2008-02-06 (mca) - added sessionTimer object
*/
galaxy={
  debugWindowId:'galaxydebug',
  init:function(){
    if(!document.getElementById || !document.createTextNode){return;}
  },
  lastSibling:function(node){
    var tempObj=node.parentNode.lastChild;
    while(tempObj.nodeType!=1 && tempObj.previousSibling!=null){
      tempObj=tempObj.previousSibling;
    }
    return (tempObj.nodeType==1)?tempObj:false;
  },
  firstSibling:function(node){
    var tempObj=node.parentNode.firstChild;
    while(tempObj.nodeType!=1 && tempObj.nextSibling!=null){
      tempObj=tempObj.nextSibling;
    }
    return (tempObj.nodeType==1)?tempObj:false;
  },
  getText:function(node){
    if(!node.hasChildNodes()){return false;}
    var reg=/^\s+$/;
    var tempObj=node.firstChild;
    while(tempObj.nodeType!=3 && tempObj.nextSibling!=null || reg.test(tempObj.nodeValue)){
      tempObj=tempObj.nextSibling;
    }
    return tempObj.nodeType==3?tempObj.nodeValue:false;
  },
  setText:function(node,txt){
    if(!node.hasChildNodes()){return false;}
    var reg=/^\s+$/;
    var tempObj=node.firstChild;
    while(tempObj.nodeType!=3 && tempObj.nextSibling!=null || reg.test(tempObj.nodeValue)){
      tempObj=tempObj.nextSibling;
    }
    if(tempObj.nodeType==3){tempObj.nodeValue=txt}else{return false;}
  },
  createLink:function(to,txt){
    var tempObj=document.createElement('a');
    tempObj.appendChild(document.createTextNode(txt));
    tempObj.setAttribute('href',to);
    return tempObj;
  },
  createTextElm:function(elm,txt){
    var tempObj=document.createElement(elm);
    tempObj.appendChild(document.createTextNode(txt));
    return tempObj;
  },
  closestSibling:function(node,direction){
    var tempObj;
    if(direction==-1 && node.previousSibling!=null){
      tempObj=node.previousSibling;
      while(tempObj.nodeType!=1 && tempObj.previousSibling!=null){
         tempObj=tempObj.previousSibling;
      }
    }else if(direction==1 && node.nextSibling!=null){
      tempObj=node.nextSibling;
      while(tempObj.nodeType!=1 && tempObj.nextSibling!=null){
         tempObj=tempObj.nextSibling;
      }
    }
    return tempObj.nodeType==1?tempObj:false;
  },
  initDebug:function(){
    if(galaxy.debug){galaxy.stopDebug();}
    galaxy.debug=document.createElement('div');
    galaxy.debug.setAttribute('id',galaxy.debugWindowId);
    document.body.insertBefore(galaxy.debug,document.body.firstChild);
  },
  setDebug:function(bug){
    if(!galaxy.debug){galaxy.initDebug();}
    galaxy.debug.innerHTML+=bug+'\n';
  },
  stopDebug:function(){
    if(galaxy.debug){
      galaxy.debug.parentNode.removeChild(galaxy.debug);
      galaxy.debug=null;
    }
  },
  getKey:function(e){
    if(window.event){
        var key = window.event.keyCode;
      } else if(e){
        var key=e.keyCode;
      }
    return key;
  },
    /* helper methods */
  getTarget:function(e){
    var target = window.event ? window.event.srcElement : e ? e.target : null;
    if (!target){return false;}
    while(target.nodeType!=1 && target.nodeName.toLowerCase()!='body'){
      target=target.parentNode;
    }
    return target;
  },
  stopBubble:function(e){
    if(window.event && window.event.cancelBubble){
      window.event.cancelBubble = true;
    } 
    if (e && e.stopPropagation){
      e.stopPropagation();
    }
  },
  stopDefault:function(e){
    if(window.event && window.event.returnValue){
      window.event.returnValue = false;
    } 
    if (e && e.preventDefault){
      e.preventDefault();
    }
  },
  cancelClick:function(e){
    if (window.event && window.event.cancelBubble 
        && window.event.returnValue){
      window.event.cancelBubble = true;
      window.event.returnValue = false;
      return;
    }
    if (e && e.stopPropagation && e.preventDefault){
      e.stopPropagation();
      e.preventDefault();
    }
  },
  addEvent: function(elm, evType, fn, useCapture){
    if (elm.addEventListener){
      elm.addEventListener(evType, fn, useCapture);
      return true;
    } else if (elm.attachEvent) {
      var r = elm.attachEvent('on' + evType, fn);
      return r;
    } else {
      elm['on' + evType] = fn;
    }
  },
  /* added by mca 2009-06-02 */
  removeEvent: function( obj, type, fn )
  {
    if (obj.removeEventListener)
    {
      obj.removeEventListener( type, fn, false );
    }
    else if (obj.detachEvent)
    {
      obj.detachEvent( "on"+type, obj[type+fn] );
      obj[type+fn] = null;
      obj["e"+type+fn] = null;
    }
  },
  /* added by mca 2009-06-02 */

  cssjs:function(a,o,c1,c2){
    switch (a){
      case 'swap':
        o.className=!galaxy.cssjs('check',o,c1)?o.className.replace(c2,c1):o.className.replace(c1,c2);
      break;
      case 'add':
        if(!galaxy.cssjs('check',o,c1)){o.className+=o.className?' '+c1:c1;}
      break;
      case 'remove':
        var rep=o.className.match(' '+c1)?' '+c1:c1;
        o.className=o.className.replace(rep,'');
      break;
      case 'check':
        var found=false;
        var temparray=o.className.split(' ');
        for(var i=0;i<temparray.length;i++){
          if(temparray[i]==c1){found=true;}
        }
        return found;
      break;
    }
  },
    safariClickFix:function(){
      return false;
    },
    
    /* 2007-02-02 (mca) : simple cookie stuff */
    createCookie:function(name,value,days){
        if (days) {
          var date = new Date();
          date.setTime(date.getTime()+(days*24*60*60*1000));
          var expires = "; expires="+date.toGMTString();
        }
        else var expires = "";
        document.cookie = name+"="+value+expires+"; path=/";
    },
    readCookie:function(name){
        var nameEQ = name + "=";
        var ca = document.cookie.split(';');
        for(var i=0;i < ca.length;i++) {
          var c = ca[i];
          while (c.charAt(0)==' ') c = c.substring(1,c.length);
          if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
        }
        return null;
    },
    eraseCookie:function(name){
      galaxy.createCookie(name,"",-1);
    },

    getRtnLink:function()
    {
      var srch,id,rex,match;
      
      srch = location.search;
      rex = /\?_rtnlink=(.*)/i;
      match = rex.exec(srch);
      if (match != null)
      {
        id=match[1];
      }
      else
      {
        rex = /\&_rtnlink=(.*)/i;
        match = rex.exec(srch);
        if (match != null)
        {
          id=match[1];
        }
        else
        {
          id='';
        }
      }
  
      return id;
      
    },
  
    
    /* 2007-02-02 (mca) : read values from the querystring into an array */
    getQSArgs:function()
    {
        var qsParm = new Array();
        var query = window.location.search.substring(1);
        var parms = query.split('&');
        for (var i=0; i<parms.length; i++) 
        {
            var pos = parms[i].indexOf('=');
            if (pos > 0) 
            {
                var key = parms[i].substring(0,pos);
                var val = parms[i].substring(pos+1);
                qsParm[key] = val;
            }
        }
        return qsParm;
    },
    
    /* 2007-02-20 (mca) : prepare a 'post-able' bucket from elements or object array */
    serialize:function(a)
  {
      var s = [];
      if(
          a.constructor == Array 
          || 
          (a[0].tagName=='INPUT' || a[0].tagName=='SELECT' || a[0].tagName=='TEXTAREA')
        )
      {
          for(var i=0;i<a.length;i++)
          {
              if(a[i].name && a[i].name.length!=0)
              {
                  // handle checkbox
                  if(a[i].type && a[i].type=='checkbox')
                  {
                      if(a[i].checked==true)
                          s.push(a[i].name + '=' + encodeURIComponent(a[i].value));
                        continue;
                  }
                  
                  // handle radio
                  if(a[i].type && a[i].type=='radio')
                  {
                      if(a[i].selected==true)
                          s.push(a[i].name + '=' + encodeURIComponent(a[i].value));
                        continue;
                  }
                  
                  // handle all others
                  s.push(a[i].name + '=' + encodeURIComponent(a[i].value));
              }
          }
      }
      else
      {
          for(var j in a)
              s.push(j+'='+encodeURIComponent(a[j]));
      }
      
      return s.join("&");
    },
  
    trim:function(data)
    {
        if(data!=null)
        {
          var a = data.replace(/^\s+/, '');
          return a.replace(/\s+$/, '');
        }
        else
        {
          return data;
        }
    },

    convertToShortName:function(data)
    {
        var a = data.toLowerCase();
        a = a.replace(/^\s+/, '');
        a = a.replace(/\s+$/, '');
        a = a.replace(' ','-',"g");
        return a;
    },

    escapeHTML:function(str)
    {
       var div = document.createElement('div');
       var text = document.createTextNode(str);
       div.appendChild(text);
       return div.innerHTML;
    },

    unescapeHTML:function(text)
    {
      var elm = document.createElement('div');
      elm.innerHTML = text;
      if(elm.innerText)
      {
        text = elm.innerText; // IE
      }
      else
      {
       text =  elm.textContent; // FF    
      }
      
      return text;
    },
    
    fixEntities:function(text)
    {
        //text = text.replace(/&amp;nbsp;/,"&#160;");
        //text = text.replace(/&nbsp;/,"&#160;");
        return text;
    },
    
    checkDate:function(element,required)
    {
        var val;
        
        // empty field and not required?
        if(required==false && element.value=='')
            return;
            
        val = galaxy.parseDate(element.value);
        if(val=='')
        {
            alert('Invalid Date! ['+element.value+']')
            galaxy.setfocus(element);
        }
        else
            element.value=val;
    },

    parseDate:function(val)
    {
        var dt,yr,mo,dy,rtn;
        
        try
        {
            // test for standard us format
            if(galaxy.isValidDate(val,'MDY'))
            {
                dt = new Date(val);
            }
            else
            {
                // test for universal format
                if(galaxy.isValidDate(val,'YMD'))
                {
                    // if yes, convert to us format
                    var nd = (val.indexOf('-')!=-1?val.split('-'):val.split('/'));
                    dt = new Date(nd[1]+'/'+nd[2]+'/'+nd[0]);
                }
                else
                    dt = null;
            }
            
            // if valid date, return universal string
            if(dt!=null)
            {
                yr = dt.getFullYear();
                mo = dt.getMonth();
                mo = mo+1;
                dy = dt.getDate();
                rtn = yr+'-'+(mo>9?mo:'0'+mo)+'-'+(dy>9?dy:'0'+dy);
            }
            else
                rtn = '';
        }
        catch(ex)
        {
            alert(ex.message);
            rtn = '';
        }
        
        return rtn;
    }, 
  
  isValidDate:function(dateStr, format) 
  {
       if (format == null) { format = "MDY"; }
       format = format.toUpperCase();
       if (format.length != 3) { format = "MDY"; }
       if ( (format.indexOf("M") == -1) || (format.indexOf("D") == -1) || (format.indexOf("Y") == -1) ) { format = "MDY"; }
       if (format.substring(0, 1) == "Y") { // If the year is first
          var reg1 = /^\d{2}(\-|\/|\.)\d{1,2}\1\d{1,2}$/
          var reg2 = /^\d{4}(\-|\/|\.)\d{1,2}\1\d{1,2}$/
       } else if (format.substring(1, 2) == "Y") { // If the year is second
          var reg1 = /^\d{1,2}(\-|\/|\.)\d{2}\1\d{1,2}$/
          var reg2 = /^\d{1,2}(\-|\/|\.)\d{4}\1\d{1,2}$/
       } else { // The year must be third
          var reg1 = /^\d{1,2}(\-|\/|\.)\d{1,2}\1\d{2}$/
          var reg2 = /^\d{1,2}(\-|\/|\.)\d{1,2}\1\d{4}$/
       }
       // If it doesn't conform to the right format (with either a 2 digit year or 4 digit year), fail
       if ( (reg1.test(dateStr) == false) && (reg2.test(dateStr) == false) ) { return false; }
       var parts = dateStr.split(RegExp.$1); // Split into 3 parts based on what the divider was
       // Check to see if the 3 parts end up making a valid date
       if (format.substring(0, 1) == "M") { var mm = parts[0]; } else 
          if (format.substring(1, 2) == "M") { var mm = parts[1]; } else { var mm = parts[2]; }
       if (format.substring(0, 1) == "D") { var dd = parts[0]; } else 
          if (format.substring(1, 2) == "D") { var dd = parts[1]; } else { var dd = parts[2]; }
       if (format.substring(0, 1) == "Y") { var yy = parts[0]; } else 
          if (format.substring(1, 2) == "Y") { var yy = parts[1]; } else { var yy = parts[2]; }
       if (parseFloat(yy) <= 50) { yy = (parseFloat(yy) + 2000).toString(); }
       if (parseFloat(yy) <= 99) { yy = (parseFloat(yy) + 1900).toString(); }
       var dt = new Date(parseFloat(yy), parseFloat(mm)-1, parseFloat(dd), 0, 0, 0, 0);
       if (parseFloat(dd) != dt.getDate()) { return false; }
       if (parseFloat(mm)-1 != dt.getMonth()) { return false; }
       return true;
    },
    
    inputField:null,
    
    setFocusDelayed:function()
    {
        galaxy.inputField.focus();
        galaxy.inputField.select();
    },

    setfocus:function(fld)
    {
        // save valfield in global variable so value retained when routine exits
        galaxy.inputField = fld;
        setTimeout( 'galaxy.setFocusDelayed()', 100 );
    },
    
    shortenPath:function(path, len)
    {
        var rtn;
        
        if (len == null) 
            len = 75;
        
        if(path.length>len)
        {
            var nodes = path.split('/');
            if(nodes.length<=3)
                rtn = path;
            else
                rtn = './'+nodes[1]+'./'+nodes[nodes.length-1];
        }
        else
            rtn = path;
            
        if(rtn>len)
        {
          rtn = rtn.substring(rtn,1,len-3)+'...';
        }
        return rtn;
    },
    
    validateRegExp:function(value,regex)
    {
      try
      {
        var rex = new RegExp(regex);
        if(rex){
          return rex.test(value);
        } else {
          return true;
        }
      } catch(ex) {
        return true;
      }
    },
    
    findPos:function (obj) {
      var curleft = curtop = 0;
      if (obj.offsetParent) {
        curleft = obj.offsetLeft;
        curtop = obj.offsetTop;
        while (obj = obj.offsetParent) {
          curleft += obj.offsetLeft;
          curtop += obj.offsetTop;
        }
      }
      return [curleft,curtop];
    },
    
    // replace placeholders w/
    // windows.location data
    resolveLocation : function (data)
    {
      var re,attr;
      attr = 'gim';
      
      re = new RegExp('{fragment}',attr);
      data = data.replace(re,location.hash);
    
      re = new RegExp('{host}',attr);
      data = data.replace(re,location.host);
    
      re = new RegExp('{hostname}',attr);
      data = data.replace(re,location.hostname);
    
      re = new RegExp('{url}',attr);
      data = data.replace(re,location.href);
    
      re = new RegExp('{path}',attr);
      data = data.replace(re,location.pathname);
    
      re = new RegExp('{port}',attr);
      data = data.replace(re,location.port);
    
      re = new RegExp('{scheme}',attr);
      data = data.replace(re,location.protocol);
    
      re = new RegExp('{query}',attr);
      data = data.replace(re,location.search);
      
      re = new RegExp('{page}',attr)
      data = data.replace(re,location.pathname.substring(location.pathname.lastIndexOf('/')+1));
    
      re = new RegExp('{path-only}',attr)
      data = data.replace(re,location.pathname.substring(0,location.pathname.lastIndexOf('/')+1));
      
      return data;
    },

    getElementsByClassName : function(className, tag, elm)
    {
      var testClass = new RegExp("(^|\\s)" + className + "(\\s|$)");
      var tag = tag || "*";
      var elm = elm || document;
      var elements = (tag == "*" && elm.all)? elm.all : elm.getElementsByTagName(tag);
      var returnElements = [];
      var current;
      var length = elements.length;
      for(var i=0; i<length; i++){
        current = elements[i];
        if(testClass.test(current.className)){
          returnElements.push(current);
        }
      }
      return returnElements;
    }
};
galaxy.addEvent(window, 'load', galaxy.init, false);


if(!document.getElementsByClassName)
{
  document.getElementsByClassName = function(className, tag, elm)
  {
    var testClass = new RegExp("(^|\\s)" + className + "(\\s|$)");
    var tag = tag || "*";
    var elm = elm || document;
    var elements = (tag == "*" && elm.all)? elm.all : elm.getElementsByTagName(tag);
    var returnElements = [];
    var current;
    var length = elements.length;
    for(var i=0; i<length; i++){
      current = elements[i];
      if(testClass.test(current.className)){
        returnElements.push(current);
      }
    }
    return returnElements;
  };
}

if(!document.getElementsByNameEx)
{
  document.getElementsByNameEx = function(name, tag, elm)
  {
    var tag = tag || "*";
    var elm = elm || document;
    var elements = (tag == "*" && elm.all)? elm.all : elm.getElementsByTagName(tag);
    var returnElements = [];
    var current;
    var length = elements.length;
    for(var i=0; i<length; i++){
      current = elements[i];
      if(current.getAttribute('name')==name){
        returnElements.push(current);
      }
    }
    return returnElements;
  };
}

// define galaxy error collection
function getGalaxyError(msg)
{
    var rtn;
    
    switch (msg.toLowerCase())
    {
        case 'server error':
            rtn = 'Unexpected server error';
            break;
        case 'forbidden':
            rtn = 'Access denied.';
        default:
            rtn = msg;
            break;    
    }
    
    return 'GalaxyError: '+rtn;
}

// 2007-11-15  (mca)
function HashTable()
{
  this.length = 0;
  this.items = new Array();
  for (var i = 0; i < arguments.length; i += 2) {
    if (typeof(arguments[i + 1]) != 'undefined') {
      this.items[arguments[i]] = arguments[i + 1];
      this.length++;
    }
  }
   
  this.removeItem = function(in_key)
  {
    var tmp_value;
    if (typeof(this.items[in_key]) != 'undefined') {
      this.length--;
      var tmp_value = this.items[in_key];
      delete this.items[in_key];
    }
     
    return tmp_value;
  }

  this.getItem = function(in_key) {
    return this.items[in_key];
  }

  this.setItem = function(in_key, in_value)
  {
    if (typeof(in_value) != 'undefined') {
      if (typeof(this.items[in_key]) == 'undefined') {
        this.length++;
      }

      this.items[in_key] = in_value;
    }
     
    return in_value;
  }

  this.hasItem = function(in_key)
  {
    return typeof(this.items[in_key]) != 'undefined';
  }
}

// Initializes a new instance of the StringBuilder class
// and appends the given value if supplied
// 2007-11-17 (mca)
function StringBuilder(value)
{
    this.strings = new Array("");
    this.append(value);
}

// Appends the given value to the end of this instance.
StringBuilder.prototype.append = function (value)
{
    if (value)
    {
        this.strings.push(value);
    }
}

// Clears the string buffer
StringBuilder.prototype.clear = function ()
{
    this.strings.length = 1;
}

// Converts this instance to a String.
StringBuilder.prototype.toString = function ()
{
    return this.strings.join("");
}


// ====================================================================
//       URLEncode and URLDecode functions
//
// Copyright Albion Research Ltd. 2002
// http://www.albionresearch.com/
//
// You may copy these functions providing that 
// (a) you leave this copyright notice intact, and 
// (b) if you use these functions on a publicly accessible
//     web site you include a credit somewhere on the web site 
//     with a link back to http://www.albionresearch.com/
//
// If you find or fix any bugs, please let us know at albionresearch.com
//
// SpecialThanks to Neelesh Thakur for being the first to
// report a bug in URLDecode() - now fixed 2003-02-19.
// And thanks to everyone else who has provided comments and suggestions.
// ====================================================================
function URLEncode( plaintext )
{
  // The Javascript escape and unescape functions do not correspond
  // with what browsers actually do...
  var SAFECHARS = "0123456789" +          // Numeric
          "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +  // Alphabetic
          "abcdefghijklmnopqrstuvwxyz" +
          "-_.!~_2A'()";          // RFC2396 Mark characters
  var HEX = "0123456789ABCDEF";

  //var plaintext = document.URLForm.F1.value;
  var encoded = "";
  for (var i = 0; i < plaintext.length; i++ ) {
    var ch = plaintext.charAt(i);
      if (ch == " ") {
        encoded += "+";       // x-www-urlencoded, rather than %20
    } else if (SAFECHARS.indexOf(ch) != -1) {
        encoded += ch;
    } else {
        var charCode = ch.charCodeAt(0);
      if (charCode > 255) {
          alert( "Unicode Character '" 
                        + ch 
                        + "' cannot be encoded using standard URL encoding.\n" +
                  "(URL encoding only supports 8-bit characters.)\n" +
              "A space (+) will be substituted." );
        encoded += "+";
      } else {
        encoded += "%";
        encoded += HEX.charAt((charCode >> 4) & 0xF);
        encoded += HEX.charAt(charCode & 0xF);
      }
    }
  } // for

  //document.URLForm.F2.value = encoded;
  return encoded;
};

function URLDecode( encoded )
{
   // Replace + with ' '
   // Replace %xx with equivalent character
   // Put [ERROR] in output if %xx is invalid.
   var HEXCHARS = "0123456789ABCDEFabcdef"; 
   //var encoded = document.URLForm.F2.value;
   var plaintext = "";
   var i = 0;
   while (i < encoded.length) {
       var ch = encoded.charAt(i);
     if (ch == "+") {
         plaintext += " ";
       i++;
     } else if (ch == "%") {
      if (i < (encoded.length-2) 
          && HEXCHARS.indexOf(encoded.charAt(i+1)) != -1 
          && HEXCHARS.indexOf(encoded.charAt(i+2)) != -1 ) {
        plaintext += unescape( encoded.substr(i,3) );
        i += 3;
      } else {
        alert( 'Bad escape combination near ...' + encoded.substr(i) );
        plaintext += "%[ERROR]";
        i++;
      }
    } else {
       plaintext += ch;
       i++;
    }
  } // while
   //document.URLForm.F1.value = plaintext;
   return plaintext;
};

var screenManager =
{
  updateScreen: function(prompts)
  {
    var i,j,p,r,p_elms,v_elms;

    for (p in prompts)
    {
      p_elms = galaxy.getElementsByClassName(p)
      if(p_elms)
      {
        for(i=0;i<p_elms.length;i++)
        {
          if(prompts[p]!='')
          {
            if(p.indexOf('button')!=-1)
            {
              p_elms[i].value = prompts[p];
            }
            else
            {
              p_elms[i].innerHTML = prompts[p];
            }
          }
          else
          {
            v_elms = galaxy.getElementsByClassName(p.replace('-prompt',''))
            if(v_elms)
            {
              for(j=0;j<v_elms.length;j++)
              {
                v_elms[j].style.display='none';
              }
            }
          }
        }
      }
    }
  },
  
  requiredCheck: function(field,data,list)
  {
    var rtn = '';
    if(list[field].length!=0 && data.length==0)
    {
      rtn = list[field];
    }
    
    return rtn;
  }
};

function fixEmptyTags(data)
{
  var tag_list = ['br','hr','meta','link','base','img','embed','param','area','frame','col','input','basefont','bgsound','keygen','sound','spacer','wbr'];
  var reg_match = '<%tag%(\\s+([^>]*))?>';
  var reg_replace = '<%tag% $2 />';
  var i,re;
  
  for(i=0;i<tag_list.length;i++)
  {
    re = new RegExp(reg_match.replace('%tag%',tag_list[i]),'img');
    data = data.replace(re,reg_replace.replace('%tag%',tag_list[i]));
  }
  return data;
}

// general error handler for dhtmlx library
function dhtmlxErrors(type,desc,errData,noerr)
{
  var msg = '';
  var url = '';
  var errText = '';
  var urlFormat = 're-login-form.html@_rtnlink={_40path}';
  var errLogUrl = 'server/error-log/error-log.ashx';
  var errLogPost = 'app={_40app}&page={_40page}&err={_40err}&msg={_40msg}';
  var obj = null;
  var str = null;
  var ne = noerr || false;
  var verbose = 1; // 1 = yes, 0= no;
  
  if(errData && errData[0])
  {
    // get dhtmlx object info
    str = null;
    obj = errData[1];

    try
    {
      if(obj instanceof dhtmlXGridObject)
      {
        str = 'dhtmlXGridObject';
        try{str+' '+obj.xmlFileUrl;}
        catch(ex){}
      }
    }
    catch(ex){}
    
    try
    {
      if(str==null && (obj instanceof dhtmlXTreeObject))
      {
        str = 'dhtmlXTreeObject ';
        try{str+' '+obj.xmlFileUrl;}
        catch(ex){}
      }
    }
    catch(ex){}

    try
    {
      if(str==null && (obj instanceof dhtmlxFolders))
      {
        str = 'dhtmlxFolders';
        try{str+' '+obj.xmlFileUrl;}
        catch(ex){}
      }
    }
    catch(ex){}

    try
    {
      if(str==null && (obj instanceof dhtmlXMenuObject))
      {
        str = 'dhtmlXMenuObject';
        try{str+' '+obj.xmlFileUrl;}
        catch(ex){}
      }
    }
    catch(ex){}

    try
    {
      if(str==null && (obj instanceof dhtmlXTabBar))
      {
        str = 'dhtmlXTabBar';
      }
    }
    catch(ex){}

    try
    {
      if(str==null && (obj instanceof dhtmlXCombo))
      {
        str = 'dhtmlXCombo';
        try{str+' '+obj.xmlFileUrl;}
        catch(ex){}
      }
    }
    catch(ex){}

    try
    {
      if(str==null && (obj instanceof dhtmlXToolbarObject))
      {
        str = 'dhtmlXToolbarObject';
        try{str+' '+obj.xmlFileUrl;}
        catch(ex){}
      }
    }
    catch(ex){}

    try
    {
      if(str==null && (obj instanceof dhtmlxCalendarObject))
      {
        str = 'dhtmlxCalendarObject';
      }
    }
    catch(ex){}

    try
    {
      if(str==null && (obj instanceof dhtmlXWindows))
      {
        str = 'dhtmlXWindows';
      }
    }
    catch(ex){}

    try
    {
      if(str==null && (obj instanceof dhtmlXVaultObject))
      {
        str = 'dhtmlXVaultObject';
      }
    }
    catch(ex){}

    try
    {
      if(str==null && (obj instanceof dhtmlXLayoutObject))
      {
        str = 'dhtmlXLayoutObject';
      }
    }
    catch(ex){}

    try
    {
      if(str==null && (obj instanceof dhtmlXAccordion))
      {
        str = 'dhtmlXAccordion';
      }
    }
    catch(ex){}

    if(str==null)
    {
      str = obj;
    }
    
    // handle true un-auth situation
    if(errData[0].status==401 || errData[0].status==403)
    {
      msg = errData[0].status+'\n'+errData[0].statusText+'\n'+str;
      url = url.replace('{@path}',location.pathname+location.search);
      return;
    }
    else
    {
      // must be some other error
      try
      {
        errText = galaxy.trim(errData[0].responseText).replace(/<br \/>/g,'\n').replace(/<h1>/g,'').replace(/<\/h1>/g,'\n').replace(/500 - server error/g,'')
        msg = errData[0].status+'\n'+errData[0].statusText+'\n'+errText+str;
      }
      catch(ex)
      {
        errText = errData[0];
        msg = errText+str;
      }
    }
  }
  else
  {
    // not a dhtmlx error
    msg = type + '\n'+desc;
  }
  
  // try to post error info to server
  if(ajax)
  {
    try
    {
      var ck = galaxy.readCookie('session-email');
      var postData = errLogPost.replace('{@app}',ck).replace('{@page}',location.href).replace('{@err}',type).replace('{@msg}',desc+' ['+errText.replace(/\n/g,',')+' ('+str+')]');
      ajax.showStatus=false;
      ajax.httpPost(errLogUrl,null,null,false,'errPost','application/x-www-form-urlencoded',postData);
    }
    catch(ex)
    {
      // na
    }
  }
  
  // url if you got'em
  if(url!='')
  {
    location.href = url;
    return;
  }
  
  // else show error
  if(msg!='' && ne==false)
  {
    if(verbose==1)
    {
      alert(msg);
    }
    else
    {
      alert('Program Error!\n'+desc+' ['+type+']');
    }
    return;
  }
}

window.size = function()
{
	var w = 0;
	var h = 0;

	//IE
	if(!window.innerWidth)
	{
		//strict mode
		if(!(document.documentElement.clientWidth == 0))
		{
			w = document.documentElement.clientWidth;
			h = document.documentElement.clientHeight;
		}
		//quirks mode
		else
		{
			w = document.body.clientWidth;
			h = document.body.clientHeight;
		}
	}
	//w3c
	else
	{
		w = window.innerWidth;
		h = window.innerHeight;
	}
	return {width:w,height:h};
}

window.center = function()
{
	var hWnd = (arguments[0] != null) ? arguments[0] : {width:0,height:0};

	var _x = 0;
	var _y = 0;
	var offsetX = 0;
	var offsetY = 0;

	//IE
	if(!window.pageYOffset)
	{
		//strict mode
		if(!(document.documentElement.scrollTop == 0))
		{
			offsetY = document.documentElement.scrollTop;
			offsetX = document.documentElement.scrollLeft;
		}
		//quirks mode
		else
		{
			offsetY = document.body.scrollTop;
			offsetX = document.body.scrollLeft;
		}
	}
	//w3c
	else
	{
		offsetX = window.pageXOffset;
		offsetY = window.pageYOffset;
	}

	_x = ((this.size().width-hWnd.width)/2)+offsetX;
	_y = ((this.size().height-hWnd.height)/2)+offsetY;

	return{x:_x,y:_y};
}

/**
*
*  Base64 encode / decode
*  http://www.webtoolkit.info/
*
**/
 
var Base64 = {
 
	// private property
	_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
 
	// public method for encoding
	encode : function (input) {
		var output = "";
		var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
		var i = 0;
 
		input = Base64._utf8_encode(input);
 
		while (i < input.length) {
 
			chr1 = input.charCodeAt(i++);
			chr2 = input.charCodeAt(i++);
			chr3 = input.charCodeAt(i++);
 
			enc1 = chr1 >> 2;
			enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
			enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
			enc4 = chr3 & 63;
 
			if (isNaN(chr2)) {
				enc3 = enc4 = 64;
			} else if (isNaN(chr3)) {
				enc4 = 64;
			}
 
			output = output +
			this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
			this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
 
		}
 
		return output;
	},
 
	// public method for decoding
	decode : function (input) {
		var output = "";
		var chr1, chr2, chr3;
		var enc1, enc2, enc3, enc4;
		var i = 0;
 
		input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
 
		while (i < input.length) {
 
			enc1 = this._keyStr.indexOf(input.charAt(i++));
			enc2 = this._keyStr.indexOf(input.charAt(i++));
			enc3 = this._keyStr.indexOf(input.charAt(i++));
			enc4 = this._keyStr.indexOf(input.charAt(i++));
 
			chr1 = (enc1 << 2) | (enc2 >> 4);
			chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
			chr3 = ((enc3 & 3) << 6) | enc4;
 
			output = output + String.fromCharCode(chr1);
 
			if (enc3 != 64) {
				output = output + String.fromCharCode(chr2);
			}
			if (enc4 != 64) {
				output = output + String.fromCharCode(chr3);
			}
 
		}
 
		output = Base64._utf8_decode(output);
 
		return output;
 
	},
 
	// private method for UTF-8 encoding
	_utf8_encode : function (string) {
		string = string.replace(/\r\n/g,"\n");
		var utftext = "";
 
		for (var n = 0; n < string.length; n++) {
 
			var c = string.charCodeAt(n);
 
			if (c < 128) {
				utftext += String.fromCharCode(c);
			}
			else if((c > 127) && (c < 2048)) {
				utftext += String.fromCharCode((c >> 6) | 192);
				utftext += String.fromCharCode((c & 63) | 128);
			}
			else {
				utftext += String.fromCharCode((c >> 12) | 224);
				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
				utftext += String.fromCharCode((c & 63) | 128);
			}
 
		}
 
		return utftext;
	},
 
	// private method for UTF-8 decoding
	_utf8_decode : function (utftext) {
		var string = "";
		var i = 0;
		var c = c1 = c2 = 0;
 
		while ( i < utftext.length ) {
 
			c = utftext.charCodeAt(i);
 
			if (c < 128) {
				string += String.fromCharCode(c);
				i++;
			}
			else if((c > 191) && (c < 224)) {
				c2 = utftext.charCodeAt(i+1);
				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
				i += 2;
			}
			else {
				c2 = utftext.charCodeAt(i+1);
				c3 = utftext.charCodeAt(i+2);
				string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
				i += 3;
			}
 
		}
 
		return string;
	}
 
}

var hexTools = function()
{
  var digitArray = new Array('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f');
  
  function toHex(n){
      var result = ''
      var start = true;
      for (var i=32; i>0;){
          i-=4;
          var digit = (n>>i) & 0xf;
          if (!start || digit != 0){
              start = false;
              result += digitArray[digit];
          }
      }
      return (result==''?'0':result);
  }
  
  function ntos(n){
    n=n.toString(16);
    if (n.length == 1) n="0"+n;
    n="%"+n;
    return unescape(n);
  }

  function pad(str, len, pad){
      var result = str;
      for (var i=str.length; i<len; i++){
          result = pad + result;
      }
      return result;
  }
  
  function encodeHex(str){
      var result = "";
      for (var i=0; i<str.length; i++){
          result += pad(toHex(str.charCodeAt(i)&0xff),2,'0');
      }
      return result;
  }
  
  var hexv = {
    "00":0,"01":1,"02":2,"03":3,"04":4,"05":5,"06":6,"07":7,"08":8,"09":9,"0A":10,"0B":11,"0C":12,"0D":13,"0E":14,"0F":15,
    "10":16,"11":17,"12":18,"13":19,"14":20,"15":21,"16":22,"17":23,"18":24,"19":25,"1A":26,"1B":27,"1C":28,"1D":29,"1E":30,"1F":31,
    "20":32,"21":33,"22":34,"23":35,"24":36,"25":37,"26":38,"27":39,"28":40,"29":41,"2A":42,"2B":43,"2C":44,"2D":45,"2E":46,"2F":47,
    "30":48,"31":49,"32":50,"33":51,"34":52,"35":53,"36":54,"37":55,"38":56,"39":57,"3A":58,"3B":59,"3C":60,"3D":61,"3E":62,"3F":63,
    "40":64,"41":65,"42":66,"43":67,"44":68,"45":69,"46":70,"47":71,"48":72,"49":73,"4A":74,"4B":75,"4C":76,"4D":77,"4E":78,"4F":79,
    "50":80,"51":81,"52":82,"53":83,"54":84,"55":85,"56":86,"57":87,"58":88,"59":89,"5A":90,"5B":91,"5C":92,"5D":93,"5E":94,"5F":95,
    "60":96,"61":97,"62":98,"63":99,"64":100,"65":101,"66":102,"67":103,"68":104,"69":105,"6A":106,"6B":107,"6C":108,"6D":109,"6E":110,"6F":111,
    "70":112,"71":113,"72":114,"73":115,"74":116,"75":117,"76":118,"77":119,"78":120,"79":121,"7A":122,"7B":123,"7C":124,"7D":125,"7E":126,"7F":127,
    "80":128,"81":129,"82":130,"83":131,"84":132,"85":133,"86":134,"87":135,"88":136,"89":137,"8A":138,"8B":139,"8C":140,"8D":141,"8E":142,"8F":143,
    "90":144,"91":145,"92":146,"93":147,"94":148,"95":149,"96":150,"97":151,"98":152,"99":153,"9A":154,"9B":155,"9C":156,"9D":157,"9E":158,"9F":159,
    "A0":160,"A1":161,"A2":162,"A3":163,"A4":164,"A5":165,"A6":166,"A7":167,"A8":168,"A9":169,"AA":170,"AB":171,"AC":172,"AD":173,"AE":174,"AF":175,
    "B0":176,"B1":177,"B2":178,"B3":179,"B4":180,"B5":181,"B6":182,"B7":183,"B8":184,"B9":185,"BA":186,"BB":187,"BC":188,"BD":189,"BE":190,"BF":191,
    "C0":192,"C1":193,"C2":194,"C3":195,"C4":196,"C5":197,"C6":198,"C7":199,"C8":200,"C9":201,"CA":202,"CB":203,"CC":204,"CD":205,"CE":206,"CF":207,
    "D0":208,"D1":209,"D2":210,"D3":211,"D4":212,"D5":213,"D6":214,"D7":215,"D8":216,"D9":217,"DA":218,"DB":219,"DC":220,"DD":221,"DE":222,"DF":223,
    "E0":224,"E1":225,"E2":226,"E3":227,"E4":228,"E5":229,"E6":230,"E7":231,"E8":232,"E9":233,"EA":234,"EB":235,"EC":236,"ED":237,"EE":238,"EF":239,
    "F0":240,"F1":241,"F2":242,"F3":243,"F4":244,"F5":245,"F6":246,"F7":247,"F8":248,"F9":249,"FA":250,"FB":251,"FC":252,"FD":253,"FE":254,"FF":255
  };
  
  function decodeHex(str){
      str = str.toUpperCase().replace(new RegExp("s/[^0-9A-Z]//g"));
      var result = "";
      var nextchar = "";
      for (var i=0; i<str.length; i++){
          nextchar += str.charAt(i);
          if (nextchar.length == 2){
              result += ntos(hexv[nextchar]);
              nextchar = "";
          }
      }
      return result;
      
  }
  
  var that = {};
  that.encodeHex = encodeHex;
  that.decodeHex = decodeHex;
  return that;
}

/**
*
*  UTF-8 data encode / decode
*  http://www.webtoolkit.info/
*
**/
 
var Utf8 = {
 
	// public method for url encoding
	encode : function (string) {
		string = string.replace(/\r\n/g,"\n");
		var utftext = "";
 
		for (var n = 0; n < string.length; n++) {
 
			var c = string.charCodeAt(n);
 
			if (c < 128) {
				utftext += String.fromCharCode(c);
			}
			else if((c > 127) && (c < 2048)) {
				utftext += String.fromCharCode((c >> 6) | 192);
				utftext += String.fromCharCode((c & 63) | 128);
			}
			else {
				utftext += String.fromCharCode((c >> 12) | 224);
				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
				utftext += String.fromCharCode((c & 63) | 128);
			}
 
		}
 
		return utftext;
	},
 
	// public method for url decoding
	decode : function (utftext) {
		var string = "";
		var i = 0;
		var c = c1 = c2 = 0;
 
		while ( i < utftext.length ) {
 
			c = utftext.charCodeAt(i);
 
			if (c < 128) {
				string += String.fromCharCode(c);
				i++;
			}
			else if((c > 191) && (c < 224)) {
				c2 = utftext.charCodeAt(i+1);
				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
				i += 2;
			}
			else {
				c2 = utftext.charCodeAt(i+1);
				c3 = utftext.charCodeAt(i+2);
				string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
				i += 3;
			}
 
		}
 
		return string;
	}
 
}
