// Browser detection
var isOpera  = (navigator.userAgent.toLowerCase().indexOf('opera') > -1);
var isIE     = (!isOpera && navigator.userAgent.toLowerCase().indexOf('msie') > -1);
var isSafari = (navigator.userAgent.indexOf('AppleWebKit') != -1); // Detecting not only Safari but WebKit-based browsers
var isKonqueror = (navigator.userAgent.toLowerCase().indexOf('khtml') > -1);
var isMoz    = (document.implementation && document.implementation.createDocument && !isKonqueror && !isSafari ? true : false);
var isFF     = (isMoz && navigator.userAgent.toLowerCase().indexOf('firefox')!= -1);

if (isIE) {
   var verIE = parseInt(navigator.appVersion.split('MSIE')[1]);
}
if (isOpera) {
   var verOpera = parseFloat(navigator.userAgent.split('Opera ')[1]);
   if (isNaN(verOpera)) {
      verOpera = parseFloat(navigator.userAgent.split('Opera/')[1]);
   }
}

String.prototype.trim = function() {
   return this.replace(/^\s+|\s+$/g,"");
}

var defaultCornerRadius = 8;
var smallCornerRadius = 6;
var df = new DOMfunc();

function doRoundCorners() {
   df.registerClass('roundedTop',RoundedTop,defaultCornerRadius);
   df.registerClass('roundedBottom',RoundedBottom,defaultCornerRadius);
   df.registerClass('roundedLeft',RoundedLeft,defaultCornerRadius);
   df.registerClass('roundedRight',RoundedRight,defaultCornerRadius);
   df.registerClass('infoBoxContent',RoundedTop,defaultCornerRadius);
   df.registerClass('infoBoxTitle',RoundedBottom,defaultCornerRadius);
   df.registerClass('roundedRBox',RoundedBoxRecursive,defaultCornerRadius);
   df.registerClass('roundedBox',RoundedBox,defaultCornerRadius);
   df.registerClass('roundedBoxSmall',RoundedBox,smallCornerRadius);
   df.registerClass('roundedTopSmall',RoundedTop,smallCornerRadius);
   df.registerClass('roundedBottomSmall',RoundedBottom,smallCornerRadius);
   df.registerClass('roundedLeftSmall',RoundedLeft,smallCornerRadius);
   df.registerClass('roundedRightSmall',RoundedRight,smallCornerRadius);
   df.apply();
   cCorners.applyToRegistered();
}

function DOMfunc () {
   this.map = {'ids':{},'classes':{}};
   this.elemMap = {};
}

DOMfunc.prototype.registerClass = function(className,func) {
   var args = [];
   if (arguments.length > 2) {
      for (var i=2; i<arguments.length; i++) {
         args.push(arguments[i]);
      }
   }
   if (!this.map.classes[className]) {
      this.map.classes[className] = [];
   }
   if (!this.elemMap[className]) {
      this.elemMap[className] = [];
   }
   this.map.classes[className].push({'func':func,'args':args});
}

DOMfunc.prototype.registerId = function(id,func) {
   var args = [];
   if (arguments.length > 2) {
      for (var i=2; i<arguments.length; i++) {
         args.push(arguments[i]);
      }
   }
   if (!this.map.ids[id]) {
      this.map.ids[id] = [];
   }
   this.map.ids[id].push({'func':func,'args':args});
}

DOMfunc.prototype.apply = function() {
   // Prefetch classes
   var strTag = '*';
   var objContElm = document;
   var objColl = (strTag == '*' && document.all && !window.opera) ? document.all : objContElm.getElementsByTagName(strTag);
   var arr = new Array();
   for (var i = 0, j = objColl.length; i < j; i++) {
      var arrObjClass = objColl[i].className.split(' ');
      if (!arrObjClass.length) continue;
      for (var k = 0, l = arrObjClass.length; k < l; k++) {
         if (this.map.classes[arrObjClass[k]]) {
            if (!objColl[i].id) {
               objColl[i].id = getTempId();
            }
            this.elemMap[arrObjClass[k]].push(objColl[i].id);
         }
      }
   }
   this._runMap();
}

DOMfunc.prototype._runMap = function() {
   // Run classes
   for (var i in this.elemMap) {
      for (var j = 0; j < this.elemMap[i].length; j++) {
         var elem = document.getElementById(this.elemMap[i][j]);
         for (var k = 0; k < this.map.classes[i].length; k++) {
            this.map.classes[i][k].func.apply(null,[elem].concat(this.map.classes[i][k].args));
         }
      }
   }
   // Run ids
   for (var i in this.map.ids) {
      var elem = document.getElementById(i);
      if (elem) {
         for (var j = 0; j < this.map.ids[i].length; j++) {
            this.map.ids[i][j].func.apply(null,[elem].concat(this.map.ids[i][j].args));
         }
      }
   }
}

var tmpCount = 0;
function getTempId() {
   return 'tmpId_'+(tmpCount++);
}

function debugLog(msg) {
   if (typeof(console) !== 'undefined') {
      console.log(msg);
   } else {
      document.body.appendChild(document.createTextNode(msg));
      document.body.appendChild(document.createElement('BR'));
   }
}

function elemAttachedToBody(el) {
   var node = el;
   while (node && node.offsetParent) {
      node = node.offsetParent;
   }
   return (node.tagName === 'BODY');
}

function stripSuffix(str,suffix) {
   if (str.substring(str.length-suffix.length) == suffix) {
      return str.substr(0,str.length - suffix.length);
   } else {
      return str;
   }
}

function convertToPT(dim,obj) {
   try {
      dim = dim.toString();
      if (dim.indexOf('pt') != -1) {
         return stripSuffix(dim,'pt');
      } else {
         return (convertToPX(dim,obj) / 1.3333);
      }
   } catch(e) {
      alert('Failed to convert "'+dim+'" to points\n'+e.message);
   }
}

