var Runners = [];
var Runner;
var IE = false, IE6 = false;

function RunEffect(el, effect, obj){
  if(IE6) return true;
  if(!Effects[effect]) return;
  if(typeof(el) !== "object"){
    if(el[0] == "#"){
      if(!(el = document.getElementById(el.substring(1,el.length)))) return;
    }else return;
  }
  if(typeof(obj) !== "object") obj = {};

  el.effect = new Effects[effect]();
  el.effect.el = el;
  LoadConf(el.effect,obj,'speed',1000);
  LoadConf(el.effect,obj,'callback',null);
  if(typeof(el.effect.conf) === 'object')
    for(var i in el.effect.conf) LoadConf(el.effect,obj,i,el.effect.conf[i]);

  if(typeof(el.effect.Pre) === "function") el.effect.Pre();

  el.finished = false;
  el.effect.last = Number(new Date());
  el.effect.start = Number(new Date());
  AddRunner(el);
}

function AddRunner(el){
  for(var i=0; i<Runners.length; i++) if(Runners[i] === el) RemoveRunner(el);
  Runners.push(el);
  if(Runners.length == 1) Runner = setInterval(function(){RunEffects();},10);
}
function RemoveRunner(el){
  for(var i=0; i<Runners.length; i++)
    if(Runners[i] === el){
      Runners.splice(i,1);
      break;
    }
  if(!Runners.length) clearInterval(Runner);
}

function RunEffects(){
  var el;
  var t = Number(new Date());
  for(var i=0;i<Runners.length; i++){
    el = Runners[i];
    el.effect.Run(t-el.effect.start, t-el.effect.last);
    el.effect.last = t;
    StopEffect(el, false);
  }
}

function StopEffect(el){
  if(el.effect.finished){
    var callback;
    RemoveRunner(el);
    if(typeof(el.effect.Post) === "function") el.effect.Post();
    if(el.effect.callback) callback = el.effect.callback;
    el.effect = undefined;
    if(typeof(callback) == 'function') callback(el);
  }
}

function LoadConf(el, conf, key, val){
  if(typeof(conf[key]) !== 'undefined') el[key] = conf[key];
  else el[key] = val;
}

function changeOpac(obj,opacity){
  if(!obj || !obj.style) return;
  obj.style.opacity=(opacity/100);
  obj.style.MozOpacity=(opacity/100);
  obj.style.KhtmlOpacity=(opacity/100);
  obj.style.filter="alpha(opacity="+opacity+");";
}

