/**
 * Synergy Point Slider for jQuery
 * 
 * Creates a simple one-handle slider
 * 
 * -----
 * Usage
 * -----
 * <div id="slider1"><div class="handle"></div></div>
 * 
 * $('#slider1').spslider({mouseOverClass:'customOverClass'});
 * 
 * $('#slider1').spslider('position');
 * $('#slider1').spslider('position', 0.5);
 * 
 * $('#slider1').spslider('enabled');
 * $('#slider1').spslider('enabled', false);
 * $('#slider1').spslider('enabled', true);
 * 
 * $('#slider1').bind('slide', function(ev){ ... });
 * $('#slider1').bind('change', function(ev){ ... });
 * 
 * -------
 * Options
 * -------
 * handle			The element inside the slider that will be used as the "handle"
 * 					Optional
 * 					Default: first child of the main slider element
 * 
 * mouseOverClass	Class given to slider when mouse is over it
 * 					Optional
 * 					Default: mouseover
 * 
 * mouseDownClass	Class given to slider when it is being dragged
 * 					Optional
 * 					Default: mousedown
 * 
 * startPosition	Position at which the slider should start out at
 * 					Possible values are [0,1]
 * 					Optional
 * 					Default: 0 (0%)
 * 
 * ------
 * Events
 * ------
 * All event callbacks are passed two objects: the event object and
 * { el:<slider element>, pos:<slider position> }
 * 
 * slide	Called every time the mouse is moved while sliding
 * 
 * change	Called when the sliding is done and the position has changed
 */

(function($) {
	var defaultSettings = {
		handle: ':first-child:first',
		mouseOverClass: 'mouseover',
		mouseDownClass: 'mousedown',
		startPosition: 0,
		enabled: true
	};
	
	var moving = {
		el:null,
		width:0,
		handle:null,
		baseX:0,
		oldPos:0,
		prevPos:0
	};
	
	function evt(el, pos) { return {el:el, pos:pos};	}
	
	function onmousedown(ev) {
		moving.el = jQuery(this);
		
		if (moving.el.hasClass('disabled')) return false;
		
		moving.el.addClass(moving.el.data('spslider.options').mouseDownClass);
		
		moving.handle = moving.el.data('spslider.handle');
		moving.baseX = moving.el.offset().left;
		moving.width = moving.el.width();
		moving.oldPos = moving.handle.width() / moving.width;
		
		$('body').bind('mousemove', onmousemove).bind('mouseup', onmouseup);
		onmousemove(ev);
		return false;
	}
	
	function onmousemove(ev) {
		var w = ev.pageX - moving.baseX;
		var newPos = setw(w, moving.width, moving.handle) / moving.width;
		
		if (newPos != moving.prevPos) {
			moving.el.triggerHandler('slide', evt(moving.el, newPos));
			moving.prevPos = newPos;
		}
		return false;
	}
	
	function onmouseup(ev) {
		$('body').unbind('mousemove', onmousemove);
		
		var newPos = position(moving.el);
		
		if (moving.oldPos != newPos) {
			moving.el.triggerHandler('change', evt(moving.el, newPos));
		};

		moving.el.removeClass(moving.el.data('spslider.options').mouseDownClass);
		
		return false;
	}
	
	function setw(w, maxw, handle) {
		if (w < 0) w = 0;
		else if (w > maxw) w = maxw;
		handle.width(w);
		return w;
	}
	
	function init(el, options) {
		var handle = el.find(options.handle);
		
		el.data('spslider.handle', handle);
		el.data('spslider.options', options);
		
		position(el, options.startPosition);
		enabled(el, options.enabled);
		
		el
			.bind('mousedown', onmousedown)
			.hover(function() { el.addClass(options.mouseOverClass); }, function() { el.removeClass(options.mouseOverClass); })
			;
	}
	
	function execute(act, args, el) {
		switch (act) {
			case 'position': return position(el, args);
			case 'enabled': return enabled(el, args);
		}
	}
	
	function position(el, pos) {
		// If a position is given, set it
		var h = el.data('spslider.handle');
		var x = el.width();
		if (pos >= 0) {
			var w = x * pos;
			setw(w, x, h);
		}
		return (h.width() / x);
	}
	
	function enabled(el, bool) {
		if (bool === false) {
			el.addClass('disabled');
		}
		else if (bool === true) {
			el.removeClass('disabled');
		}
		return !el.hasClass('disabled');
	}
	
	$.fn.spslider = function(options) {
		
		if (typeof options == 'string') {
			var args = arguments[1];
			var el = jQuery(this);
			return execute(options, arguments[1], el);
		}
		
		else {
			options = jQuery.extend({}, defaultSettings, options);
			return this.each (function() { init(jQuery(this), options); });
		}
	}
})(jQuery);