function convertToPX(dim,obj) {
   try {
      dim = dim.toString();
      if (dim.indexOf('em') != -1) {
         var fontSize = convertToPX(getFontSize(obj));
         return parseFloat(stripSuffix(dim,'em') * fontSize);
      } else if (dim.indexOf('pt') != -1) {
         return parseFloat(stripSuffix(dim,'pt') * 1.3333);
      } else if (dim.indexOf('px') != -1) {
         return parseFloat(stripSuffix(dim,'px'));
      } else {
         return parseFloat(dim);
      }
   } catch(e) {
      alert('Failed to convert "'+dim+'" to pixels\n'+e.message);
   }
}

function convertToEM(dim,obj) {
   try {
      dim = dim.toString();
      if (dim.indexOf('em') != -1) {
         return stripSuffix(dim,'em');
      } else  {
         var fontSize = convertToPX(getFontSize(obj));
         return (convertToPX(dim) / fontSize);
      }
   } catch(e) {
      alert('Failed to convert "'+dim+'" to EMs\n'+e.message);
   }
}

function getFontSize(obj) {
   var fontSize = get_style(obj, 'fontSize', 'font-size');

   if (fontSize.indexOf('em') != -1) {
      // We have a font size in EM, look up the DOM tree until we find a PX or PT value
      var stack = [fontSize];
      var node = obj.parentNode;
      var nodeFontSize = get_style(node, 'fontSize', 'font-size');
      while (node && nodeFontSize.indexOf('em') != -1) {
         stack.unshift(nodeFontSize);
         node = node.parentNode;
         if (node) {
            nodeFontSize = get_style(node, 'fontSize', 'font-size');
         }
      }
      if (node) {
         fontSize = convertToPX(nodeFontSize,node);
         for (var i=0; i<stack.length; i++) {
            fontSize = fontSize * stripSuffix(stack[i],'em');
         }
         fontSize += 'px';
      }
   }

   return fontSize;
}

/*
Converts a number to hexadecimal format
*/
function IntToHex(strNum) {
   base = strNum / 16;
   rem = strNum % 16;
   base = base - (rem / 16);
   baseS = MakeHex(base);
   remS = MakeHex(rem);
   return baseS + '' + remS;
}

/*
gets the hex bits of a number
*/
function MakeHex(x) {
   if ((x >= 0) && (x <= 9)) {
      return x;
   } else {
      switch(x) {
         case 10:
            return "A";
         case 11:
            return "B";
         case 12:
            return "C";
         case 13:
            return "D";
         case 14:
            return "E";
         case 15:
            return "F";
      }
   }
}

// This function converts CSS rgb(x, x, x) to hexadecimal
function rgb2Hex(rgbColor) {
   try {
       // Get array of RGB values
       var rgbArray = rgb2Array(rgbColor);

       if (rgbArray.length == 3) {
          // Get RGB values
          var red   = parseInt(rgbArray[0]);
          var green = parseInt(rgbArray[1]);
          var blue  = parseInt(rgbArray[2]);

          // Build hex color code
          var hexColor = '#' + IntToHex(red) + IntToHex(green) + IntToHex(blue);
       }
   } catch(e) {
       alert('There was an error converting the RGB value to Hexadecimal in function rgb2Hex');
   }

   return hexColor;
}

// Returns an array of rbg values
function rgb2Array(rgbColor) {
   var parenthesis1 = rgbColor.indexOf('(');
   var parenthesis2 = rgbColor.indexOf(')');
   var rgbType = rgbColor.substr(0, parenthesis1).toLowerCase();
   var rgbValues = rgbColor.substring((parenthesis1 + 1), parenthesis2);
   var rgbArray = rgbValues.split(',');
   for (var i=0; i<rgbArray.length; i++) {
      rgbArray[i] = parseInt(rgbArray[i]);
   }
   if ((rgbType == 'rgb' && rgbArray.length != 3) || (rgbType == 'rgba' && rgbArray.length != 4)) {
      throw new Error('failed to extract array from rgb: error parsing rgb values');
   }
   return rgbArray;
}

/*
Function by Simon Willison from sitepoint.com
Modified by Cameron Cooke adding Safari's rgba support
*/
function setOpacity(obj,opacity) {
   opacity = (opacity == 100) ? 99.999 : opacity;

   if (typeof(obj.style.opacity) != 'undefined') {
      // W3C
      obj.style.opacity = opacity / 100;
   } else if (typeof(obj.style.MozOpacity) != 'undefined') {
      // Older Mozilla
      obj.style.MozOpacity = opacity / 100;
   } else if (typeof(obj.style.filter) != 'undefined') {
      // IE
      obj.style.filter = 'alpha(opacity:' + opacity + ')';
   } else if (typeof(obj.style.KHTMLOpacity) != 'undefined') {
      // Older KHTML Based Browsers
      obj.style.KHTMLOpacity = opacity / 100;
   }
}

/*
Returns index if the passed value is found in the
array otherwise returns false.
*/
function inArray(array,value) {
   for (var i=0; i<array.length; i++) {
      // Matches identical (===), not just similar (==).
      if (array[i] === value) return i;
   }
   return false;
}

/*
Returns true if the passed value is found as a key
in the array otherwise returns false.
*/
function inArrayKey(array,value) {
   for (key in array) {
      // Matches identical (===), not just similar (==).
      if (key === value) return true;
   }
   return false;
}

// Formats colors
function format_color(color) {
   // Make sure color is set and not transparent
   if (color != '' && color != 'transparent') {
      // RGB Value?
      if (color.substr(0,3) == 'rgb') {
         if (color.substr(0,4) == 'rgba') {
            var rgbArray = rgb2Array(color);
            if (rgbArray.length == 4 && rgbArray[3] == 0) {
               return 'transparent';
            } else {
               return rgb2Hex(color);
            }
         } else {
            // Get HEX aquiv.
            return rgb2Hex(color);
         }
      } else if (color.length == 4) {
         // 3 chr color code add remainder
         return '#' + color.charAt(1) + color.charAt(1) + color.charAt(2) + color.charAt(2) + color.charAt(3) + color.charAt(3);
      } else {
         // Normal valid hex color
         return color;
      }
   }

   return '#ffffff';
}

