﻿// 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 tmpCount = 0;
function getTempId() {
   return 'tmpId_'+(tmpCount++);
}






/*
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 + '"';
   }
};

