
// Original idea of this function by prototype.js @ www.conio.net, improved for webability
function $()
{
  if (arguments.length == 1)
  {
    var element = arguments[0];
    if (typeof element == 'string')
      return document.getElementById(element);
  }

  var elements = new Array();

  for (var i = 0, l = arguments.length; i < l; i++)
  {
    var element = arguments[i];

    if (typeof element == 'string')
    {
      el = document.getElementById(element);
      elements.push(el);
    }
    else if (typeof element == 'object')
    {
      for (var j = 0, m = element.length; j < m; j++)
      {
        el = document.getElementById(element[j]);
        elements.push(el);
      }
    }
  }
  return elements;
}

function min()
{
  var min = +Infinity;
  for (var i = 0, l = arguments.length; i < l; i++)
  {
    if (arguments[i] < min)
      min = arguments[i];
  }
  return min;
}

function max()
{
  var max = -Infinity;
  for (var i = 0, l = arguments.length; i < l; i++)
  {
    if (arguments[i] > max)
      max = arguments[i];
  }
  return max;
}

function functionQueue()
{
  var self = this;
  this.functions = new Array();

  this.registerFunction = registerFunction;
  function registerFunction(fct)
  {
    self.functions[self.functions.length] = fct;
  }

  this.unregisterFunction = unregisterFunction;
  function unregisterFunction(fct)
  {
    for (var i = 0; i < self.functions.length; i++)
    {
    }
  }

  this.call = call;
  function call()
  {
    var args;
    if (arguments.length == 1)
      args = arguments[0];
    else
      args = arguments;

    for (var i = 0; i < self.functions.length; i++)
    {
      self.functions[i](args);
    }
  }

}

var logger =
{
  loggerwindow: null,

  __getWindow: function()
  {
    if (!this.loggerwindow)
    {
      this.loggerwindow = $('logger_window');
    }
  },

  put: function(message)
  {
    this.__getWindow();
    if (this.loggerwindow)
    {
      var text = this.loggerwindow.value;
      this.loggerwindow.value = message + "<br />\r\n" + text;
    }
  },

  clear: function()
  {
    this.__getWindow();
    if (this.loggerwindow)
    {
      this.loggerwindow.value = "";
    }
  }
}

// Date validation function
function isDate(year, month, day)
{
  var numdays = [,31,28,31,30,31,30,31,31,30,31,30,31][month];
  return day>0 && !!numdays && (day<=numdays || day==29 && year%4==0 && (year%100!=0 || year%400==0) )
}

// Hour validation function
function isHour(hour, min, sec)
{
  return hour>=0 && hour<=23 && min>=0 && min<=59 && sec>=0 && sec<=59;
}

// UTF-8 conversions

var utf8 =
{
  // public method for utf8 encoding
  encode : function (value)
  {
    value = value.replace(/\r\n/g,"\n");
    var utf = "";
    for (var i = 0, l = value.length; i < l; i++)
    {
      var c = value.charCodeAt(i);
      if (c < 128)
      {
        utf += String.fromCharCode(c);
      }
      else if((c > 127) && (c < 2048))
      {
        utf += String.fromCharCode((c >> 6) | 192);
        utf += String.fromCharCode((c & 63) | 128);
      }
      else
      {
        utf += String.fromCharCode((c >> 12) | 224);
        utf += String.fromCharCode(((c >> 6) & 63) | 128);
        utf += String.fromCharCode((c & 63) | 128);
      }
    }
    return utf;
  },

  // public method for utf8 decoding
  decode : function (value)
  {
    var str = "";
    var i = 0;
    var c1 = c2 = c3 = 0;
    while ( i < value.length )
    {
      c1 = value.charCodeAt(i);
      if (c1 < 128)
      {
        str += String.fromCharCode(c1);
        i++;
      }
      else if((c1 > 191) && (c1 < 224))
      {
        c2 = value.charCodeAt(i+1);
        str += String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
        i += 2;
      }
      else
      {
        c2 = value.charCodeAt(i+1);
        c3 = value.charCodeAt(i+2);
        str += String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
        i += 3;
      }
    }
    return str;
  }
}