// Returns the style value for the property specfied
function get_style(obj,property,propertyNS) {
   var returnVal;

   try {
      if (obj.currentStyle && !isOpera) {
         var returnVal = obj.currentStyle[property];
      } else {
         /*
         Safari does not expose any information for the object if display is
         set to none is set so we temporally enable it.
         */
         if (isSafari && obj.style.display == 'none') {
            obj.style.display = '';
            var wasHidden = true;
         }

         var returnVal = document.defaultView.getComputedStyle(obj,'').getPropertyValue(propertyNS);

         // Rehide the object
         if (isSafari && wasHidden) {
            obj.style.display = 'none';
         }
      }
   } catch(e) {
       // Do nothing
   }

   if (typeof(returnVal) == 'undefined') {
      returnVal = '';
   }

   return returnVal;
}

// Inserts a element after another
function insertAfter (parentNode, node, referenceNode)
{
   try {
      if (referenceNode.nextSibling) {
         return parentNode.insertBefore(node, referenceNode.nextSibling);
      } else {
         return parentNode.appendChild(node);
      }
   } catch(e) {
      // Do nothing
   }
}

function getElementsByClassName(strClass, aTags, objContElm) {
   if (!aTags) {
      aTags = ['*'];
   } else if (!(aTags instanceof Array)) {
      aTags = [aTags];
   }
   objContElm = objContElm || document;
   if (inArray(aTags,'*') && document.all && !window.opera) {
      var objColl = document.all;
   } else {
      var objColl = [];
      for (var i=0; i<aTags.length; i++) {
         var hc = objContElm.getElementsByTagName(aTags[i]);
         for (var j=0; j<hc.length; j++) {
            objColl.push(hc[j]);
         }
      }
   }
   var arr = new Array();
   var delim = strClass.indexOf('|') != -1  ? '|' : ' ';
   var arrClass = strClass.split(delim);
   for (var i = 0, j = objColl.length; i < j; i++) {
      var arrObjClass = objColl[i].className.split(' ');
      if (delim == ' ' && arrClass.length > arrObjClass.length) continue;
      var c = 0;
      comparisonLoop:
      for (var k = 0, l = arrObjClass.length; k < l; k++) {
         for (var m = 0, n = arrClass.length; m < n; m++) {
            if (arrClass[m] == arrObjClass[k]) c++;
            if (( delim == '|' && c == 1) || (delim == ' ' && c == arrClass.length)) {
               arr.push(objColl[i]);
               break comparisonLoop;
            }
         }
      }
   }
   return arr;
}

function addClass(obj,className) {
   var classes = getClasses(obj);
   for (var i=0; i<classes.length; i++) {
      if (classes[i].toLowerCase() == className.toLowerCase()) {
         classes[i] = '';
      }
   }
   classes.push(className);
   obj.className = classes.join(' ');
}

function removeClass(obj,className) {
   var classes = getClasses(obj);
   for (var i=0; i<classes.length; i++) {
      if (classes[i].toLowerCase() == className.toLowerCase()) {
         classes[i] = '';
      }
   }
   obj.className = classes.join(' ');
}

function hasClass(obj,className) {
   var classes = getClasses(obj);
   if (!(className instanceof Array)) {
      className = new Array(className.toString());
   }
   var matchAll = (className.length > 0);
   for (var i=0; i<className.length; i++)
   {
      var matchAll = (matchAll && inArray(classes,className[i]) !== false);
   }
   return matchAll;
}

function showInfo(targetId)
{
   document.getElementById(targetId).style.display = 'block';
}

function hideInfo(targetId)
{
   document.getElementById(targetId).style.display = 'none';
}

function getClasses(obj) {
   return (obj && obj.className ? obj.className.split(/\s+/) : []);
}

function addEvent(obj,evType,fn,useCapture) {
   if (window.opera && obj.addEventListener) {
      // Prevent an Opera bug where event added in capture mode to form elements do not get triggered
      useCapture = false;
   }
   if (obj.addEventListener) {
      obj.addEventListener(evType,fn,useCapture);
      return true;
   } else if (obj.attachEvent) {
      var r = obj.attachEvent('on'+evType,fn);
      return r;
   } else {
      return false;
   }
}

function removeEvent(obj,evType,fn,useCapture) {
   if (window.opera && obj.addEventListener) {
      // Prevent an Opera bug where event added in capture mode to form elements do not get triggered
      useCapture = false;
   }
   if (obj.removeEventListener) {
      obj.removeEventListener(evType,fn,useCapture);
      return true;
   } else if (obj.detachEvent) {
      var r = obj.detachEvent('on'+evType,fn);
      return r;
   } else {
      return false;
   }
}

function fireEvent(obj,evType,isCustom) {
   try {
      if (document.createEvent) {
         if (!isCustom) {
            var eventModuleMap = {
               'abort':'HTMLEvents',
               'blur':'HTMLEvents',
               'change':'HTMLEvents',
               'error':'HTMLEvents',
               'focus':'HTMLEvents',
               'load':'HTMLEvents',
               'reset':'HTMLEvents',
               'resize':'HTMLEvents',
               'scroll':'HTMLEvents',
               'select':'HTMLEvents',
               'submit':'HTMLEvents',
               'unload':'HTMLEvents',
               'click':'MouseEvents',
               'mousedown':'MouseEvents',
               'mousemove':'MouseEvents',
               'mouseout':'MouseEvents',
               'mouseover':'MouseEvents',
               'mouseup':'MouseEvents',
               'DOMAttrModified':'MutationEvents',
               'DOMNodeInserted':'MutationEvents',
               'DOMNodeRemoved':'MutationEvents',
               'DOMCharacterDataModified':'MutationEvents',
               'DOMNodeInsertedIntoDocument':'MutationEvents',
               'DOMNodeRemovedFromDocument':'MutationEvents',
               'DOMSubtreeModified':'MutationEvents',
               'DOMActivate':'UIEvents',
               'DOMFocusIn':'UIEvents',
               'DOMFocusOut':'UIEvents'
            }
            if (isMoz) {
               eventModuleMap['keydown'] = 'KeyEvents';
               eventModuleMap['keypress'] = 'KeyEvents';
               eventModuleMap['keyup'] = 'KeyEvents';
            } else {
               eventModuleMap['keydown'] = 'UIEvents';
               eventModuleMap['keypress'] = 'UIEvents';
               eventModuleMap['keyup'] = 'UIEvents';
            }
            var eventModule = eventModuleMap[evType];
         } else {
            var eventModule = 'Events';
         }
         var evObj = document.createEvent(eventModule);
         evObj.initEvent(evType,true,false);
         var ret = obj.dispatchEvent(evObj);
      } else if (document.createEventObject) {
         var ret = obj.fireEvent('on'+evType);
      } else {
         var ret = false;
         alert('fireEvent() unsupported on this browser');
      }
   } catch (e) {
      alert('An error occured in fireEvent()\n'+e.message);
   }
   return ret;
}