var Effects = {
  "fadeIn": function(){
    this.conf = {"min": 0, "max": 100},
    this.Pre = function(){
      if(!this.el.style.opacity) changeOpac(this.el,0);
    },
    this.Run = function(t,tt){
      var opac = Math.round(Math.min(this.el.style.opacity*100+tt*(this.max-this.min)/this.speed,this.max));
      changeOpac(this.el, opac);
      if(opac >= this.max) this.finished = true;
    };
  },
  "fadeOut": function(){
    this.conf = {"min": 0, "max": 100},
    this.Pre = function(){
      if(!this.el.style.opacity) changeOpac(this.el,100);
    },
    this.Run = function(t,tt){
      var opac = Math.round(Math.max(this.el.style.opacity*100-tt*(this.max-this.min)/this.speed,this.min));
      changeOpac(this.el, opac);
      if(opac <= this.min) this.finished = true;
    };
  },
  "move": function(){
    this.conf = {"min": 0, "max": 100, "f": function(r){return r*r;}},
    this.Pre = function(){
      this.el.style.left = this.min+"px";
    },
    this.Run = function(t,tt){
      var ratio = Math.min(this.f(t/this.speed), 1);
      var pos = Math.round(this.min+ratio*(this.max-this.min));
      this.el.style.left = pos+"px";
      if(ratio >= 1) this.finished = true;
    },
    this.Post = function(){
      this.el.style.left = this.max+"px";
    }
  },
  "moveOut": function(){
    this.conf = {"side": "down", "f": function(r){return r*r;}},
    this.Pre = function(){
      this.width = this.el.offsetWidth;
      this.height = this.el.offsetHeight;
      this.el.style.position = 'relative';
      this.el.style.width = this.width+'px';
      this.el.style.height = this.height+'px';
      this.el.style.overflow = 'hidden';
      this.to = document.createElement('div');
      this.to.style.width = this.width+'px';
      this.to.style.height = this.height+'px';
      this.to.style.position = 'absolute';
      this.to.style.top = '0px';
      this.to.style.left = '0px';
      var el;
      while(this.el.firstChild && (el = this.el.removeChild(this.el.firstChild))) this.to.appendChild(el);
      this.el.appendChild(this.to);
    },
    this.Run = function(t,tt){
      var top = 0, left = 0;
      var ratio = this.f(Math.min(1,t/this.speed));
      switch(this.side){
        case "down":
          top = this.height*ratio;
          break;
        case "up":
          top = -this.height*ratio;
          break;
        case "left":
          left = -this.width*ratio;
          break;
        case "right":
          left = this.width*ratio;
          break;
      }
      this.to.style.top = top+'px';
      this.to.style.left = left+'px';
      if(ratio >= 1) this.finished = true;
    },
    this.Post = function(){
      this.el.removeChild(this.to);
    };
  },
  "moveIn": function(){
    this.conf = {"side": "up","html": '', "dom": null, "f": function(r){return r*r;}},
    this.Pre = function(){
      this.width = this.el.offsetWidth;
      this.height = this.el.offsetHeight;
      this.el.style.position = 'relative';
      this.el.style.width = this.width+'px';
      this.el.style.height = this.height+'px';
      this.el.style.overflow = 'hidden';
      if(this.dom){
        this.to = this.dom;
      }else{
        this.to = document.createElement('div');
        this.to.innerHTML = this.html;
      }
      this.to.style.visibility = '';
      this.to.style.width = this.width+'px';
      this.to.style.height = this.height+'px';
      this.to.style.position = 'absolute';
      var top = 0, left = 0;
      switch(this.side){
        case "down":
          top = this.height;
          break;
        case "up":
          top = -this.height;
          break;
        case "left":
          left = -this.width;
          break;
        case "right":
          left = this.width;
          break;
      }
      this.to.style.top = top+'px';
      this.to.style.left = left+'px';
      while(this.el.firstChild) this.el.removeChild(this.el.firstChild);
      this.el.appendChild(this.to);
    },
    this.Run = function(t,tt){
      var top = 0, left = 0;
      var ratio = this.f(1-Math.min(1,t/this.speed));
      switch(this.side){
        case "down":
          top = this.height*ratio;
          break;
        case "up":
          top = -this.height*ratio;
          break;
        case "left":
          left = -this.width*ratio;
          break;
        case "right":
          left = this.width*ratio;
          break;
      }
      this.to.style.top = top+'px';
      this.to.style.left = left+'px';
      if(ratio <= 0) this.finished = true;
    },
    this.Post = function(){
      var el;
      while(this.to.firstChild && (el = this.to.removeChild(this.to.firstChild))) this.el.appendChild(el);
      this.el.removeChild(this.to);
    };
  },
  "roll": function(){
    this.conf = {"side": "top", "f": function(r){return r*r;}, "from": 0, "to": 240, "padding": null},
    this.Pre = function(){
      var result = this.from;
      switch(this.side){
        case "top":
        case "bottom":
          this.el.style.overflowY = 'hidden';
          if(this.padding instanceof Array){
            if(result <= this.padding[0]){
              this.el.style.paddingTop = result+'px';
              this.el.style.height = '0px';
              this.el.style.paddingBottom = '0px';
            }else if((this.to > this.from && result <= this.to-this.padding[2]) || (this.to < this.from && result >= this.padding[0])){
              this.el.style.paddingTop = this.padding[0]+'px';
              this.el.style.height = (result-this.padding[0])+'px';
              this.el.style.paddingBottom = '0px';
            }else{
              this.el.style.paddingTop = this.padding[0]+'px';
              this.el.style.height = (this.to-this.padding[0]-this.padding[2])+'px';
              this.el.style.paddingBottom = (this.padding[2] - Math.min(Math.abs(this.to-result),Math.abs(this.from-result)))+'px';
            }
          }else{
            this.el.style.height = result+'px';
          }
          break;
        case "left":
        case "right":
          this.el.style.overflowX = 'hidden';
          if(this.padding instanceof Array){
            if(result <= this.padding[4]){
              this.el.style.paddingLeft = result+'px';
              this.el.style.width = '0px';
              this.el.style.paddingRight = '0px';
            }else if((this.to > this.from && result <= this.to-this.padding[1]) || (this.to < this.from && result >= this.padding[4])){
              this.el.style.paddingLeft = this.padding[4]+'px';
              this.el.style.width = (result-this.padding[4])+'px';
              this.el.style.paddingRight = '0px';
            }else{
              this.el.style.paddingLeft = this.padding[4]+'px';
              this.el.style.width = (this.to-this.padding[4]-this.padding[1])+'px';
              this.el.style.paddingright = (result - this.to + this.padding[1])+'px';
            }
          }else{
            this.el.style.width = result+'px';
          }
          break;
      }
      if(this.el.style.display == 'none') this.el.style.display = '';
    },
    this.Run = function(t,tt){
      var top = 0, left = 0;
      var ratio = this.f(Math.min(1,t/this.speed));
      var result = Math.round(this.from+(this.to-this.from)*ratio);
      switch(this.side){
        case "top":
        case "bottom":
          if(this.padding instanceof Array){
            if(result <= this.padding[0]){
              this.el.style.paddingTop = result+'px';
            }else if((this.to > this.from && result <= this.to-this.padding[2]) || (this.to < this.from && result >= this.padding[0])){
              this.el.style.paddingTop = this.padding[0]+'px';
              this.el.style.height = (result-this.padding[0])+'px';
            }else{
              this.el.style.paddingTop = this.padding[0]+'px';
              this.el.style.height = (this.to-this.padding[0]-this.padding[2])+'px';
              this.el.style.paddingBottom = (this.padding[2] - Math.min(Math.abs(this.to-result),Math.abs(this.from-result)))+'px';
            }
          }else{
            this.el.style.height = result+'px';
          }
          break;
        case "left":
        case "right":
          if(this.padding instanceof Array){
            if(result <= this.padding[4]){
              this.el.style.paddingLeft = result+'px';
            }else if((this.to > this.from && result <= this.to-this.padding[1]) || (this.to < this.from && result >= this.padding[4])){
              this.el.style.paddingLeft = this.padding[4]+'px';
              this.el.style.width = (result-this.padding[4])+'px';
            }else{
              this.el.style.paddingLeft = this.padding[4]+'px';
              this.el.style.width = (this.to-this.padding[4]-this.padding[1])+'px';
              this.el.style.paddingright = (this.padding[1] - Math.min(Math.abs(this.to-result),Math.abs(this.from-result)))+'px';
            }
          }else{
            this.el.style.width = result+'px';
          }
          break;
      }
      if(ratio >= 1) this.finished = true;
    },
    this.Post = function(){
      this.el.style.padding = '';
      this.el.style.width = '';
      this.el.style.height = '';
      this.el.style.overflow = '';
    };
  },
  "scroll": function(){
    this.conf = {"f": function(r){return 0.5-Math.cos(Math.PI*r)/2;}, "to": 'formdiv'},
    this.Pre = function(){
      if(typeof( window.innerHeight ) == 'number'){
        this.winHeight = window.innerHeight;
      }else if(document.documentElement && document.documentElement.clientHeight){
        this.winHeight = document.documentElement.clientHeight;
      }
      var el;
      if(typeof(this.to) != 'object')
        el = document.getElementById(this.to);
      else
        el = this.to;
      var hei = el.offsetHeight;
      var fromtop = 0;
      do{
        fromtop += el.offsetTop;
      }while(el = el.offsetParent);
      fromtop -= Math.max(0,(this.winHeight-hei)/2);
      this.scrollHeight = fromtop > document.body.scrollHeight ? document.body.scrollHeight : fromtop;
      if(typeof(window.pageYOffset) == 'number'){
        this.scrollY = window.pageYOffset;
        this.scrollX = window.pageXOffset;
      }else if(document.body && document.body.scrollTop){
        this.scrollY = document.body.scrollTop;
        this.scrollX = document.body.scrollLeft;
      }else if(document.documentElement && document.documentElement.scrollTop){
        this.scrollY = document.documentElement.scrollTop;
        this.scrollX = document.documentElement.scrollLeft;
      }
      this.nowY = this.scrollY;
    },
    this.Run = function(t,tt){
      var ratio = this.f(Math.min(1,t/this.speed));
      this.nowY = Math.round(this.scrollY+(this.scrollHeight-this.scrollY)*ratio);
      window.scrollTo(this.scrollX,this.nowY);
      if(ratio >= 1) this.finished = true;
    };
  }
};
