Boxable = Class.create();
Boxable.prototype = {
  initialize: function(element) {
    var options = {
      handle: false,
      left: 0,
      right: 0,
      top: 0,
      bottom: 0,
      endeffect: false
    }.extend(arguments[1] || {});
    
    this.element      = $(element);
    this.element.drag = this;
    this.handle       = options.handle ? $(options.handle) : this.element;
    
	this.offsetTop = 0;
	this.offsetLeft = 0;

	var oo = this.element;
	while (oo.tagName != 'BODY' && oo.tagName != 'HTML') {
		if (oo.offsetTop) this.offsetTop += oo.offsetTop;
		if (oo.offsetLeft) this.offsetLeft += oo.offsetLeft;
		oo = oo.offsetParent;
	}
	
    this.startX       = 0;
    this.startY       = 0;
    
    this.left         = options.left;
    this.right        = options.right;
    this.top          = options.top;
    this.bottom       = options.bottom;
    
    this.options      = options;
    this.active       = false;
    this.dragging     = false;
    this.rect         = false;
    this.outerRect    = false;
    this.innerRect    = false;
    
    Event.observe(this.handle, "mousedown", this.startDrag.bindAsEventListener(this));
    Event.observe(document, "mouseup", this.endDrag.bindAsEventListener(this));
    Event.observe(document, "mousemove", this.update.bindAsEventListener(this));
    
    // Create inner structure...
    this.innerRect = document.createElement('div');
    this.outerRect = document.createElement('div');
    this.outerRect.style.position = 'relative';
    this.outerRect.style.display = 'none';
    this.outerRect.appendChild(this.innerRect);
    this.element.appendChild(this.outerRect);

    // Draw current structure...
    this.draw();
    if(this.options.change) this.options.change(this);
  },
  startDrag: function(event) {
    if(Event.isLeftClick(event)) {
      this.active = true;

      this.startX = parseInt(Event.pointerX(event) - this.offsetLeft);
      this.startY = parseInt(Event.pointerY(event) - this.offsetTop);
      this.left = this.right = this.startX;
      this.top = this.bottom = this.startY;
      Event.stop(event);
    }
  },
  endDrag: function(event) {
    if(this.active && this.dragging) {
      this.active = false;
      this.dragging = false;
      Event.stop(event);
    }
    this.active = false;
    this.dragging = false;
    
    if (this.left + 10 > this.right || 
        this.top + 10 > this.bottom) {
            
        this.top = this.bottom = this.left = this.right = 0;
        this.draw();
        if(this.options.change) this.options.change(this);
    }
  },
  draw: function() {
    var outerStyle = this.outerRect.style;
    var innerStyle = this.innerRect.style;

    if (this.left != 0 || this.right != 0 || this.top != 0 || this.bottom != 0)
    {
      var width = this.right - this.left;
      var height = this.bottom - this.top;
      
      outerStyle.left = this.left + 'px';
      outerStyle.width = (width - 2 > 0 ? width - 2 : 0) + 'px';   
      outerStyle.top = this.top + 'px';
      outerStyle.height = (height - 2 > 0 ? height - 2 : 0) + 'px';   

      innerStyle.width = (width - 4 > 0 ? width - 4 : 0) + 'px';
      innerStyle.height = (height - 4 > 0 ? height - 4 : 0) + 'px';

      outerStyle.display = 'block';
    } else {

      if(this.options.endeffect) 
        this.options.endeffect(this.outerRect);
      else
        outerStyle.display = 'none';   
    }
  },
  update: function(event) {
   if(this.active) {
      if(!this.dragging) {
        this.dragging = true;
      }
      
      //alert(event.pointerY());
      
      var newX = parseInt(Event.pointerX(event) - this.offsetLeft);
      var newY = parseInt(Event.pointerY(event) - this.offsetTop);
      
      if (newX > this.startX) {
        this.left = this.startX; 
        this.right = newX;
      } else {
        this.left = newX;
        this.right = this.startX;
      }
      
      if (newY > this.startY) {
        this.top = this.startY; 
        this.bottom = newY;
      } else {
        this.top = newY;
        this.bottom = this.startY;
      }
      
      if (this.left < 0) this.left = 0;
      if (this.top < 0) this.top = 0;
      if (this.right > this.element.offsetWidth) this.right = parseInt(this.element.offsetWidth);
      if (this.bottom > this.element.offsetHeight) this.bottom = parseInt(this.element.offsetHeight);
 
      this.draw();

      if(this.options.change) this.options.change(this);

      Event.stop(event);
    }
  }
}

Contents = Class.create();
Contents.prototype = {
  initialize: function(element) {
    var options = {
      handle: false
    }.extend(arguments[1] || {});

    this.element      = $(element);
    this.handle       = options.handle ? $(options.handle) : this.element;
    this.contents     = options.text ? options.text : this.element.alt;
    this.parser       = document.createElement('div');
	this.parser.innerHTML = this.contents;

	Event.observe(this.element, "mousemove", this.set.bindAsEventListener(this));
    Event.observe(this.element, "click", this.cancel.bindAsEventListener(this));
  },
  set: function(event) {
	if (this.handle.innerHTML != this.parser.innerHTML)
	    this.handle.innerHTML = this.parser.innerHTML;
    Event.stop(event);
  },
  clear: function(event) {
    this.handle.innerHTML = '';
  },
  cancel: function(event) {
	Event.stop(event);
  }
}


ContentsToggle = Class.create();
ContentsToggle.prototype = {
  initialize: function(element) {
    var options = {
      hideChildren: 	null,
	  showChild:		null,
	  initial:			null,
	  hideOnInit:		false
    }.extend(arguments[1] || {});

    this.element      = $(element);
    this.hideChildren = options.hideChildren ? $(options.hideChildren) : null;
    this.showChild    = options.showChild ? $(options.showChild) : null;
    this.initial      = options.initial ? $(options.initial) : null;

	if (options.hideOnInit && this.showChild) {
		Element.hide(this.showChild);
	}

	Event.observe(this.element, "mousemove", this.set.bindAsEventListener(this));
    Event.observe(this.element, "click", this.cancel.bindAsEventListener(this));
  },
  
  set: function(event) {
	if (this.initial) {
		Element.hide(this.initial);
	}
	
	if (this.showChild && this.showChild.style.display != 'none') {
		return;
	}
	
	for (var i = 0; i < this.hideChildren.childNodes.length; i++) {
		if (this.hideChildren.childNodes[i].tagName == 'LI') {
			Element.hide(this.hideChildren.childNodes[i]);
		}
	}
	
	Element.show(this.showChild);
    Event.stop(event);
  },
  clear: function(event) {
    this.handle.innerHTML = '';
  },
  cancel: function(event) {
	Event.stop(event);
  }
}




Effect.ShakeAway = function(element) {
  new Effect.Parallel(
    [ new Effect.Shake(element, {}), new Effect.Fade(element, {}) ]
  );
}