function getCookie(name) {
   var arg = name + "=";
   var alen = arg.length;
   var clen = document.cookie.length;
   var i = 0;
   while (i < clen) {
      var j = i + alen;
      if (document.cookie.substring(i, j) == arg) {
         var endstr = document.cookie.indexOf (";", j);
         if (endstr == -1) endstr = document.cookie.length;
         return unescape(document.cookie.substring(j, endstr));
      }
      i = document.cookie.indexOf(" ", i) + 1;
      if (i == 0) break;
   }
   return null;
}

function setCookie(name, value, expires, path, domain, secure) {
   document.cookie = name + "=" + escape(value) + (expires ? ("; expires=" + expires.toGMTString()) : "") + (path ? ("; path=" + path) : "") + (domain ? ("; domain=" + domain) : "") + (secure ? "; secure" : "");
}

function clearCookie(name) {
   date = new Date;
   date.setFullYear(date.getFullYear() - 1);
   setCookie(name,null,date);
}

// Clone an object
// Usage: var clonedObj = new cloneObject(originalObj);
function cloneObject(what) {
   var result;
   var cut = (String(Object).indexOf('(') != 16) ? 9 : 10;
   var oname = String(what.constructor);
   oname = oname.substr(cut, (oname.indexOf('(') - cut));
   switch(oname) {
      case 'String':
      case 'Number':
      case 'Boolean':
      case 'Function':
         result = what;
         break;
      case 'Array':
         result = new Array();
         //result = what.concat();
         for (var i=0; i<what.length; i++) {
            if (parseInt(i) != Number.NaN) {
               result[i] = cloneObject(what[i]);
            }
         }
         break;
      default:
         eval('result = new ' + oname + '();');
         for(var a in what)
            result[a] = cloneObject(what[a]);
         break;
   }
   return result;
}

// Merge objects
// Usage: ret = mergeObjects(obj1[,obj2[,obj3,...[,objn]]])
function mergeObjects() {
   var newObj;
   try {
      newObj = cloneObject(arguments[0]);
      if (arguments.length > 1) {
         for (var i=1; i<arguments.length; i++) {
            for (var prop in arguments[i]) {
               newObj[prop] = arguments[i][prop];
            }
         }
      }
   } catch(e) {
      // Do nothing
   }
   return newObj;
}

function getObjectType(obj) {
   var sConstructor = obj.constructor.toString();
   return sConstructor.substring(9,sConstructor.indexOf('(')).replace(/\s/,'');
}

function instanceOf(obj,objConstructor) {
   return (obj && objConstructor && typeof(obj) == 'object' && typeof(objConstructor) == 'function' && obj instanceof objConstructor);
}

/** CW
 * Call wrapper for async function and method calls
 */
function CW(callDef,aArguments) {
   this.mId = 'CW_'+(CW.mCounter++);
   this.callDef = callDef;
   this.mTimerId = null;
   this.mIntervalId = null;
   this.aArguments = aArguments;
   CW.mPendingCalls[this.mId] = this;
}

CW.prototype.execute = function(keepAfter,aArguments) {
   if (aArguments && aArguments.length) {
      var tArgs = aArguments;
   } else if (this.aArguments) {
      var tArgs = this.aArguments;
   } else {
      var tArgs = new Array();
   }
   if (typeof(this.callDef) == 'object' && typeof(this.callDef[0][this.callDef[1]]) == 'function') {
      this.callDef[0][this.callDef[1]].apply(this.callDef[0],tArgs);
   } else if (typeof(this.callDef) == 'function') {
      this.callDef.apply(null,tArgs);
   } else if (typeof(this.callDef) == 'string') {
      eval(this.callDef);
   } else {
      alert('Invalid call:\n'+(this.callDef.toSource ? this.callDef.toSource() : this.callDef.toString()));
   }
   if (!keepAfter) {
      delete(CW.mPendingCalls[this.mId]);
   }
}

CW.prototype.clear = function() {
   delete(CW.mPendingCalls[this.mId]);
}

CW.clearInterval = function(callwrapper) {
   if (instanceOf(callwrapper,CW) && CW.mPendingCalls[callwrapper.mId]) {
      clearInterval(CW.mPendingCalls[callwrapper.mId].mIntervalId);
   }
}

CW.setInterval = function(callwrapper,mInterval) {
   if (instanceOf(callwrapper,CW) && CW.mPendingCalls[callwrapper.mId]) {
      CW.mPendingCalls[callwrapper.mId].mIntervalId = setInterval('CW.mPendingCalls["' + callwrapper.mId + '"].execute(true)', mInterval);
   }
}

CW.clearTimeout = function(callwrapper) {
   if (instanceOf(callwrapper,CW) && CW.mPendingCalls[callwrapper.mId]) {
      clearTimeout(CW.mPendingCalls[callwrapper.mId].mTimerId);
   }
}

