Position.includeScrollOffsets = true;

var Engine = {
  detect: function() {
    var UA = navigator.userAgent;
    this.isKHTML = /Konqueror|Safari|KHTML/.test(UA);
    this.isGecko = (/Gecko/.test(UA) && !this.isKHTML);
    this.isOpera = /Opera/.test(UA);
    this.isMSIE  = (/MSIE/.test(UA) && !this.isOpera);
    this.isMSIE7 = this.isMSIE && !(/MSIE 6\./.test(UA) && !this.isOpera);
  }
}
Engine.detect();

Position.getPageSize = function() {
  var xScroll, yScroll;

  if (window.scrollMaxX) {  
    xScroll = window.innerWidth  + window.scrollMaxX;
    yScroll = window.innerHeight + window.scrollMaxY;
  } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
    xScroll = document.body.scrollWidth;
    yScroll = document.body.scrollHeight;
  } 
  
  var windowWidth, windowHeight;
  if (self.innerHeight) { // all except Explorer
    windowWidth = self.innerWidth;
    windowHeight = self.innerHeight;
  } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
    windowWidth = document.documentElement.clientWidth;
    windowHeight = document.documentElement.clientHeight;
  } else if (document.body) { // other Explorers
    windowWidth = document.body.clientWidth;
    windowHeight = document.body.clientHeight;
  } 

  // for small pages with total height less then height of the viewport
  pageHeight = Math.max(windowHeight, yScroll);

  // for small pages with total width less then width of the viewport
  pageWidth = Math.max(windowWidth, xScroll);

  return { page: { width: pageWidth, height: pageHeight }, window: { width: windowWidth, height: windowHeight } };
}

Position.scrollX = function(){
  return (window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0);
}

var Loader = {
  _assets: $H({}),
  _checkInterval: null,
  _options: {},
  _update: function() {
    var allLoaded = true;
    Loader._assets.each(function(a){
      if(!a[1].complete && a[1].image.complete) {
        a[1].complete = true;
        a[1].completed_at = new Date().getTime();;
        if(a[1].options.onComplete) a[1].options.onComplete(a[0]);
      }
      if(!a[1].complete && !a[1].image.complete) allLoaded = false;
    });
    if(allLoaded) {
      clearInterval(Loader._checkInterval);
      Loader._checkInterval = null;
      if(Loader._options && Loader._options.onComplete) Loader._options.onComplete();
      Loader._options = null;
    }
  },
  initialize: function() {
    var options = arguments[0] || {};
    Loader._options = options;
  },
  load: function(url) {
    if(Loader._assets[url]) return;
    var options = arguments[1] || {};
    var a = {};
    a.image = new Image();
    a.image.src = url;
    a.complete = false;
    a.options  = options;
    a.loaded_at = new Date().getTime();
    Loader._assets[url] = a;
    if(!Loader._checkInterval) Loader._checkInterval = setInterval(Loader._update,10);
  },
  stats: function(url) {
    return (Loader._assets[url]._complete ?
      (Loader._assets[url]._completed_at - Loader._assets[url]._loaded_at) : null);
  },
  isLoaded: function(url) {
    return (Loader._assets[url] && Loader._assets[url].complete);
  }
}

Event.localPointer = function(event){
  var p = [Event.pointerX(event), Event.pointerY(event)];
  var element = arguments[1] || Event.element(event);
  var e = Position.page($(element));
  return [
    p[0]-(e[0]+(window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0)),
    p[1]-(e[1]+(window.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop  || 0))];
}

var Xml = {
  removeWhitespace: function(xmldoc) {
    for (var i = 0; i < xmldoc.childNodes.length; i++)	{
      var curNode = xmldoc.childNodes[i];
      if(curNode.nodeType==1) Xml.removeWhitespace(curNode);
      if (((/^\s+$/.test(curNode.nodeValue))) && (curNode.nodeType == 3))
        xmldoc.removeChild(xmldoc.childNodes[i--]);
    }
  }
}