Function.prototype.bind = function(object) {
  var method = this;
  return function() {
    method.apply(object, arguments);
  }
}

var Effect = {};

Effect.clip = function(e, width, step, interv) {

  if (this.timer) {
    clearTimeout(this.timer);
  }
  
  if (!this.clipped) {
    this.clipped = true;
    this.e = $(e);
    this.interv = interv || 15;
    this.step = step || 10;
    this.width = width;
    this.left = this.right = width / 2;
    this.e.style.display = 'block';
  }  
  
  this.left = this.opened ? this.left + this.step : this.left - this.step;
  this.right = this.opened ? this.right - this.step : this.right + this.step;
  
  var rect = 'rect(auto, '+ this.right +'px, auto, '+ this.left +'px)';
  this.e.style.clip = rect;
  
  if (this.right > this.width && !this.opened) {
    this.left = 0; this.right = this.width + 5;
    this.opened = true;
    var rect = 'rect(auto, '+ this.right +'px, auto, '+ this.left +'px)';
    this.e.style.clip = rect;
    return;
  }
  
  if (this.left > this.width / 2 && this.opened) {
    this.left = this.right = this.width / 2;
    this.opened = false;
    var rect = 'rect(auto, '+ this.right +'px, auto, '+ this.left +'px)';
    this.e.style.clip = rect;
    return;
  }

  this.timer = setTimeout(Effect.clip.bind(this), this.interv);
}

Effect.appear = function(e, step, interv) {
  if (this.timer) {
    clearTimeout(this.timer);
  }
  
  if (!this.appeared) {
    this.appeared = true;
    this.e = $(e);
    this.interv = interv || 40;
    this.step = step || 1;
    this.e.style.display = 'block';
    this.opacity = 0;
  }  
  
  this.opacity = this.opened ? this.opacity - this.step : this.opacity + this.step;
  
  this.e.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity='+this.opacity+')';
  this.e.style.opacity = this.opacity / 100; 
  
  if (this.opacity >= 100 && !this.opened) {
    this.opacity = 100;
    this.opened = true;
    return;
  }
  
  if (this.opacity <= 0 && this.opened) {
    this.opacity = 0;
    this.opened = false;
    return;
  }

  this.timer = setTimeout(Effect.appear.bind(this), this.interv);
}

