//MooTools More, <http://mootools.net/more>. Copyright (c) 2006-2009 Aaron Newton <http://clientcide.com/>, Valerio Proietti <http://mad4milk.net> & the MooTools team <http://mootools.net/developers>, MIT Style License.



/*

---



script: More.js



description: MooTools More



license: MIT-style license



authors:

- Guillermo Rauch

- Thomas Aylott

- Scott Kyle



requires:

- core:1.2.4/MooTools



provides: [MooTools.More]



...

*/



MooTools.More = {

	'version': '1.2.4.4',

	'build': '6f6057dc645fdb7547689183b2311063bd653ddf'

};



/*

---



script: Class.Binds.js



description: Automagically binds specified methods in a class to the instance of the class.



license: MIT-style license



authors:

- Aaron Newton



requires:

- core:1.2.4/Class

- /MooTools.More



provides: [Class.Binds]



...

*/



Class.Mutators.Binds = function(binds){

    return binds;

};



Class.Mutators.initialize = function(initialize){

	return function(){

		$splat(this.Binds).each(function(name){

			var original = this[name];

			if (original) this[name] = original.bind(this);

		}, this);

		return initialize.apply(this, arguments);

	};

};





/*

---



script: Element.Measure.js



description: Extends the Element native object to include methods useful in measuring dimensions.



credits: "Element.measure / .expose methods by Daniel Steigerwald License: MIT-style license. Copyright: Copyright (c) 2008 Daniel Steigerwald, daniel.steigerwald.cz"



license: MIT-style license



authors:

- Aaron Newton



requires:

- core:1.2.4/Element.Style

- core:1.2.4/Element.Dimensions

- /MooTools.More



provides: [Element.Measure]



...

*/



Element.implement({



	measure: function(fn){

		var vis = function(el) {

			return !!(!el || el.offsetHeight || el.offsetWidth);

		};

		if (vis(this)) return fn.apply(this);

		var parent = this.getParent(),

			restorers = [],

			toMeasure = []; 

		while (!vis(parent) && parent != document.body) {

			toMeasure.push(parent.expose());

			parent = parent.getParent();

		}

		var restore = this.expose();

		var result = fn.apply(this);

		restore();

		toMeasure.each(function(restore){

			restore();

		});

		return result;

	},



	expose: function(){

		if (this.getStyle('display') != 'none') return $empty;

		var before = this.style.cssText;

		this.setStyles({

			display: 'block',

			position: 'absolute',

			visibility: 'hidden'

		});

		return function(){

			this.style.cssText = before;

		}.bind(this);

	},



	getDimensions: function(options){

		options = $merge({computeSize: false},options);

		var dim = {};

		var getSize = function(el, options){

			return (options.computeSize)?el.getComputedSize(options):el.getSize();

		};

		var parent = this.getParent('body');

		if (parent && this.getStyle('display') == 'none'){

			dim = this.measure(function(){

				return getSize(this, options);

			});

		} else if (parent){

			try { //safari sometimes crashes here, so catch it

				dim = getSize(this, options);

			}catch(e){}

		} else {

			dim = {x: 0, y: 0};

		}

		return $chk(dim.x) ? $extend(dim, {width: dim.x, height: dim.y}) : $extend(dim, {x: dim.width, y: dim.height});

	},



	getComputedSize: function(options){

		options = $merge({

			styles: ['padding','border'],

			plains: {

				height: ['top','bottom'],

				width: ['left','right']

			},

			mode: 'both'

		}, options);

		var size = {width: 0,height: 0};

		switch (options.mode){

			case 'vertical':

				delete size.width;

				delete options.plains.width;

				break;

			case 'horizontal':

				delete size.height;

				delete options.plains.height;

				break;

		}

		var getStyles = [];

		//this function might be useful in other places; perhaps it should be outside this function?

		$each(options.plains, function(plain, key){

			plain.each(function(edge){

				options.styles.each(function(style){

					getStyles.push((style == 'border') ? style + '-' + edge + '-' + 'width' : style + '-' + edge);

				});

			});

		});

		var styles = {};

		getStyles.each(function(style){ styles[style] = this.getComputedStyle(style); }, this);

		var subtracted = [];

		$each(options.plains, function(plain, key){ //keys: width, height, plains: ['left', 'right'], ['top','bottom']

			var capitalized = key.capitalize();

			size['total' + capitalized] = size['computed' + capitalized] = 0;

			plain.each(function(edge){ //top, left, right, bottom

				size['computed' + edge.capitalize()] = 0;

				getStyles.each(function(style, i){ //padding, border, etc.

					//'padding-left'.test('left') size['totalWidth'] = size['width'] + [padding-left]

					if (style.test(edge)){

						styles[style] = styles[style].toInt() || 0; //styles['padding-left'] = 5;

						size['total' + capitalized] = size['total' + capitalized] + styles[style];

						size['computed' + edge.capitalize()] = size['computed' + edge.capitalize()] + styles[style];

					}

					//if width != width (so, padding-left, for instance), then subtract that from the total

					if (style.test(edge) && key != style &&

						(style.test('border') || style.test('padding')) && !subtracted.contains(style)){

						subtracted.push(style);

						size['computed' + capitalized] = size['computed' + capitalized]-styles[style];

					}

				});

			});

		});



		['Width', 'Height'].each(function(value){

			var lower = value.toLowerCase();

			if(!$chk(size[lower])) return;



			size[lower] = size[lower] + this['offset' + value] + size['computed' + value];

			size['total' + value] = size[lower] + size['total' + value];

			delete size['computed' + value];

		}, this);



		return $extend(styles, size);

	}



});



