var URL = '/';

var dc = {
   version: '0.1',
   isPresto: !!window.opera,
   isTrident: !!window.ActiveXObject,
   isWebkit: (navigator.userAgent.toLowerCase().indexOf("webkit") != -1),
   isGecko: (navigator.userAgent.toLowerCase().indexOf("gecko") != -1),
   isXhr: !!window.XMLHttpRequest,
   isXPath: !!document.evaluate
};
dc.isIE7 = dc.isTrident && window.XMLHttpRequest;
dc.isIE6 = dc.isTrident && !dc.isIE7;

document.head = document.getElementsByTagName('head')[0];
document.html = document.getElementsByTagName('html')[0];

if (!window.console) {
   window.console = {};
   var f = ['$', '$$', '$x', 'dir', 'dirxml', 'cd', 'clear', 'inspect', 'keys', 'values', 'debug', 'undebug', 'monitor', 'unmonitor', 'monitorEvents', 'unmonitorEvents', 'profile', 'profileEnd'];
   var i = 0;
   while (f[i++])
      window.console[f[i]] = function(){};
}

dc.extend = function(){
   var args = arguments;
   if (!args[1])
      args = [this, args[0]];
   for (var i in args[1]) {
      args[0][i] = args[1][i];
   }
   return args;
};
dc.extendNative = function(){
   for (var i = 0; i < arguments.length; ++i) {
      arguments[i].extend = function(args){
         for (var j in args) {
            if (!this.prototype[j])
               this.prototype[j] = args[j];
         }
      }
   }
};

dc.Dom = {};
dc.extend(dc.Dom, {
   scrollOffset: function(){
      var x = 0, y = 0;
      if (typeof window.pageYOffset == 'number') {
         y = window.pageYOffset;
         x = window.pageXOffset;
      }
      else
         if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
            y = document.body.scrollTop;
            x = document.body.scrollLeft;
         }
         else
            if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
               y = document.documentElement.scrollTop;
               x = document.documentElement.scrollLeft;
            }
      return {
         'x': x,
         'y': y
      };
   },
   windowSize: function(){
      var x = 0;
      var y = 0;
      if (window.innerHeight >= 0) {
         x = window.innerWidth;
         y = window.innerHeight;
      }
      else
         if (document.documentElement) {
            x = document.documentElement.clientWidth;
            y = document.documentElement.clientHeight;
         }
         else
            if (document.body.clientHeight >= 0) {
               x = document.body.clientWidth;
               y = document.body.clientHeight;
            }
      return {
         'x': x,
         'y': y
      };
   },
   getScrollWidth: function(){
      var x, y;
      y = Math.max(document.body.scrollHeight, document.body.offsetHeight);
      y = Math.max(y, document.documentElement.offsetHeight);

      x = Math.max(document.body.scrollWidth, document.body.offsetWidth);
      x = Math.max(x, document.documentElement.offsetWidth);

      return {
         'x': x,
         'y': y
      };
   }
});

var Class = function(_instance, _static){
   var _class = function(){
      return (this.init && arguments[0] !== 'noinit') ? this.init.apply(this, arguments) : this;
   }
   _class.prototype = _instance;
   _class.constructor = Class;
   _class.extend = Class.extend;
   _class.implement = Class.implement;

   return _class;
}
Class.extend = function(_ins){
   var act = new this;
   function overload(prev, act){
      return function(){
         this.base = prev;
         return act.apply(this, arguments);
      }
   }
   for (var i in _ins) {
      act[i] = (act[i] && act[i] != _ins[i] && _ins[i].apply) ? overload(act[i], _ins[i]) : _ins[i]
   }
   return Class(act)
}
Class.implement = function(){
   for (var j = 0, jl = arguments.length; j < jl; ++j)
      for (var i in arguments[j])
         this.prototype[i] = arguments[j][i];
};

dc.Events = Class({
   addEvent: function(type, fn, bind){
      if (fn) {
         this.events = this.events ||
         {};
         this.events[type] = this.events[type] || [];
         var bind = bind ? bind : this;
         this.events[type].push([fn, bind]);
      }
   },
   fireEvent: function(type, args){
      if (this.events[type]) {
         var obj = this.events[type];
         for (var i in obj)
            obj[i][0].apply(obj[i][1], [args]);
         }
   },
   removeEvent: function(type, fn){
      if (this.events && this.events[type]) {
         if (fn)
            var l = this.events[type].length;
         for (var i = 0; i < l; ++i)
            if (this.events[type][i][0] == fn) {
               delete this.events[type][i];
               --i;
            }
            else
               delete this.events[type];
      }
   }
});

