var Selectable = new Class
({
 options:
 {
 onComplete: Class.empty
 },

 initialize: function(el, options)
 {
 this.setOptions(options);

 this.el = $(el);

 this.attached = false;

 this.bound =
 {
 'start': this.start.bindWithEvent(this),
 'drag': this.drag.bindWithEvent(this),
 'stop': this.stop.bindWithEvent(this)
 };

 this.overlay = new Element
 (
 'div',
 {
 'class': 'overlay',
 'styles':
 {
 'position': 'absolute',
 'top': '0px',
 'left': '0px',
 'display': 'block',
 'cursor': 'crosshair'
 },
 'events':
 {
 'mousedown': this.bound.start
 }
 }
 );

 this.handle = new Element
 (
 'div',
 {
 'class': 'handle',
 'styles':
 {
 'position': 'absolute',
 'top': '0px',
 'left': '0px',
 'display': 'none'
 }
 }
 ).injectInside(this.overlay);

 if (window.ie) this.handle.setStyle('opacity', '.6');
 },

 attach: function()
 {
 this.overlay.injectInside(this.el);
 this.overlay.setStyles(this.el.getStyles('height', 'width'));
 this.attached = true;
 },

 detach: function()
 {
 this.handle.setStyle('display', 'none');
 this.overlay.remove();
 this.attached = false;
 },

 start: function(event)
 {
 event.stopPropagation().preventDefault();

 this.pin =
 {
 x: event.client.x - this.overlay.getLeft(),
 y: event.client.y - this.overlay.getTop()
 };

 this.limit =
 {
 x:
 {
 max: this.overlay.getStyle('width').toInt() - this.pin.x,
 min: -this.pin.x
 },
 y:
 {
 max: this.overlay.getStyle('height').toInt() - this.pin.y,
 min: -this.pin.y
 }
 }

 this.handle.setStyles
 ({
 'display': 'block',
 'left': this.pin.x + 'px',
 'top': this.pin.y + 'px',
 'width': '0px',
 'height': '0px'
 });

 document.addListener('mousemove', this.bound.drag);
 document.addListener('mouseup', this.bound.stop);
 },

 drag: function(event)
 {
 event.stopPropagation().preventDefault();

 var dim =
 {
 x: this.pin.x,
 y: this.pin.y,
 w: (event.client.x - this.overlay.getLeft() - this.pin.x).limit(this.limit.x.min, this.limit.x.max),
 h: (event.client.y - this.overlay.getTop() - this.pin.y).limit(this.limit.y.min, this.limit.y.max)
 }

 if (dim.w < 0) dim.x += dim.w;
 if (dim.h < 0) dim.y += dim.h;

 this.handle.setStyles
 ({
 'height': Math.abs(dim.h) + 'px',
 'width': Math.abs(dim.w) + 'px',
 'left' : dim.x + 'px',
 'top' : dim.y + 'px'
 });
 },

 stop: function(event)
 {
 event.stopPropagation().preventDefault();

 document.removeListener('mousemove', this.bound.drag);
 document.removeListener('mouseup', this.bound.stop);

 var dim =
 {
 x: this.handle.getLeft() - this.overlay.getLeft(),
 y: this.handle.getTop() - this.overlay.getTop(),
 w: this.handle.getStyle('width').toInt(),
 h: this.handle.getStyle('height').toInt()
 }

 this.fireEvent('onComplete', dim);
 this.detach();
 }
});

Selectable.implement(new Events(), new Options());