// color transfer
function RGBColor(color)
{
  this.ok = false;

  if (color.charAt(0) == '#')
    color = color.substr(1,6);
  color = color.replace(/ /,'').toLowerCase();

  var htmlcolors =
  {
    black: '000000',
    silver: 'c0c0c0',
    gray: '808080',
    white: 'ffffff',
    maroon: '800000',
    red: 'ff0000',
    purple: '800080',
    fuchsia: 'ff00ff',
    green: '008000',
    lime: '00ff00',
    olive: '808000',
    yellow: 'ffff00',
    navy: '000080',
    blue: '0000ff',
    teal: '008080',
    aqua: '00ffff'
  };

  for (var name in htmlcolors)
  {
    if (color == name)
    {
      this.name = color;
      color = htmlcolors[name];
    }
  }

  var rgb = /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/.exec(color);
  if (rgb)
  {
    this.red = parseInt(rgb[1], 10);
    this.green = parseInt(rgb[2], 10);
    this.blue = parseInt(rgb[3], 10);
    this.ok = true;
  }
  else
  {
    rgb = /^(\w{2})(\w{2})(\w{2})$/.exec(color);
    if (rgb)
    {
      this.red = parseInt(rgb[1], 16);
      this.green = parseInt(rgb[2], 16);
      this.blue = parseInt(rgb[3], 16);
      this.ok = true;
    }
    else
    {
      rgb = /^(\w{1})(\w{1})(\w{1})$/.exec(color);
      if (rgb)
      {
        this.red = parseInt(rgb[1]+rgb[1], 16);
        this.green = parseInt(rgb[2]+rgb[2], 16);
        this.blue = parseInt(rgb[3]+rgb[3], 16);
        this.ok = true;
      }
    }
  }

  this.red = (this.red < 0 || isNaN(this.red)) ? 0 : ((this.red > 255) ? 255 : this.red);
  this.green = (this.green < 0 || isNaN(this.green)) ? 0 : ((this.green > 255) ? 255 : this.green);
  this.blue = (this.blue < 0 || isNaN(this.blue)) ? 0 : ((this.blue > 255) ? 255 : this.blue);

  this.toRGB = function()
  {
    return 'rgb(' + this.red + ', ' + this.green + ', ' + this.blue + ')';
  }

  this.toHex = function()
  {
    var red = this.red.toString(16);
    var green = this.green.toString(16);
    var blue = this.blue.toString(16);
    if (red.length == 1) red = '0' + red;
    if (green.length == 1) green = '0' + green;
    if (blue.length == 1) blue = '0' + blue;
    return '#' + red + green + blue;
  }
}


// Unique browser methods

