var Class = {
  create: function() {
    return function() { 
      this.initialize.apply(this, arguments);
    }
  }
}

var Abstract = new Object();

Object.extend = function(destination, source) {
  for (property in source) {
    destination[property] = source[property];
  }
  return destination;
}

Object.inspect = function(object) {
  try {
    if (object == undefined) return 'undefined';
    if (object == null) return 'null';
    return object.inspect ? object.inspect() : object.toString();
  } catch (e) {
    if (e instanceof RangeError) return '...';
    throw e;
  }
}

Function.prototype.bind = function() {
  var __method = this, args = $A(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
}

Function.prototype.bindAsEventListener = function(object) {
  var __method = this;
  return function(event) {
    return __method.call(object, event || window.event);
  }
}

Object.extend(Number.prototype, {
  toColorPart: function() {
    var digits = this.toString(16);
    if (this < 16) return '0' + digits;
    return digits;
  },

  succ: function() {
    return this + 1;
  },
  
  times: function(iterator) {
    $R(0, this, true).each(iterator);
    return this;
  }
});

var Try = {
  these: function() {
    var returnValue;

    for (var i = 0; i < arguments.length; i++) {
      var lambda = arguments[i];
      try {
        returnValue = lambda();
        break;
      } catch (e) {}
    }

    return returnValue;
  }
}

/*--------------------------------------------------------------------------*/

var PeriodicalExecuter = Class.create();
PeriodicalExecuter.prototype = {
  initialize: function(callback, frequency) {
    this.callback = callback;
    this.frequency = frequency;
    this.currentlyExecuting = false;

    this.registerCallback();
  },

  registerCallback: function() {
    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  },

  onTimerEvent: function() {
    if (!this.currentlyExecuting) {
      try { 
        this.currentlyExecuting = true;
        this.callback(); 
      } finally { 
        this.currentlyExecuting = false;
      }
    }
  }
}

/*--------------------------------------------------------------------------*/

function $() {
  var elements = new Array();

  for (var i = 0; i < arguments.length; i++) {
    var element = arguments[i];
    if (typeof element == 'string')
      element = document.getElementById(element);

    if (arguments.length == 1) 
      return element;

    elements.push(element);
  }

  return elements;
}

//extract from Position.js
var Position={
    cumulativeOffset: function(element) {
        var valueT = 0, valueL = 0;
        do {
          valueT += element.offsetTop  || 0;
          valueL += element.offsetLeft || 0;
          element = element.offsetParent;
        } while (element);
        return [valueL, valueT];
    },
    center:function(width,height,doc){
        if(doc) this.doc=doc;
        var theBody=this.doc.getElementsByTagName('BODY')[0]; 
        //theBody.style.overflow='hidden';
        var scTop = this.scrollTop();
        var scLeft = this.scrollLeft();
        var fullHeight = this.fullHeight();
        var fullWidth = this.fullWidth();
        var _top=scTop + ((fullHeight - (height+20)) / 2);
        return [
            scLeft + ((fullWidth - width) / 2),
            _top<0?scTop:_top
        ];
    },
    scrollTop:function(){
        if(document.documentElement && document.documentElement.scrollTop) return this.doc.documentElement.scrollTop;
        else return this.doc.body.scrollTop;
    },
    scrollLeft:function(){
        if(document.documentElement && document.documentElement.scrollLeft) return this.doc.documentElement.scrollLeft;
        else return this.doc.body.scrollLeft;
    },
    fullHeight:function(){
        if (window.innerHeight!=window.undefined) return window.innerHeight;
        if (document.documentElement && document.documentElement.clientHeight) return this.doc.documentElement.clientHeight;
        if (document.body) return this.doc.body.clientHeight; 
        return window.undefined; 
    },
    fullWidth:function() {
        if (window.innerWidth!=window.undefined) return window.innerWidth; 
        if (document.documentElement && document.documentElement.clientWidth) return this.doc.documentElement.clientWidth; 
        if (document.body) return this.doc.body.clientWidth; 
        return window.undefined; 
    },
    doc:document
}

// Safari returns margins on body which is incorrect if the child is absolutely
// positioned.  For performance reasons, redefine Position.cumulativeOffset for
// KHTML/WebKit only.
function camelize(style) {
    var parts = style.split('-'), len = parts.length;
    if (len == 1) return parts[0];

    var camelized = style.charAt(0) == '-'
      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
      : parts[0];

    for (var i = 1; i < len; i++)
      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);

    return camelized;
  }
function getStyle(element, style) {
    element = $(element);
    style = style == 'float' ? 'cssFloat' : camelize(style);
    var value = element.style[style];
    if (!value) {
      var css = document.defaultView.getComputedStyle(element, null);
      value = css ? css[style] : null;
    }
    if (style == 'opacity') return value ? parseFloat(value) : 1.0;
    return value == 'auto' ? null : value;
  }
  
if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
  Position.cumulativeOffset = function(element) {
    //alert(camelize('position'));
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      if (element.offsetParent == document.body)
        //if (Element.getStyle(element, 'position') == 'absolute') break;
        if (getStyle(element, 'position') == 'absolute') break;
      element = element.offsetParent;
    } while (element);
    //alert(valueL);
    return [valueL, valueT];
  }
}


var Request=Object.extend({},{
    querystring:function(key){
        var _query=window.location.search.substring(1).toLowerCase();
        var _key=key.toLowerCase();
        var params=_query.split('&');
        for(var i=0;i<params.length;i++){
            var pair=params[i].split('=');
            if(pair[0]==_key) return pair[1];
        }
        return false;
    }
})

var GUID={
    newGuid:function(){
        var g ='';
        for(var i = 0; i < 16; i++)
        g += Math.floor(Math.random() * 0xF).toString(0xF) + (i == 8 || i == 12 || i == 16 || i == 20 ? "-" : "")
        return g;
    }
};