/*

---



script: Drag.js



description: The base Drag Class. Can be used to drag and resize Elements using mouse events.



license: MIT-style license



authors:

- Valerio Proietti

- Tom Occhinno

- Jan Kassens



requires:

- core:1.2.4/Events

- core:1.2.4/Options

- core:1.2.4/Element.Event

- core:1.2.4/Element.Style

- /MooTools.More



provides: [Drag]



*/



var stick = false;

var flashback = false;

var stickValue = 60;

var stickPos = 0;

var stickCounter = 1;

var itemCounter = 0;

var itemsNumber = 9;

var mousePos = 0;

var prePos = 0;

var postPos = 0;



var Drag = new Class({



	Implements: [Events, Options],



	options: {/*

		onBeforeStart: $empty(thisElement),

		onStart: $empty(thisElement, event),

		onSnap: $empty(thisElement)

		onDrag: $empty(thisElement, event),

		onCancel: $empty(thisElement),

		onComplete: $empty(thisElement, event),*/

		snap: 6,

		unit: 'px',

		grid: false,

		style: true,

		limit: false,

		handle: false,

		invert: false,

		preventDefault: false,

		stopPropagation: false,

		modifiers: {x: 'left', y: 'top'}

	},



	initialize: function() {

	

		var params = Array.link(arguments, {'options': Object.type, 'element': $defined});

		

		this.element = document.id(params.element);

		this.document = this.element.getDocument();

		this.setOptions(params.options || {});

		var htype = $type(this.options.handle);

		this.handles = ((htype == 'array' || htype == 'collection') ? $$(this.options.handle) : document.id(this.options.handle)) || this.element;

		this.mouse = {'now': {}, 'pos': {}};

		this.value = {'start': {}, 'now': {}};



		this.selection = (Browser.Engine.trident) ? 'selectstart' : 'mousedown';



		this.bound = {

			start: this.start.bind(this),

			check: this.check.bind(this),

			drag: this.drag.bind(this),

			stop: this.stop.bind(this),

			cancel: this.cancel.bind(this),

			eventStop: $lambda(false)

		};

		this.attach();

	},



	attach: function() {

		this.handles.addEvent('mousedown', this.bound.start);

		return this;

	},



	detach: function(){

		this.handles.removeEvent('mousedown', this.bound.start);

		return this;

	},



	start: function(event){

		if (event.rightClick) return;

		if (this.options.preventDefault) event.preventDefault();

		if (this.options.stopPropagation) event.stopPropagation();

		this.mouse.start = event.page;

		this.fireEvent('beforeStart', this.element);

		var limit = this.options.limit;

		this.limit = {x: [], y: []};

		for (var z in this.options.modifiers){

			if (!this.options.modifiers[z]) continue;

			if (this.options.style) this.value.now[z] = this.element.getStyle(this.options.modifiers[z]).toInt();

			else this.value.now[z] = this.element[this.options.modifiers[z]];

			if (this.options.invert) this.value.now[z] *= -1;

			this.mouse.pos[z] = event.page[z] - this.value.now[z];

			if (limit && limit[z]){

				for (var i = 2; i--; i){

					if ($chk(limit[z][i])) this.limit[z][i] = $lambda(limit[z][i])();

				}

			}

		}

		if ($type(this.options.grid) == 'number') this.options.grid = {x: this.options.grid, y: this.options.grid};

		this.document.addEvents({mousemove: this.bound.check, mouseup: this.bound.cancel});

		this.document.addEvent(this.selection, this.bound.eventStop);

	},



	check: function(event){

		if (this.options.preventDefault) event.preventDefault();

		var distance = Math.round(Math.sqrt(Math.pow(event.page.x - this.mouse.start.x, 2) + Math.pow(event.page.y - this.mouse.start.y, 2)));

		if (distance > this.options.snap){

			this.cancel();

			this.document.addEvents({

				mousemove: this.bound.drag,

				mouseup: this.bound.stop

			});

			this.fireEvent('start', [this.element, event]).fireEvent('snap', this.element);

		}

	},



	drag: function(event){

		this.mouse.now = event.page;

		for (var z in this.options.modifiers) {

			if (!this.options.modifiers[z]) continue;

			//

			if (Browser.Engine.trident) {

				mousePos = (this.mouse.now[z] - this.mouse.pos[z]);

			} else {

				mousePos = this.mouse.now[z] - this.mouse.pos[z];

			}


			//

			if ( Browser.Engine.presto ) {

				stickPos = (stickValue * stickCounter);

			} else if ( !Browser.Engine.gecko ) {

				stickPos = (stickValue * stickCounter) + 1;

			} else {

				stickPos = stickValue * stickCounter + 1;

			}

			if ( Browser.Engine.trident && (Browser.Engine.version == 4) ) {

				stickPos = stickValue * stickCounter + 1;


			}

			//

			prePos = stickPos - 10;
			postPos = stickPos + 10;

			//

			if ( stickCounter > 1) {

				if ( mousePos <= (stickPos - 50) ) {

					flashback = true;
					stickCounter--;

				}

			}

			//

			if ( mousePos >= prePos && mousePos <= postPos ) {

				stick = true;

			}

			//

			if (flashback) {


				if ( mousePos > postPos && stickCounter < itemsNumber ) {

					stick = false;
					stickCounter++;

				} else if ( mousePos < prePos && mousePos >= 0 ) {

					stick = false;
					stickCounter--;

				}

			} else {

				if ( mousePos > postPos && stickCounter < itemsNumber ) {

					stick = false;
					stickCounter++;

				} else  if ( mousePos < prePos && mousePos >= 0 ) {

					stick = false;
					stickCounter--;

				}

			}
	

			//
	

			if (stick) {

				if ( stickCounter == 1 ){

					$('item00').setStyle('font-weight', 'bold');

				} else {

					if ( stickCounter <= 0 || stickCounter > itemsNumber ) {} else {

					   $('item0' + (stickCounter-1)).setStyle('font-weight', 'bold');

					}

				}

				if ( stickPos < 60 ) {

					this.value.now[z] = 1;

					if (Browser.Engine.trident) {

					$('slider').set('styles', {
					'position': 'relative',
					'margin-left': '-1px'
					});

					}

				} else {

					this.value.now[z] = stickPos;

				}
	

			} else {

				if (Browser.Engine.trident) {

					$('slider').set('styles', {
					'position': 'relative',
					'margin-left': '0px'

					});

				}

				$('item00').setStyle('font-weight', 'normal');
				$('item01').setStyle('font-weight', 'normal');
				$('item02').setStyle('font-weight', 'normal');
				$('item03').setStyle('font-weight', 'normal');
				$('item04').setStyle('font-weight', 'normal');
				$('item05').setStyle('font-weight', 'normal');
				$('item06').setStyle('font-weight', 'normal');
				$('item07').setStyle('font-weight', 'normal');
				$('item08').setStyle('font-weight', 'normal');

				if (Browser.Engine.trident) {

					this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z] - 5;

				} else {

					this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z];

				}

			}

			//


			if (this.options.invert) this.value.now[z] *= -1;


			if (this.options.limit && this.limit[z]){

				if ($chk(this.limit[z][1]) && (this.value.now[z] > this.limit[z][1])){

					this.value.now[z] = this.limit[z][1];

				} else if ($chk(this.limit[z][0]) && (this.value.now[z] < this.limit[z][0])){

					this.value.now[z] = this.limit[z][0];

				}

			}


			if (this.options.grid[z]) this.value.now[z] -= ((this.value.now[z] - (this.limit[z][0]||0)) % this.options.grid[z]);

			if (this.options.style) {

				this.element.setStyle(this.options.modifiers[z], this.value.now[z] + this.options.unit);

			} else {

				this.element[this.options.modifiers[z]] = this.value.now[z];

			}

		}

		this.fireEvent('drag', [this.element, event]);

	},

	cancel: function(event){

		this.document.removeEvent('mousemove', this.bound.check);
		this.document.removeEvent('mouseup', this.bound.cancel);

		if (event){

			this.document.removeEvent(this.selection, this.bound.eventStop);
			this.fireEvent('cancel', this.element);

		}

	},



	stop: function(event){

		// Changing KNOB background to NORMAL state
		//$('knob').setStyle('background-position', '0 0');

		this.document.removeEvent(this.selection, this.bound.eventStop);
		this.document.removeEvent('mousemove', this.bound.drag);
		this.document.removeEvent('mouseup', this.bound.stop);
		if (event) this.fireEvent('complete', [this.element, event]);

	}

});