CW.setTimeout = function(callwrapper,mDelay) {
   if (instanceOf(callwrapper,CW) && CW.mPendingCalls[callwrapper.mId]) {
      CW.mPendingCalls[callwrapper.mId].mTimerId = setTimeout('CW.mPendingCalls["' + callwrapper.mId + '"].execute()', mDelay);
   }
}

CW.mCounter = 0;
CW.mPendingCalls = {};

var JSON = new Object();
JSON.parse = function (x) {
   if (x == null || typeof(x) == 'undefined') {
      return JSON.s['null'](x);
   }
   if (typeof(x) == 'function') {
      x = String(x);
   }
   var type = getObjectType(x).toLowerCase();
   if (JSON.s[type]) {
      return JSON.s[type](x);
   }
   return JSON.s['object'](x);
}
JSON.m = {
   '\b': '\\b',
   '\t': '\\t',
   '\n': '\\n',
   '\f': '\\f',
   '\r': '\\r',
   '"' : '\\"',
   '\\': '\\\\'
};
JSON.s = {
   'array': function (x) {
      var a = ['['], b, f, i, l = x.length, v;
      for (i = 0; i < l; i += 1) {
         v = JSON.parse(x[i]);
         if (b) {
            a[a.length] = ',';
         }
         a[a.length] = v;
         b = true;
      }
      a[a.length] = ']';
      return a.join('');
   },
   'boolean': function (x) {
      return String(x);
   },
   'null': function (x) {
      return "null";
   },
   'number': function (x) {
      return isFinite(x) ? String(x) : 'null';
   },
   'object': function (x) {
      var a = ['{'], b, f, i, v;
      for (i in x) {
         if (typeof(x[i]) != 'function') {
            v = JSON.parse(x[i]);
            if (v) {
               if (b) {
                  a[a.length] = ',';
               }
               a.push(JSON.parse(i), ':', v);
               b = true;
            }
         }
      }
      a[a.length] = '}';
      return a.join('');
   },
   'string': function (x) {
      if (/["\\\x00-\x1f]/.test(x)) {
         x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
            var c = JSON.m[b];
            if (c) {
               return c;
            }
            c = b.charCodeAt();
            return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
         });
      }
      return '"' + x + '"';
   }
};

Object.prototype.toJSONString = function () {
    return JSON.parse(this);
};

String.prototype.parseJSON = function () {
   try {
      return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(this.replace(/"(\\.|[^"\\])*"/g, ''))) && eval('(' + this + ')');
   } catch (e) {
      return false;
   }
};

String.prototype.ucFirst = function () {
   return this.substr(0,1).toUpperCase() + this.substr(1,this.length);
}

Number.prototype.isOdd = function () {
   return (parseInt(this.valueOf()) == this.valueOf() && (this.valueOf() % 2) != 0);
}

function _out(msg, elemType, className) {
   try {
      if (!elemType) {
         elemType = 'DIV';
      }
      var el = document.createElement(elemType.toUpperCase());
      el.className = className;
      el.appendChild(document.createTextNode(msg));
      document.body.appendChild(el);
   } catch (e) {
      alert('Failed _out("'+msg+'", "'+elemType+'", "'+className+'")');
   }
}

// load un stylesheet
function loadStyleSheet(styleSheetSrc) {
   var linkObj = document.createElement('LINK');
   linkObj.rel = 'stylesheet';
   linkObj.type = 'text/css';
   linkObj.href = styleSheetSrc;
   document.getElementsByTagName('head')[0].appendChild(linkObj); 
}

_hitch = function(thisObject, method) {
   if(method instanceof String || typeof method == 'string') {
      var fcn = thisObject[method];
   } else {
      var fcn = method;
   }
   
   return function() {
      return fcn.apply(thisObject, arguments);
   }
}

function SplashDiv(contentNode, bgOpacity, bgColor, speed, toHideNode) {
   if (typeof(bgOpacity) == 'undefined') {
      bgOpacity = 0.8;
   }

   if (typeof(bgColor) == 'undefined') {
      bgColor = '#ffffff';
   }

   if (typeof(speed) == 'undefined') {
      speed = 1;
   }
   
   this.bgDiv = null;
   this.topDiv = null;
   this.table = null;
   this.visibleDivs = 0;
   this.contentNode = contentNode;
   this.bgOpacity = bgOpacity;
   this.bgColor = bgColor;
   this.speed = speed;
   this.state = 'closed';
   this.scrollTop = null;
   this.showAfterFinish = null;
   this.hideAfterFinish = null;
   this.toHideNode = toHideNode;
}

SplashDiv.prototype.show = function(afterFinish) {
   if (this.state == 'closed') {
      this._create();
      this.showAfterFinish = afterFinish;
      
      if(typeof(this.toHideNode) == 'undefined') {
         document.body.appendChild(this.bgDiv);
         document.body.appendChild(this.topDiv);
      }
      else {
         this.toHideNode.appendChild(this.bgDiv);
         this.toHideNode.appendChild(this.topDiv);
      }
      
      this.state = 'opening';
      
      if (this.speed) {
         var t1 = new OpacityTween(this.bgDiv, null, 0, (this.bgOpacity * 100), this.speed);
         var t2 = new OpacityTween(this.topDiv, null, 0, 100, this.speed);
         var t = this;
         var listener = {
            'onMotionFinished': function () {
               t._showComplete();
            }
         };
         t1.addListener(listener);
         t2.addListener(listener);
         t1.start();
         t2.start();
         //new Effect.Opacity(this.bgDiv,{duration:this.speed,from:0,to:this.bgOpacity,afterFinish:_hitch(this,'_showComplete')});
         //new Effect.Opacity(this.topDiv,{duration:this.speed,from:0,to:1,afterFinish:_hitch(this,'_showComplete')});
      } else {
         setOpacity(this.bgDiv, (this.bgOpacity * 100));
         setOpacity(this.topDiv, 100);
         this._showComplete();
         this._showComplete();
      }
   }
}