dc.Event = {
   cache: [],

   addListener: function(el, eventName, fn, bind, opt){
      var i = this.indexOf(el, eventName, fn);
      if (i != -1)
         return false;
      var nFn = function(e){
         bind = bind || this;
         return fn.apply(bind, [new dc.Event.Object(e), opt]);
      };
      var l = this.cache.length;
      this.cache[l] = [el, eventName, fn, nFn];
      this.add(el, eventName, nFn);
      return true;
   },
   removeListener: function(el, eventName, fn){
      var i = this.indexOf(el, eventName, fn);
      if (i == -1)
         return false;

      fn = this.cache[i][3];
      this.remove(el, eventName, fn);
      delete this.cache[i][3];
      delete this.cache[i][2];
      this.cache.splice(i, 1);
      return true;
   },
   add: function(){
      if (window.addEventListener) {
         return function(el, eventName, fn){
            if (eventName == 'mousewheel') {
               eventName = 'DOMMouseScroll';
            }
            el.addEventListener(eventName, fn, false);
         };
      }
      else
         if (window.attachEvent) {
            return function(el, eventName, fn){
               el.attachEvent("on" + eventName, fn);
            };
         }
         else
            return function(){
            };
   }()   ,
   remove: function(){
      if (window.removeEventListener) {
         return function(el, eventName, fn){
            if (eventName == 'mousewheel') {
               eventName = 'DOMMouseScroll';
            }
            el.removeEventListener(eventName, fn, false);
         };
      }
      else
         if (window.detachEvent) {
            return function(el, eventName, fn){
               el.detachEvent("on" + eventName, fn);
            };
         }
         else
            return function(){
            };
   }(),
   removeAll: function(){
      var c;
      for (var i = 0; i < this.cache.length; ++i) {
         c = this.cache[i];
         this.remove(c[0], c[1], c[3]);
      }
      delete this.cache;
   },
   indexOf: function(el, eventName, fn){
      var tmp = null, c;
      for (var i = 0; i < this.cache.length; i++) {
         c = this.cache[i];
         if (c && c[0] == el && c[1] == eventName && c[2] == fn) {
            return i;
         }
      }
      return -1;
   },
   initDomReady: function(){
      if (!this.isInitDomReady) {
         this.isInitDomReady = true;
         this.events = this.events || new dc.Events();
         var self = this;
         var domReady = function(){
            if (self.isLoad)
               return;
            self.isLoad = true;
            self.events.fireEvent('edomReady');
         };
         if(document.readyState && window.ActiveXObject){
             document.write('<script id="ie_defer" defer src=javascript:void(0)></script>');
             document.getElementById('ie_defer').onreadystatechange = function(){
                if (this.readyState == 'complete') {
                  domReady();
                }
             };
         } else  if (document.readyState) {
               this.$timer = setInterval(function(){
                  if (/loaded|complete/.test(document.readyState)) {
                     clearInterval(this.$timer);
                     domReady();
                  }
               }, 50);
            }
            else {
               if (document.addEventListener) {
                  document.addEventListener("DOMContentLoaded", domReady, true);
               }else{
                  window.onload = domRaedy;
               }
            }
      }
   },
   domReady: function(fn, bind){
      this.initDomReady();

      if (this.isLoad)
         fn.call(bind ? bind : this);
      else
         this.events.addEvent('edomReady', fn, bind);
   },
   shellResizeFire: function(e){
      e.stop();
      var a = dc.Dom.windowSize();
      var p = this.shellOptions;
      if (!p || a.x != p.x || a.y != p.y) {
         this.events.fireEvent('eshellResize', dc.Dom.windowSize());
         this.shellOptions = a;
      }

   },
   shellResize: function(fn, bind){
      if (!this.isShellResize) {
         this.isShellResize = true;
         this.events = this.events || new dc.Events();
         dc.Event.addListener(window, 'resize', this.shellResizeFire, this);
      }
      this.events.addEvent('eshellResize', fn, bind);
   }
};
dc.domReady = dc.Event.domReady;

