
// 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;
  }
}

// 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();
  },


  // 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)
      e = event;
    return e.clientX+this.getScrollLeft();
  },

  // returns the absolute position of the event in the document
  getCursorY: function(e)
  {
    if (!e)
      e = event;
    return e.clientY+this.getScrollTop();
  },

  // returns the absolute position of the event in the browserwindow
  getCursorWindowX: function(e)
  {
    if (!e)
      e = event;
    return e.clientX;
  },

  // returns the absolute position of the event in the browserwindow
  getCursorWindowY: function(e)
  {
    if (!e)
      e = event;
    return e.clientY;
  },

  // returns the absolute position of the event in the browserwindow
  // IF the function does not work on FIREFOX: DO NOT MODIFY the code, 
  //     but add a position: relative to the container !
  getCursorOffsetX: function(e)
  {
    if (!e)
      e = event;
    if(typeof(e.layerX) == 'number')
      return e.layerX;
    if(typeof(e.offsetX) == 'number')
      return e.offsetX;
  },

  // returns the absolute position of the event in the browserwindow
  // IF the function does not work on FIREFOX: DO NOT MODIFY the code, 
  //     but add a position: relative to the container !
  getCursorOffsetY: function(e)
  {
    if (!e)
      e = event;
    if(typeof(e.layerY) == 'number')
      return e.layerY;
    if(typeof(e.offsetY) == 'number')
      return e.offsetY;
  },
  
  // OBSOLETE FUNCTIONS for compatibility
  getOffsetX: function(e)
  {
    return this.getCursorOffsetX();
  },

  // returns the offset of the event in the container
  getOffsetY: function(e)
  {
    return this.getCursorOffsetY();
  },


  // 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();