SplashDiv.prototype.hide = function(afterFinish) {
   if (this.state == 'opened') {
      this.hideAfterFinish = afterFinish;
      
      this.state = 'hiding';
      
      if (this.speed) {
         var t1 = new OpacityTween(this.bgDiv, null, (this.bgOpacity * 100), 0, this.speed);
         var t2 = new OpacityTween(this.topDiv, null, 100, 0, this.speed);
         var t = this;
         var listener = {
            'onMotionFinished': function () {
               t._hideComplete();
            }
         };
         t1.addListener(listener);
         t2.addListener(listener);
         t1.start();
         t2.start();
         //new Effect.Opacity(this.bgDiv,{duration:this.speed,from:this.bgOpacity,to:0,afterFinish:_hitch(this,'_hideComplete')});
         //new Effect.Opacity(this.topDiv,{duration:this.speed,from:1,to:0,afterFinish:_hitch(this,'_hideComplete')});
      } else {
         setOpacity(this.bgDiv, 0);
         setOpacity(this.topDiv, 0);
         this._hideComplete();
         this._hideComplete();
      }
   }
}

SplashDiv.prototype.destroy = function() {
   if (this.state == 'opened') {
      this.hideAfterFinish = null;
      
      this.state = 'closed';
      
      this._hideComplete();
      this._hideComplete();
   }
}

SplashDiv.prototype._create = function() {
   this.bgDiv = document.createElement('DIV');
   this.bgDiv.id = 'splashDiv';
   if (isIE) {
      this.bgDiv.style.position = 'absolute';
      this.bgDiv.style.zoom = '1';
   } else if(typeof(this.toHideNode) == 'undefined') { 
      this.bgDiv.style.position = 'fixed';
   }
   else {
      this.bgDiv.style.position = 'absolute';
   }
   this.bgDiv.style.left = (isIE ? get_style(document.body, 'paddingLeft', 'padding-left') : '0');
   this.bgDiv.style.top = '0';
   this.bgDiv.style.width = '100%';
   this.bgDiv.style.height = (isIE ? document.body.scrollHeight+'px' : '100%');
   this.bgDiv.style.backgroundColor = this.bgColor;
   this.bgDiv.style.zIndex = '254';
   setOpacity(this.bgDiv, 0);

   this.topDiv = document.createElement('DIV');
   if (isIE) {
      this.topDiv.style.position = 'absolute';
      this.topDiv.style.zoom = '1';
   } else {
      this.topDiv.style.position = 'fixed';
   }
   this.topDiv.style.left = (isIE ? get_style(document.body, 'paddingLeft', 'padding-left') : '0');
   this.topDiv.style.top = '0';
   this.topDiv.style.width = '100%';
   this.topDiv.style.height = (isIE ? document.body.scrollHeight+'px' : '100%');
   this.topDiv.style.backgroundColor = 'transparent';
   this.topDiv.style.zIndex = '255';
   setOpacity(this.topDiv, 0);

   this.table = document.createElement('TABLE');
   if (!isIE) {
      this.table.style.position = 'fixed';
   } else {
      this.table.style.position = 'absolute';
      this._place();
      addEvent(window, 'scroll', _hitch(this, '_place'));
   }
   this.table.style.left = '0';
   this.table.style.width = '100%';
   this._resize();

   var splashTableTBody = document.createElement('TBODY');

   var splashTableRow = document.createElement('TR');

   var splashTableCol = document.createElement('TD');
   splashTableCol.style.verticalAlign = 'middle';
   splashTableCol.style.textAlign = 'center';

   var splashMsgDiv = document.createElement('DIV');
   splashMsgDiv.className = 'splashMsg';
   
   // Hide selects
   if (isIE)
   {
      var selects = document.getElementsByTagName('SELECT');
      for (var i=0; i<selects.length; i++)
      {
         label = selects[i].options[selects[i].selectedIndex].text;
         labelDiv = document.createElement('DIV');
         labelDiv.className = 'selectReplaceLabelDiv';
         labelDiv.style.display = 'inline';
         labelDiv.style.zoom = '1';
         labelDiv.style.margin = get_style(selects[i], 'margin', 'margin');
         labelDiv.style.width = selects[i].offsetWidth+'px';
         labelDiv.style.height = selects[i].offsetHeight+'px';
         labelDiv.appendChild(document.createTextNode(label));
         selects[i].parentNode.insertBefore(labelDiv,selects[i]);
         selects[i].style.display = 'none';
      }
   }

   if (this.contentNode) {
      splashMsgDiv.appendChild(this.contentNode);
   }
   
   splashTableCol.appendChild(splashMsgDiv);
   splashTableRow.appendChild(splashTableCol);
   splashTableTBody.appendChild(splashTableRow);
   this.table.appendChild(splashTableTBody);
   this.topDiv.appendChild(this.table);
   
   addEvent(window, 'resize', _hitch(this, '_resize'));
}

SplashDiv.prototype._place = function() {
   this.table.style.top = getScrollTop() + 'px';
}

SplashDiv.prototype._resize = function() {
   this.table.style.height = getViewportHeight() + 'px';
}

SplashDiv.prototype._hideComplete = function() {
   this.visibleDivs--;
   if (this.visibleDivs == 0) {
      this.topDiv.parentNode.removeChild(this.topDiv);
      this.bgDiv.parentNode.removeChild(this.bgDiv);
      this.state = 'closed';
      if (typeof(this.hideAfterFinish) == 'function') {
         this.hideAfterFinish();
      }
   }
}

SplashDiv.prototype._showComplete = function() {
   this.visibleDivs++;
   if (this.visibleDivs == 2) {
      this.state = 'opened';
      if (typeof(this.showAfterFinish) == 'function') {
         this.showAfterFinish();
      }
   }
}

function Dialog(id, contentNode, bgOpacity, bgColor, speed) {
   this.id = id;
   this.contentNode = contentNode;
   this.bgOpacity = bgOpacity;
   this.bgColor = bgColor;
   this.speed = speed;
   
   this.state = 'closed';
   this.dialogDiv = null;
   this.innerDialogDiv = null;
}

