$small_js = function(el){
  this.fps = 60;
  this.duration = 500;
  this.time = null;
  this.frame = 0;

  this.addEvent = function (elem, evType, fn) {
    if (elem.addEventListener){
      elem.addEventListener(evType, fn, false)
      return fn;
    }

    iefn = function() { fn.call(elem,event) } 
    elem.attachEvent('on' + evType, iefn);
    return iefn;
  }

  this.removeEvent = function (elem, evType, fn) {
    if (elem.addEventListener) {
      elem.removeEventListener(evType, fn, false)
      return;
    }
   
    elem.detachEvent('on' + evType, fn)
  }

  this.addClass = function (o, c){
      var re = new RegExp("(^|\\s)" + c + "(\\s|$)", "g")
      if (re.test(o.className)) return
      o.className = (o.className + " " + c).replace(/\s+/g, " ").replace(/(^ | $)/g, "")
  }
 
  this.removeClass = function (o, c){
      var re = new RegExp("(^|\\s)" + c + "(\\s|$)", "g")
      o.className = o.className.replace(re, "$1").replace(/\s+/g, " ").replace(/(^ | $)/g, "")
  }

  this.$e = function(el){
    this.el = el;
    return this;
  }

  this.getPos = function(el){
    var curleft = 0;
    var curtop = 0;

    if (el.offsetParent) {
      do {
          curleft += el.offsetLeft;
          curtop += el.offsetTop;
         } while (el = el.offsetParent);
      return {x:curleft,y:curtop};
    }
  }

  this.$ = function(el){
    //here return element
    this.el = document.getElementById(el);
    return this;
  }

  this.$$ = function(classList, node){
    if(document.getElementsByClassName) {
      return (node || document).getElementsByClassName(classList)
    } else {      
      var node = node || document,
      list = node.getElementsByTagName('*'), 
      length = list.length,  
      classArray = classList.split(/\s+/), 
      classes = classArray.length, 
      result = [], i,j
      for(i = 0; i < length; i++) {
        for(j = 0; j < classes; j++)  {
          if(list[i].className.search('\\b' + classArray[j] + '\\b') != -1) {
            result.push(list[i])
            break
          }
        }
      }
      return result
    }
  }

  this.fade = function(v, fn){
    //here set from to
    //this.value = v;
    if(fn == 'undefined'){
      this.callback = false;
    }else{
      this.callback = fn;
    }
    this.prop = 'opacity';
    if(v == 1){
      this.start(0,1);
    }else{
      this.start(1,0);
    }
  }

  this.opacity = function(v){
    var hasOpacity = (document.body.style.opacity != null);
    var reAlpha = /alpha\(opacity=([\d.]+)\)/i;

    if (hasOpacity){
      this.el.style.opacity = v;
    }else{
      opacity = Math.min(100, Math.max(0, (v * 100))).round();
      opacity = (opacity == 100) ? '' : 'alpha(opacity=' + opacity + ')';
      var filter = this.el.style.filter || '';
      this.el.style.filter = reAlpha.test(filter) ? filter.replace(reAlpha, opacity) : filter + opacity;
    }
  }

  this.start = function(from,to){
    this.from = from;
    this.to = to;
    this.frameInterval = 1000 / this.fps;
    this.frames = Math.round(this.duration / this.frameInterval);
    this.instance(this.fps);
  }

  this.stop = function(){
    clearInterval(this.int);
    if(this.callback){
      this.callback.call();
    }
  }

  this.instance = function(fps){
    this.int = setInterval(this.pass(this.loop,[], this),Math.round(1000 / this.fps));
  }

  this.pass = function(func, args, bind){
    var self = func;
    return function(){
      return self.apply(bind, args || arguments);
    };
  }

  this.loop = function(){
    var now = Date.now();
    this.step(now);
  }

  this.set = function(v){
    if(this.prop == 'opacity'){
      this.opacity(v);
    }
  }

  this.transition = function(pos){
    return (pos <= 0.5 ? this.trans(2 * pos) : (2 - this.trans(2 * (1 - pos)))) / 2;
  }

  this.trans = function(v){
    return 1 - Math.cos(v * Math.PI / 2);
  }

  this.step = function(now){
    var diff = (this.time != null) ? (now - this.time) : 0, frames = diff / this.frameInterval;
    this.time = now;
    this.frame += frames;
    
    if (this.frame < this.frames){
      t = this.transition(this.frame / this.frames);
      var delta = (t <= 0.5 ? this.trans(1 - Math.cos((2 * t) * Math.PI / 2)) : (2 - this.trans(1 - Math.cos((2 * (1 - t)) * Math.PI / 2)))) / 2;
      this.set((this.to - this.from) * delta + this.from);
    }else{
      this.frame = this.frames;
      this.set((this.to - this.from) * 1 + this.from);
      this.stop();
    }
    
  }

  this.ret = function(){
    return this;
  }

  this.open_dialog_local = function(header,text,callback,e){
    r = {
      readyState:4,
      status:200,
      responseText:'<div class="header">'+header+'<a class="close" style="color:white;float:right;cursor:pointer;">Close X</a></div><div class="content">'+text+'</div>'
    }

    $sj.process_dialog.apply(r,[r,callback]);
    return this;
  }

  this.open_dialog = function(url,callback,e){
    this.transport = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
    this.transport.open('GET', url, true);
    this.transport.vars=this.options;
    if(callback != undefined){
      this.transport.onreadystatechange=function(r){
        $sj.process_dialog.apply(this,[this,callback]);
      }
    }else{
      this.transport.onreadystatechange=this.process_dialog;
    }
    this.transport.send();
    return this;
  }

  this.close_dialog = function(e){
    el = e.target || e.srcElement;
    var el = el.parentNode.parentNode;
    new $small_js().$e(el).fade(0,function(){
      el.parentNode.removeChild(el);
    });
  }

  this.close_dialog_direct = function(el){
    new $small_js().$e(el).fade(0,function(){
      el.parentNode.removeChild(el);
    });
  }

  this.process_dialog = function(r,callback){
    if (this.readyState != 4) return;
    if (this.status != 200) return;

    el = document.createElement('div');
    el.className = 'dialog_inline_window';
    el.innerHTML = this.responseText;

    $sj.addEvent($sj.$$('close', el)[0], 'click', function(e){
      $sj.close_dialog(e);
      return false;
    });

    if(!window.innerWidth)
    {
      //strict mode
      if(!(document.documentElement.clientWidth == 0))
      {
        w = document.documentElement.clientWidth;
        h = document.documentElement.clientHeight;
      }
      //quirks mode
      else
      {
        w = document.body.clientWidth;
        h = document.body.clientHeight;
      }
    }
    //w3c
    else
    {
      w = window.innerWidth;
      h = window.innerHeight;
    }
  
    //get scroll size
      if(typeof pageYOffset!= 'undefined'){
          //most browsers
          h_of = pageYOffset;
      }
      else{
          var B= document.body; //IE 'quirks'
          var D= document.documentElement; //IE with doctype
          D= (D.clientHeight)? D: B;
          h_of =  D.scrollTop;
      }
    //

    el.style.top = h_of+100+'px';
    el.style.left = w/2-250+'px';
    el.style.zIndex = 9999;
    $sj.$e(el).opacity(0);
    document.body.appendChild(el);
    
    new $small_js().$e(el).fade(1);
    
    if(callback != undefined){
      callback(el);
    }
  }

};

$sj = new $small_js();

if(!Date.now){  
  Date.now = function now() {  
    return +new Date();  
  };  
}