Element.implement({



	makeResizable: function(options){

		var drag = new Drag(this, $merge({modifiers: {x: 'width', y: 'height'}}, options));

		this.store('resizer', drag);

		return drag.addEvent('drag', function(){

			this.fireEvent('resize', drag);

		}.bind(this));

	}



});





/*

---



script: Slider.js



description: Class for creating horizontal and vertical slider controls.



license: MIT-style license



authors:

- Valerio Proietti



requires:

- core:1.2.4/Element.Dimensions

- /Class.Binds

- /Drag

- /Element.Dimensions

- /Element.Measure



provides: [Slider]



...

*/



var Slider = new Class({



	Implements: [Events, Options],



	Binds: ['clickedElement', 'draggedKnob', 'scrolledElement'],



	options: {/*

		onTick: $empty(intPosition),

		onChange: $empty(intStep),

		onComplete: $empty(strStep),*/

		onTick: function(position){

			//if (this.options.snap) position = this.toPosition(this.step);

			this.knob.setStyle(this.property, position);

		},

		initialStep: 0,

		snap: false,

		offset: 0,

		range: false,

		wheel: false,

		steps: 10,

		stepWidth: 0,

		mode: 'horizontal'

	},



	initialize: function(element, knob, options){

		this.setOptions(options);

		this.element = document.id(element);

		this.knob = document.id(knob);

		this.previousChange = this.previousEnd = this.step = -1;

		var offset, limit = {}, modifiers = {'x': false, 'y': false};

		

		switch (this.options.mode){

			case 'vertical':

				this.axis = 'y';

				this.property = 'top';

				offset = 'offsetHeight';

				break;

			case 'horizontal':

				this.axis = 'x';

				this.property = 'left';

				offset = 'offsetWidth';

		}

		

		this.full = this.element.measure(function(){ 

			this.half = this.knob[offset] / 2; 

			return this.element[offset] - this.knob[offset] + (this.options.offset * 2); 

		}.bind(this));

		

		this.min = $chk(this.options.range[0]) ? this.options.range[0] : 0;

		this.max = $chk(this.options.range[1]) ? this.options.range[1] : this.options.steps;

		this.range = this.max - this.min;

		this.steps = this.options.steps || this.full;

		this.stepSize = Math.abs(this.range) / this.steps;

		this.stepWidth = this.options.stepWidth || this.stepSize * this.full / Math.abs(this.range) ;



		this.knob.setStyle('position', 'relative').setStyle(this.property, this.options.initialStep ? this.toPosition(this.options.initialStep) : - this.options.offset);

		modifiers[this.axis] = this.property;

		limit[this.axis] = [- this.options.offset, this.full - this.options.offset];



		var dragOptions = {

			snap: 0,

			limit: limit,

			modifiers: modifiers,

			onDrag: this.draggedKnob,

			onStart: this.draggedKnob,

			onBeforeStart: (function(){

				this.isDragging = true;

			}).bind(this),

			onCancel: function() {

				this.isDragging = false;

			}.bind(this),

			onComplete: function(){

				this.isDragging = false;

				this.draggedKnob();

				this.end();

			}.bind(this)

		};

		if (this.options.snap){

			dragOptions.grid = Math.ceil(this.stepWidth);

			dragOptions.limit[this.axis][1] = this.full;

		}

		

		var mousePos;

		

		this.drag = new Drag(this.knob, dragOptions);

		this.attach();

	},



	attach: function(){

		this.element.getElements('div.dota').setStyle('cursor','pointer').addEvent('click',this.clickedElement);

		//this.element.addEvent('mousedown', this.clickedElement);

		if (this.options.wheel) this.element.addEvent('mousewheel', this.scrolledElement);

		this.drag.attach();

		return this;

	},

	

	detach: function(){

		this.element.removeEvent('mousedown', this.clickedElement);

		this.element.removeEvent('mousewheel', this.scrolledElement);

		this.drag.detach();

		return this;

	},



	set: function(step){

		if (!((this.range > 0) ^ (step < this.min))) step = this.min;

		if (!((this.range > 0) ^ (step > this.max))) step = this.max;



		this.step = Math.round(step);

		this.checkStep();

		this.fireEvent('tick', this.toPosition(this.step));

		this.end();

		return this;

	},



	tick: function(position,callback)

	{

		if (position>this.full) position = this.full;



		this.fireEvent('tick', position);

		this.fireEvent('change', position);



		if( $defined( callback ) && $type( callback )=='function' )

			callback( position );



		return this;

	},



	clickedElement: function(event){

		if (this.isDragging || event.target == this.knob) return;



		var dir = this.range < 0 ? -1 : 1;

		var position = event.page[this.axis] - this.element.getPosition()[this.axis] - this.half;

		position = position.limit(-this.options.offset, this.full -this.options.offset);

		//var position = this.stepWidth * ( event.target.rel ? event.target.rel : event.target.getProperty( 'rel' ) );



		this.step = Math.round(this.min + dir * this.toStep(position));

		//this.step = Math.round(this.toStep(position));

		this.checkStep();

		this.fireEvent('tick', position);

		this.end();

	},



	scrolledElement: function(event){

		var mode = (this.options.mode == 'horizontal') ? (event.wheel < 0) : (event.wheel > 0);

		this.set(mode ? this.step - this.stepSize : this.step + this.stepSize);

		event.stop();

	},



	draggedKnob: function(){

		var dir = this.range < 0 ? -1 : 1;

		var position = this.drag.value.now[this.axis];

		position = position.limit(-this.options.offset, this.full -this.options.offset);

		//this.step = Math.round(this.min + dir * this.toStep(position));

		this.step = position;

		this.checkStep();

	},



	checkStep: function(){

		if (this.previousChange != this.step){

			this.previousChange = this.step;

			this.fireEvent('change', this.step);

		}

	},



	end: function(){

		if (this.previousEnd !== this.step){

			this.previousEnd = this.step;

			this.fireEvent('complete', this.step + '');

		}

	},



	toStep: function(position){

		var step = (position + this.options.offset) * this.stepSize / this.full * this.steps;

		return this.options.steps ? Math.round(step -= step % this.stepSize) : step;

	},



	toPosition: function(step){

		return (this.full * Math.abs(this.min - step)) / (this.steps * this.stepSize) - this.options.offset;

	}



});