Dialog.prototype._create = function() {
   this.dialogDiv = document.createElement('DIV');
   this.dialogDiv.id = this.id + 'Dialog';
   this.dialogDiv.className = 'roundedBox dialog';
   
   this.innerDialogDiv = document.createElement('DIV');
   this.innerDialogDiv.className = 'dialogInner';
   
   closeImg = document.createElement('IMG');
   closeImg.className = 'dialogCloseImg';
   closeImg.style.cursor = 'pointer';
   closeImg.src = baseMediaUrl + '/images/windowCloseWhite.png';
   addEvent(closeImg, 'click', _hitch(this, 'hide'));
   
   this.dialogDiv.appendChild(closeImg);
   this.dialogDiv.appendChild(this.innerDialogDiv);
   if (this.contentNode) {
      this.innerDialogDiv.appendChild(this.contentNode);
   }
   
   this.splashDiv = new SplashDiv(this.dialogDiv, this.bgOpacity, this.bgColor, this.speed);
}

Dialog.prototype.setSpeed = function(speed) {
   this.speed = speed;
   if (this.splashDiv) {
      this.splashDiv.speed = speed;
   }
}

Dialog.prototype.show = function() {
   if (this.state == 'closed') {
      this._create();
      
      this.state = 'opening';
      
      this.splashDiv.show(_hitch(this, '_showComplete'));
      
      var settings = {'tl':{'radius':defaultCornerRadius},'tr':{'radius':defaultCornerRadius},'bl':{'radius':defaultCornerRadius},'br':{'radius':defaultCornerRadius},'doTopMargin':false,'doBottomMargin':false,'cornerScriptUrl':cornerScriptUrl}
      cCorners.apply(this.dialogDiv, settings);
   }
}

Dialog.prototype.hide = function() {
   if (this.state == 'opened') {
      this.state = 'hiding';
      this.splashDiv.hide(_hitch(this, '_hideComplete'));
   }
}

Dialog.prototype.destroy = function() {
   if (this.state == 'opened') {
      this.state = 'closed';
      this.splashDiv.destroy();
   }
}

Dialog.prototype._showComplete = function() {
   this.state = 'opened';
}

Dialog.prototype._hideComplete = function() {
   this.state = 'closed';
}

function exists(obj, name) {
   var p = name.split('.');
   for (var i=0; i<p.length; i++) {
      if (!(obj[p[i]])) {
         return false;
      }
      obj = obj[p[i]];
   }
   return true;
}

function getViewportHeight() {
   if (window.innerHeight){
      return window.innerHeight;
   }
   
   if (exists(document, 'documentElement.clientHeight')) {
      // IE6 Strict
      return document.documentElement.clientHeight;
   }
   
   if (document.body) {
      // IE
      return document.body.clientHeight;
   }
   
   return 0;
}

function getScrollTop() {
   return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
}

lang = {texts:{}};

lang.set = function(id, text) {
   lang.texts[id] = text;
}

lang.get = function(id) {
   if (typeof(lang.texts[id]) !== 'undefined')
   return lang.texts[id];
}

function enforceWidth(obj, fillerText) {
   if (typeof(fillerText) == 'undefined') {
      fillerText = '[...]';
   }

   try {
      var styleWidth = get_style(obj, 'width', 'width');
      if (styleWidth == 'auto' || styleWidth == '') {
         return;
      }
      
      if (obj.tagName == 'TH' || obj.tagName == 'TD') {
         var maxWidth = obj.offsetWidth;
         var entireText = obj.innerHTML;
         var truncatedText;
         var testDiv = document.createElement('DIV');
         testDiv.style.visibility = 'hidden';
         testDiv.style.position = 'absolute';
         testDiv.style.whiteSpace = 'nowrap';
         testDiv.innerHTML = entireText;
         obj.appendChild(testDiv);
         maxWidth -= 1;
         if (testDiv.offsetWidth > maxWidth) {
            testDiv.innerHTML += fillerText;
            while (testDiv.offsetWidth > maxWidth) {
               testDiv.innerHTML = testDiv.innerHTML.substr(0, (testDiv.innerHTML.length - (fillerText.length + 1))) + fillerText;
            }
            truncatedText = testDiv.innerHTML;
         }
         obj.removeChild(testDiv);
         if (truncatedText) {
            obj.setAttribute('title', entireText);
            obj.innerHTML = truncatedText;
         }
      } else {      
      
         if (styleWidth.indexOf('em') >= 0) {
            obj.style.width = 'auto';
            var testDiv = document.createElement('DIV');
            testDiv.style.visibility = 'hidden';
            testDiv.style.position = 'absolute';
            testDiv.style.left = '1em';
            testDiv.style.top = '1em';
            obj.appendChild(testDiv);
            width = (testDiv.offsetLeft * parseFloat(styleWidth));
            obj.removeChild(testDiv);
         } else if (styleWidth.indexOf('px')) {
            width = parseFloat(styleWidth);
         } else {
            throw new Error('enforceWidth cannot handle this type of unit');
         }
      
         if (obj.offsetWidth > width) {
            var textNode = obj.childNodes[obj.childNodes.length - 1];
            var entireText = textNode.nodeValue;
            textNode.nodeValue += fillerText;
            while (obj.offsetWidth > width && textNode.nodeValue != fillerText) {
               var textNode = obj.childNodes[obj.childNodes.length - 1];
               textNode.nodeValue = textNode.nodeValue.substr(0, (textNode.nodeValue.length - (fillerText.length + 1))) + fillerText;
            }
            obj.setAttribute('title', entireText);
         }
         
         if (obj.style.width == 'auto') {
            obj.style.width = styleWidth;
         }
      }
   } catch (e) {
      // Do nothing
      alert(e);
   }
}