var browser =
{
  https: false,
  msie: false,
  ns: false,
  safari: false,
  dom: false,
  version: null,
  zindex: 1,

  main: function()
  {
    if (document.location.href.indexOf("https")==0)
    {
      this.https=true;
    }
    if (document.getElementById && document.childNodes && document.createElement )
    {
      this.dom=true;
    }
    if ((pos=navigator.userAgent.indexOf('MSIE'))>=0)
    {
      this.msie=true;
      this.version=parseFloat(navigator.userAgent.substr(pos+4));
      return true;
    }
    if ((pos=navigator.userAgent.indexOf('Netscape6/'))>=0)
    {
      this.ns=true;
      this.version=parseFloat(navigator.userAgent.substr(pos+10));
      return true;
    }
    if ((pos=navigator.userAgent.indexOf('Safari/'))>=0)
    {
      this.safari=true;
      this.version=parseFloat(navigator.userAgent.substr(pos+7));
      return true;
    }
    if (navigator.userAgent.indexOf('Gecko')>=0)
    {
      this.ns=true;
      this.version=6.1;
      return true;
    }
    return false; // not recognized browser
  },

  isHttps: function()
  {
    return this.https;
  },

  isIE: function()
  {
    return this.msie;
  },

  isNS: function()
  {
    return this.ns;
  },

  getVersion: function()
  {
    return this.version;
  },

  // POSITIONING FUNCTIONS
  // Will return the next z.index to put things other anything already in window
  getNextZIndex: function()
  {
    return ++this.zindex;
  },

  // SIZE FUNCTIONS
  // get the size of the document
  getDocumentWidth: function()
  {
    if(this.dom && ((this.msie && this.version >= 7) || !this.msie))
      return document.documentElement.scrollWidth;
    return document.body.scrollWidth;
  },

  getDocumentHeight: function()
  {
    if(this.dom && ((this.msie && this.version >= 7) || !this.msie))
      return document.documentElement.scrollHeight;
    return document.body.scrollHeight;
  },

  getWindowWidth: function()
  {
    if (!this.msie)
      return window.innerWidth;

    if( document.documentElement && document.documentElement.clientWidth)
      return document.documentElement.clientWidth;

    if( document.body && document.body.clientWidth)
      return document.body.clientWidth;

    return 0;
  },

  getWindowHeight: function()
  {
    if (!this.msie)
      return window.innerHeight;

    if( document.documentElement && document.documentElement.clientHeight)
      return document.documentElement.clientHeight;

    if( document.body && document.body.clientHeight)
      return document.body.clientHeight;

    return 0;
  },

  // get the size of the OS/screen
  getScreenWidth: function()
  {
    return screen.width;
  },

  // get the size of the OS/screen
  getScreenHeight: function()
  {
    return screen.height;
  },

  // get the scroll of the window if bigger than the browser
  getScrollLeft: function()
  {
    // ie6 and before use BAD the documentelement on dom!
    if(this.dom && ((this.msie && this.version >= 7) || !this.msie))
      return document.documentElement.scrollLeft;

    // ie6 and before
    if(document.body && document.body.scrollLeft)
      return document.body.scrollLeft;

    // others without dom
    if(typeof(window.pageXOffset) == 'number')
      return window.pageXOffset;

    return 0;
  },

  // get the scroll of the window if bigger than the browser
  getScrollTop: function()
  {
    // ie6 and before use BAD the documentelement on dom!
    if(this.dom && ((this.msie && this.version >= 7) || !this.msie))
      return document.documentElement.scrollTop;

    // ie6 and before
    if(document.body && document.body.scrollTop)
      return document.body.scrollTop;

    // others without dom
    if(typeof(window.pageYOffset) == 'number')
      return window.pageYOffset;

    return 0;
  },

  // ==== Older compatibility functions
  getClientWidth: function()
  {
    return this.getWindowWidth();
  },

  getClientHeight: function()
  {
    return this.getWindowHeight();
  },

  // get the maximum scroll available
  getScrollWidth: function()
  {
    return this.getDocumentWidth();
  },

  // get the maximum scroll available
  getScrollHeight: function()
  {
    return this.getDocumentHeight();
  },

  // get the real width of a DOM element
  getNodeWidth: function(node)
  {
//    if (this.ns)
//      return node.clip.width;
    return node.offsetWidth;
  },

  // get the real height of a DOM element
  getNodeHeight: function(node)
  {
//    if (this.ns)
//      return node.clip.height;
    return node.offsetHeight;
  },

  // MOUSE FUNCTIONS
  // getCursorNode will return the DOM node in which the event happened
  getCursorNode: function(e)
  {
    if (!e) var e = window.event;
    if (e.target) return e.target;
    if (e.srcElement) return e.srcElement;
    return null;
  },

  // returns the absolute position of the event in the document
  getCursorX: function(e)
  {
    if (!e) var e = window.event;
    return e.clientX+this.getScrollLeft();
  },

  // returns the absolute position of the event in the document
  getCursorY: function(e)
  {
    if (!e) var e = window.event;
    return e.clientY+this.getScrollTop();
  },

  // returns the absolute position of the event in the browserwindow
  getCursorWindowX: function(e)
  {
    if (!e) var e = window.event;
    return e.clientX;
  },

  // returns the absolute position of the event in the browserwindow
  getCursorWindowY: function(e)
  {
    if (!e) var e = window.event;
    return e.clientY;
  },

  // returns the absolute position of the event in the container
  // IF the function does not work on FIREFOX: DO NOT MODIFY the code,
  //     but add a position: relative to the container !
  // FF starts the offset at 1, not at 0 !
  getCursorOffsetX: function(e)
  {
    if (!e) var e = window.event;
    if(typeof(e.layerX) == 'number')
      return e.layerX - (browser.ns?1:0);
    if(typeof(e.offsetX) == 'number')
      return e.offsetX - (browser.ns?1:0);
  },

  // returns the absolute position of the event in the container
  // IF the function does not work on FIREFOX: DO NOT MODIFY the code,
  //     but add a position: relative to the container !
  // FF starts the offset at 1, not at 0 !
  getCursorOffsetY: function(e)
  {
    if (!e) var e = window.event;
    if(typeof(e.layerY) == 'number')
      return e.layerY - (browser.ns?1:0);
    if(typeof(e.offsetY) == 'number')
      return e.offsetY - (browser.ns?1:0);
  },

  // OBSOLETE FUNCTIONS for compatibility
  getOffsetX: function(e)
  {
    return this.getCursorOffsetX(e);
  },

  // returns the offset of the event in the container
  getOffsetY: function(e)
  {
    return this.getCursorOffsetY(e);
  },

  // key functions
  getKey: function(e)
  {
    if (!e) var e = window.event;
    var key;
    if (this.msie)
      key = e.keyCode;
    else
      key = e.which;
    return key;
  },

  ifShift: function(e)
  {
    if (!e) var e = window.event;
    return e.shiftKey;
  },

  ifCtrl: function(e)
  {
    if (!e) var e = window.event;
    return e.ctrlKey;
  },

  ifAlt: function(e)
  {
    if (!e) var e = window.event;
    return e.altKey;
  },

  // click functions
  ifRightClick: function(e)
  {
    if (!e) var e = window.event;
  },

  ifCenterClick: function(e)
  {
    if (!e) var e = window.event;
  },

  ifLeftClick: function(e)
  {
    if (!e) var e = window.event;
  },

  ifDoubleRightClick: function(e)
  {
    if (!e) var e = window.event;
  },

  ifDoubleCenterClick: function(e)
  {
    if (!e) var e = window.event;
  },

  ifDoubleLeftClick: function(e)
  {
    if (!e) var e = window.event;
  },

  // SELECTION FUNCTIONS
  // select something in the document
  setSelectionRange: function(obj, selectionStart, selectionEnd)
  {
    if (obj.setSelectionRange)
    {
      obj.focus();
      obj.setSelectionRange(selectionStart, selectionEnd);
    }
    else if (obj.createTextRange)
    {
      var range = obj.createTextRange();
      range.collapse(true);
      range.moveEnd('character', selectionEnd);
      range.moveStart('character', selectionStart);
      range.select();
    }
  },

  // FILL FUNCTIONS
  // fill an innerHTML
  setInnerHTML: function(node, content)
  {
    if (this.ns) //document.getElementById && !document.all
    {
      rng = document.createRange();
      rng.setStartBefore(node);
      htmlFrag = rng.createContextualFragment(content);
      while (node.hasChildNodes())
        node.removeChild(node.lastChild);
      node.appendChild(htmlFrag);
    }
    else
    {
      node.innerHTML = content;
    }
  }

}

// We init browser object
browser.main();