dc.Event.Object = Class({
   init: function(ev){

      if (ev.isExtend)
         return ev;
      ev.isExtend = true;
      ev = ev || window.event;
      this.event = ev;
      this.type = ev.type;
      this.target = ev.target || ev.srcElement;
      if (this.target && this.target.nodeType == 3)
         this.target = this.target.parentNode;

      this.shift = ev.shiftKey;
      this.crtl = ev.ctrlKey;
      this.alt = ev.altKey;
      this.meta = ev.metaKey;
      if (this.type.indexOf('mousewheel') > 0  || this.type.indexOf('DOMMouseScroll') > 0) {
         this.wheel = (ev.wheelDelta) ? ev.wheelDelta / 120 : -(ev.detail || 0) / 3;
      }
      else
         if (this.type.indexOf('key') > 0) {
            this.code = ev.which || ev.keyCode;
            var k = dc.Event.Keys;
            for (var i in k) {
               if (k[i] == this.code) {
                  this.key = i;
                  break;
               }
            }
         } else  if (/(click|mouse)/.test(this.type)) {
               this.page = {
                  'x': ev.pageX || ev.clientX + document.documentElement.scrollLeft,
                  'y': ev.pageY || ev.clientY + document.documentElement.scrollTop
               };
               this.client = {
                  'x': ev.pageX ? ev.pageX - window.pageXOffset : ev.clientX,
                  'y': ev.pageY ? ev.pageY - window.pageYOffset : ev.clientY
               };
               this.rightClick = (ev.which == 3) || (ev.button == 2);
               this.checkRelated();
            }

   },
   stop: function(){
      this.stopPropagation();
      this.stopDefault();
   },
   stopPropagation: function(){
      if (this.event.stopPropagation)
         this.event.stopPropagation();
      else
         this.event.cancelBubble = true;
   },
   stopDefault: function(){
      if (this.event.preventDefault)
         this.event.preventDefault();
      else
         this.event.returnValue = false;
   },
   checkRelated: function(){
      var ev = this.event;
      var r = ev.relatedTarget;
      if (!r) {
         switch (this.type) {
            case 'mouseover':
               r = ev.fromElement;
            case 'mouseout':
               r = ev.toElement;
         }
      }
      this.relatedTarget = r;
   }
});
dc.Event.Keys = {
   'enter': 13,
   'up': 38,
   'down': 40,
   'left': 37,
   'right': 39,
   'esc': 27,
   'space': 32,
   'backspace': 8,
   'tab': 9,
   'delete': 46
};
var App = Class({
   setOptions: function(opt){
      var def = this.options;
      this.options = {};
      for (var i in def) {
         this.options[i] = opt && opt[i] ? opt[i] : def[i];
      }
   },
   addListener: function(obj){
      if (!this.listeners)
         this.listeners = [this];
      this.listeners[this.listeners.length] = obj;

      return this;
   },
   fireEvent: function(fn, attr){
      for (var i = 0, len = this.listeners.length; i < len; ++i) {
         if (this.listeners[i][fn]) {
            this.listeners[i][fn](attr);
         }
      }
   }
});

dc.Tween = App.extend({
   options: {
      duration: 500,
      fps: 30,
      type: function(p){
         return -(Math.cos(Math.PI * p) - 1) / 2; // down
         return (Math.sin(Math.PI * p / 2));// down2
         return (Math.pow(p, 2)); //up
         return p; //line
      }
   },
   init: function(opt){
      this.setOptions(opt);
      this.isTween = false;
   },
   start: function(from, to){
      if(this.isTween) this.stop(true);
      this.isTween = true;
      this.from = from;
      this.to = to;
      this.distance = this.to - this.from;
      var self = this;
      this.time = new Date().getTime();
      this.timer = setInterval(function(){
         self.step();
      }, 1000 / this.options.fps);
      this.fireEvent('onStart');
   },
   stop: function(normal){
      this.isTween = false;
      clearInterval(this.timer);
      this.timer = null;
      if (!normal) {
         this.fireEvent('onCancel');
      }
   },
   back: function(){
      this.stop(true);
      this.start(this.now, this.from);
   },
   step: function(){
      var time = new Date().getTime();
      if (time < this.time + this.options.duration) {
         this.now = this.from + this.distance * this.options.type((time - this.time) / this.options.duration);
         this.fireEvent('onStep',this.now);
      }
      else {
         this.stop(true);
         this.now = this.to;
         this.fireEvent('onStep',this.now);
         this.fireEvent('onComplete');
      }
   },
   onSte2p: function(){
      //use this.now;
   }
});

function $type(obj){
   if(!obj) return null;
   if(obj.nodeName){
      switch(obj.nodeType){
         case 1 : return 'element';
         case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
      }
   }
   var type = typeof obj;
   if(type == 'object'){
      switch(obj.constructor){
         case Array: return 'array';
         case RegExp: return 'regexp';
         case Class: return 'class';
      }
   }
   return type;
}
function $(el,test){
   if(!el) return null;
   return (typeof el == 'string') ? document.getElementById(el) : el;
}