startList = function(nodeName,className) {
   if (document.all&&document.getElementById) {
      navRoot = document.getElementById(nodeName);
      for (i=0; i<navRoot.childNodes.length; i++) {
         node = navRoot.childNodes[i];
         if (node.nodeName=="LI") {
            node.onmouseover=function() {
               addClass(this, className);
               if (isIE && verIE <= 6 && this.id == 'mainMenuItemColo') {
                  var ul = document.getElementById('mainMenuItemSubColo');
                  if (ul) {
                     ul.style.display = 'block';
                  }
               }
               else if (isIE && verIE <= 6 && this.id == 'mainMenuItemShared') {
                  var ul = document.getElementById('mainMenuItemSubShared');
                  if (ul) {
                     ul.style.display = 'block';
                  }
               }
               else if (isIE && verIE <= 6 && this.id == 'mainMenuItemDedicated') {
                  var ul = document.getElementById('mainMenuItemSubDedicated');
                  if (ul) {
                     ul.style.display = 'block';
                  }
               }
               else if (isIE && verIE <= 6 && this.id == 'mainMenuItemManaged') {
                  var ul = document.getElementById('mainMenuItemSubManaged');
                  if (ul) {
                     ul.style.display = 'block';
                  }
               }
            }
            node.onmouseout=function() {
               removeClass(this, className);
               if (isIE && verIE <= 6 && this.id == 'mainMenuItemColo') {
                  var ul = document.getElementById('mainMenuItemSubColo');
                  if (ul) {
                     ul.style.display = 'none';
                  }
               }
               else if (isIE && verIE <= 6 && this.id == 'mainMenuItemShared') {
                  var ul = document.getElementById('mainMenuItemSubShared');
                  if (ul) {
                     ul.style.display = 'none';
                  }
               }
               else if (isIE && verIE <= 6 && this.id == 'mainMenuItemDedicated') {
                  var ul = document.getElementById('mainMenuItemSubDedicated');
                  if (ul) {
                     ul.style.display = 'none';
                  }
               }
               else if (isIE && verIE <= 6 && this.id == 'mainMenuItemManaged') {
                  var ul = document.getElementById('mainMenuItemSubManaged');
                  if (ul) {
                     ul.style.display = 'none';
                  }
               }
            }
         }
      }
   }
}

function displayDD(element) {
   if (element.className == 'opened') {
      element.className = 'closed';
   } else {
      element.className = 'opened';
   }
   elementToDisplay = null;
   
   for (var i=0; i<element.parentNode.childNodes.length; i++) {
      if (element.parentNode.childNodes[i].nodeName == 'DD') {
         elementToDisplay = element.parentNode.childNodes[i];
      }
   }
   
   if (elementToDisplay.className == 'visible') {
      elementToDisplay.className = 'default';
   } else {
      elementToDisplay.className = 'visible';
   }
}

function bindGDRenders()
{
   df.registerClass("gdRender", gdRenderReplace);
   df.apply();
}

function gdRenderReplace(elem)
{
   var renderText = elem.childNodes[0].nodeValue.trim();
   var img = document.createElement('IMG');
   elem.replaceChild(img, elem.childNodes[0]);
   
   var style = new cStyles(elem);      
   
   //var img = document.createElement('IMG');
   img.src = 'http://media.iweb.com.dev/text.php' +
             '?fgColor=' + escape(style.color) +
             '&bgColor=' + escape(style.bgcolor) +
             '&fontModif=' + escape(style.fontModif) +
             '&fontSize=' + escape(style.size) +
             '&text=' + escape(renderText) +
             '&angle=0';
             
   img.alt = renderText;
   
   //elem.replaceChild(img, elem.childNodes[0]);
   elem.style.fontSize = '0pt';
}

function cStyles (elem) {
   this.color = gdFormatColor(get_style(elem, 'color', 'color'));
   this.bgcolor = gdFormatColor(get_style(elem, 'backgroundColor', 'background-color'));
      
   /*
   //Works only under firefox
   this.font = get_style(elem, 'fontFamily', 'font-family');
   this.font = this.font.split(',')[0].trim();
   this.font = this.font.replace(/["']/g, '');
   this.font = this.font.replace(/\s/g, '_');
   */
   
   this.fontModif = '';
   var weight = get_style(elem, 'fontWeight', 'font-weight'); 
   if (weight == 'bold' || (!isNaN(weight) && weight > 400)) this.fontModif += '_Bold';
   if (get_style(elem, 'fontStyle', 'font-style') == 'italic') this.fontModif += '_Italic';
   
   this.size = convertToPT(getFontSize(elem), elem);
}

function gdFormatColor(color)
{
   var retVal = color;   
   if (typeof(retVal) != 'undefined' && retVal != '')
   {
      if (retVal != 'transparent') {
         if (retVal.substring(0,3) == 'rgb') retVal = rgb2Hex(retVal);
         retVal = retVal.substring(1);
      }
   }
   else
   {
      retVal = '';
   }
   return retVal;
}

function launchSifrReplacement() {

	if(typeof sIFR == "function"){
	
	// This is the preferred "named argument" syntax
	   //sIFR.replaceElement(named({sSelector:".gdRender", sFlashSrc:baseMediaUrl+"vivaldi.swf", sColor:"#000000", sLinkColor:"#000000", sBgColor:"#FFFFFF", sHoverColor:"#CCCCCC", nPaddingTop:20, nPaddingBottom:20, sFlashVars:"textalign=center&offsetTop=6"}));
	
	// This is the older, ordered syntax
	   //sIFR.replaceElement("h5#pullquote", "vivaldi.swf", "#000000", "#000000", "#FFFFFF", "#FFFFFF", 0, 0, 0, 0);
	   sIFR.replaceElement(".gdRender", baseMediaUrl+"vivaldi.swf", "#000000", null, null, null, 0, 0, 0, 0);
	   /*sIFR.replaceElement("h4.subhead", "vivaldi.swf", "#660000", null, null, null, 0, 0, 0, 0);
	   sIFR.replaceElement("h3.sidebox","vivaldi.swf","#000000", "#000000", "#DCDCDC", "#DCDCDC", 0, 0, 0, 0, null);
	   sIFR.replaceElement("h3", "vivaldi.swf", "#000000", null, null, null, 0, 0, 0, 0, null);
	*/
	};

}