// jQuery Slider Plugin
// Egor Khmelev - http://blog.egorkhmelev.com/ - hmelyoff@gmail.com

(function(){

	// Simple Inheritance
	Function.prototype.inheritFrom = function(BaseClass, oOverride){
		var Inheritance = function() {};
		Inheritance.prototype = BaseClass.prototype;
		this.prototype = new Inheritance();
		this.prototype.constructor = this;
		this.prototype.baseConstructor = BaseClass;
		this.prototype.superClass = BaseClass.prototype;

		if(oOverride){
			for(var i in oOverride) {
				this.prototype[i] = oOverride[i];
			}
		}
	};

	// Format numbers
	Number.prototype.jSliderNice=function(iRoundBase){
		var re=/^(-)?(\d+)([\.,](\d+))?$/;
		var iNum=Number(this);
		var sNum=String(iNum);
		var aMatches;
		var sDecPart='';
		var sTSeparator=' ';
		if((aMatches = sNum.match(re))){
			var sIntPart=aMatches[2];
			var iDecPart=(aMatches[4]) ? Number('0.'+aMatches[4]) : 0;
			if(iDecPart){
//				var iRF=Math.pow(10, (iRoundBase) ? iRoundBase : 2);
				var round = iRoundBase || 2;
				var iRF=Math.pow(10, round);
				iDecPart=Math.round(iDecPart*iRF);
				sNewDecPart=String(iDecPart);
				sDecPart = sNewDecPart;
//				if(sNewDecPart.length < iRoundBase){
				if(sNewDecPart.length < round){
					var iDiff = round-sNewDecPart.length;
					for (var i=0; i < iDiff; i++) {
						sDecPart = "0" + sDecPart;
					};
				}
				sDecPart = "," + sDecPart;
			} else {
				if(iRoundBase && iRoundBase != 0){
					for (var i=0; i < iRoundBase; i++) {
						sDecPart += "0";
					};
					sDecPart = "," + sDecPart;
				}
			}
			var sResult;
			if(Number(sIntPart) < 1000){
				sResult = sIntPart+sDecPart;
			}else{
				var sNewNum='';
				var i;
				for(i=1; i*3<sIntPart.length; i++)
					sNewNum=sTSeparator+sIntPart.substring(sIntPart.length - i*3, sIntPart.length - (i-1)*3)+sNewNum;
				sResult = sIntPart.substr(0, 3 - i*3 + sIntPart.length)+sNewNum+sDecPart;
			}
			if(aMatches[1])
				return '-'+sResult;
			else
				return sResult;
		}
		else{
			return sNum;
		}
	};

	this.jSliderIsArray = function( value ){
		if( typeof value == "undefined" ) return false;

		if (value instanceof Array ||	// Works quickly in same execution context.
				// If value is from a different execution context then
				// !(value instanceof Object), which lets us early out in the common
				// case when value is from the same context but not an array.
				// The {if (value)} check above means we don't have to worry about
				// undefined behavior of Object.prototype.toString on null/undefined.
				//
				// HACK: In order to use an Object prototype method on the arbitrary
				//	 value, the compiler requires the value be cast to type Object,
				//	 even though the ECMA spec explicitly allows it.
				(!(value instanceof Object) &&
				 (Object.prototype.toString.call(
						 /** @type {Object} */ (value)) == '[object Array]') ||

				 // In IE all non value types are wrapped as objects across window
				 // boundaries (not iframe though) so we have to do object detection
				 // for this edge case
				 typeof value.length == 'number' &&
				 typeof value.splice != 'undefined' &&
				 typeof value.propertyIsEnumerable != 'undefined' &&
				 !value.propertyIsEnumerable('splice')

				)) {
			return true;
		}

		return false;
	}
})();


// Simple JavaScript Templating
// John Resig - http://ejohn.org/ - MIT Licensed

(function(){
	var cache = {};

	this.jSliderTmpl = function jSliderTmpl(str, data){
		// Figure out if we're getting a template, or if we need to
		// load the template - and be sure to cache the result.
		var fn = !(/\W/).test(str) ?
			cache[str] = cache[str] ||
				jSliderTmpl(str) :

			// Generate a reusable function that will serve as a template
			// generator (and which will be cached).
			new Function("obj",
				"var p=[],print=function(){p.push.apply(p,arguments);};" +

				// Introduce the data as local variables using with(){}
				"with(obj){p.push('" +

				// Convert the template into pure JavaScript
				str
					.replace(/[\r\t\n]/g, " ")
					.split("<%").join("\t")
					.replace(/((^|%>)[^\t]*)'/g, "$1\r")
					.replace(/\t=(.*?)%>/g, "',$1,'")
					.split("\t").join("');")
					.split("%>").join("p.push('")
					.split("\r").join("\\'")
			+ "');}return p.join('');");
		
		// Provide some basic currying to the user
		return data ? fn( data ) : fn;
	};
})();


// Draggable Class
// Egor Khmelev - http://blog.egorkhmelev.com/

(function( $ ){

	this.Draggable = function(){
		this._init.apply( this, arguments );
	};

	Draggable.prototype = {
		// Methods for re-init in child class
		oninit: function(){},
		events: function(){},
		onmousedown: function(){
			this.ptr.css({ position: "absolute" });
		},
		onmousemove: function( evt, x, y ){
			this.ptr.css({ left: x, top: y });
		},
		onmouseup: function(){},

		isDefault: {
			drag: false,
			clicked: false,
			toclick: true,
			mouseup: false
		},

		_init: function(){
			if( arguments.length > 0 ){
				this.ptr = $(arguments[0]);
				this.outer = $(".draggable-outer");

				this.is = {};
				$.extend( this.is, this.isDefault );

				var _offset = this.ptr.offset();
				this.d = {
					left: _offset.left,
					top: _offset.top,
					width: this.ptr.width(),
					height: this.ptr.height()
				};

				this.oninit.apply( this, arguments );

				this._events();
			}
		},
		_getPageCoords: function( event ){
			if( event.targetTouches && event.targetTouches[0] ){
				return { x: event.targetTouches[0].pageX, y: event.targetTouches[0].pageY };
			} else
				return { x: event.pageX, y: event.pageY };
		},
		_bindEvent: function( ptr, eventType, handler ){
			var self = this;

			if( this.supportTouches_ )
				ptr.get(0).addEventListener( this.events_[ eventType ], handler, false );
			else
				ptr.bind( this.events_[ eventType ], handler );
		},
		_events: function(){
			var self = this;

			this.supportTouches_ = ( $.browser.webkit && navigator.userAgent.indexOf("Mobile") != -1 );
			this.events_ = {
				"click": this.supportTouches_ ? "touchstart" : "click",
				"down": this.supportTouches_ ? "touchstart" : "mousedown",
				"move": this.supportTouches_ ? "touchmove" : "mousemove",
				"up"	: this.supportTouches_ ? "touchend" : "mouseup"
			};

			this._bindEvent( $( document ), "move", function( event ){
				if( self.is.drag ){
					event.stopPropagation();
					event.preventDefault();
					self._mousemove( event );
				}
			});
			this._bindEvent( $( document ), "down", function( event ){
				if( self.is.drag ){
					event.stopPropagation();
					event.preventDefault();
				}
			});
			this._bindEvent( $( document ), "up", function( event ){
				self._mouseup( event );
			});
			this._bindEvent( this.ptr, "down", function( event ){
				self._mousedown( event );
				return false;
			});
			this._bindEvent( this.ptr, "up", function( event ){
				self._mouseup( event );
			});
			this.ptr.find("a")
				.click(function(){
					self.is.clicked = true;

					if( !self.is.toclick ){
						self.is.toclick = true;
						return false;
					}
				})
				.mousedown(function( event ){
					self._mousedown( event );
					return false;
				});

			this.events();
		},
		_mousedown: function( evt ){
			this.is.drag = true;
			this.is.clicked = false;
			this.is.mouseup = false;

			var _offset = this.ptr.offset();
			var coords = this._getPageCoords( evt );
			this.cx = coords.x - _offset.left;
			this.cy = coords.y - _offset.top;

			$.extend(this.d, {
				left: _offset.left,
				top: _offset.top,
				width: this.ptr.width(),
				height: this.ptr.height()
			});

			if( this.outer && this.outer.get(0) ){
				this.outer.css({ height: Math.max(this.outer.height(), $(document.body).height()), overflow: "hidden" });
			}

			this.onmousedown( evt );
		},
		_mousemove: function( evt ){
			this.is.toclick = false;
			var coords = this._getPageCoords( evt );
			this.onmousemove( evt, coords.x - this.cx, coords.y - this.cy );
		},
		_mouseup: function( evt ){
			var oThis = this;

			if( this.is.drag ){
				this.is.drag = false;

				if( this.outer && this.outer.get(0) ){

					if( $.browser.mozilla ){
						this.outer.css({ overflow: "hidden" });
					} else {
						this.outer.css({ overflow: "visible" });
					}

					if( $.browser.msie && $.browser.version == '6.0' ){
						this.outer.css({ height: "100%" });
					} else {
						this.outer.css({ height: "auto" });
					}
				}
				this.onmouseup( evt );
			}
		}
	};

})( jQuery );



// jQuery Slider (Safari)
// Egor Khmelev - http://blog.egorkhmelev.com/

(function( $ ) {

	$.slider = function( node, settings ){
		var jNode = $(node);
		if( !jNode.data( "jslider" ) )
			jNode.data( "jslider", new jSlider( node, settings ) );
		return jNode.data( "jslider" );
	};

	$.fn.slider = function( action, opt_value ){
		var returnValue, args = arguments;

		function isDef( val ){
			return val !== undefined;
		};

		function isDefAndNotNull( val ){
			return val != null;
		};

		this.each(function(){
			var self = $.slider( this, action );

			// do actions
			if( typeof action == "string" ){
				switch( action ){
					case "value":
						if( isDef( args[ 1 ] ) && isDef( args[ 2 ] ) ){
							var pointers = self.getPointers();
							if( isDefAndNotNull( pointers[0] ) && isDefAndNotNull( args[1] ) ){
								pointers[0].set( args[ 1 ] );
								pointers[0].setIndexOver();
							}
							if( isDefAndNotNull( pointers[1] ) && isDefAndNotNull( args[2] ) ){
								pointers[1].set( args[ 2 ] );
								pointers[1].setIndexOver();
							}
						}
						else if( isDef( args[ 1 ] ) ){
							var pointers = self.getPointers();
							if( isDefAndNotNull( pointers[0] ) && isDefAndNotNull( args[1] ) ){
								pointers[0].set( args[ 1 ] );
								pointers[0].setIndexOver();
							}
						}
						else
							returnValue = self.getValue();

						break;

					case "prc":
						if( isDef( args[ 1 ] ) && isDef( args[ 2 ] ) ){
							var pointers = self.getPointers();
							if( isDefAndNotNull( pointers[0] ) && isDefAndNotNull( args[1] ) ){
								pointers[0]._set( args[ 1 ] );
								pointers[0].setIndexOver();
							}

							if( isDefAndNotNull( pointers[1] ) && isDefAndNotNull( args[2] ) ){
								pointers[1]._set( args[ 2 ] );
								pointers[1].setIndexOver();
							}
						}

						else if( isDef( args[ 1 ] ) ){
							var pointers = self.getPointers();
							if( isDefAndNotNull( pointers[0] ) && isDefAndNotNull( args[1] ) ){
								pointers[0]._set( args[ 1 ] );
								pointers[0].setIndexOver();
							}
						}

						else
							returnValue = self.getPrcValue();

						break;

					case "calculatedValue":
						var value = self.getValue().split(";");
						returnValue = "";
						for (var i=0; i < value.length; i++) {
							returnValue += (i > 0 ? ";" : "") + self.nice( value[i] );
						};

						break;

					case "skin":
						self.setSkin( args[1] );

						break;
				};
			}

			// return actual object
			else if( !action && !opt_value ){
				if( !jSliderIsArray( returnValue ) )
					returnValue = [];

				returnValue.push( slider );
			}
		});

		// flatten array just with one slider
		if( jSliderIsArray( returnValue ) && returnValue.length == 1 )
			returnValue = returnValue[ 0 ];

		return returnValue || this;
	};

	var OPTIONS = {

		settings: {
			from: 1,
			to: 10,
			step: 1,
			smooth: true,
			limits: true,
			round: 0,
			value: "5;7",
			dimension: ""
		},

		className: "jslider",
		selector: ".jslider-",

		template: jSliderTmpl(
			'<span class="<%=className%>">' +
				'<table><tr><td>' +
					'<div class="<%=className%>-bg">' +
						'<i class="l"><i></i></i><i class="r"><i></i></i>' +
						'<i class="v"><i></i></i>' +
					'</div>' +

					'<div class="<%=className%>-pointer"><i></i></div>' +
					'<div class="<%=className%>-pointer <%=className%>-pointer-to"><i></i></div>' +
				
					'<div class="<%=className%>-label"><span><%=settings.from%></span></div>' +
					'<div class="<%=className%>-label <%=className%>-label-to"><ins><%=settings.dimension%></ins><span><%=settings.to%></span><%=settings.dimension%></div>' +

					'<div class="<%=className%>-value"><ins><%=settings.dimension%></ins><span></span><%=settings.dimension%></div>' +
					'<div class="<%=className%>-value <%=className%>-value-to"><ins><%=settings.dimension%></ins><span></span><%=settings.dimension%></div>' +
					
					'<div class="<%=className%>-scale"><%=scale%></div>'+

				'</td></tr></table>' +
			'</span>'
		)

	};

	this.jSlider = function(){
		return this.init.apply( this, arguments );
	};

	jSlider.prototype = {
		init: function( node, settings ){
			this.settings = $.extend(true, {}, OPTIONS.settings, settings ? settings : {});

			// obj.sliderHandler = this;
			this.inputNode = $( node ).hide();

			this.settings.interval = this.settings.to-this.settings.from;
			this.settings.value = this.inputNode.attr("value");

			if( this.settings.calculate && $.isFunction( this.settings.calculate ) )
				this.nice = this.settings.calculate;

			if( this.settings.onstatechange && $.isFunction( this.settings.onstatechange ) )
				this.onstatechange = this.settings.onstatechange;

			this.is = {
				init: false
			};
			this.o = {};

			this.create();
		},

		onstatechange: function(){},

		create: function(){
			var $this = this;

			this.domNode = $( OPTIONS.template({
				className: OPTIONS.className,
				settings: {
					from: this.nice( this.settings.from ),
					to: this.nice( this.settings.to ),
					dimension: this.settings.dimension
				},
				scale: this.generateScale()
			}) );

			this.inputNode.after( this.domNode );
			this.drawScale();

			// set skin class
			if( this.settings.skin && this.settings.skin.length > 0 )
				this.setSkin( this.settings.skin );

			this.sizes = {
				domWidth: this.domNode.width(),
				domOffset: this.domNode.offset()
			};

			// find some objects
			$.extend(this.o, {
				pointers: {},
				labels: {
					0: {
						o: this.domNode.find(OPTIONS.selector + "value").not(OPTIONS.selector + "value-to")
					},
					1: {
						o: this.domNode.find(OPTIONS.selector + "value").filter(OPTIONS.selector + "value-to")
					}
				},
				limits: {
					0: this.domNode.find(OPTIONS.selector + "label").not(OPTIONS.selector + "label-to"),
					1: this.domNode.find(OPTIONS.selector + "label").filter(OPTIONS.selector + "label-to")
				}
			});

			$.extend(this.o.labels[0], {
				value: this.o.labels[0].o.find("span")
			});

			$.extend(this.o.labels[1], {
				value: this.o.labels[1].o.find("span")
			});

			if( !$this.settings.value.split(";")[1] ){
				this.settings.single = true;
				this.domNode.addDependClass("single");
			}

			if( !$this.settings.limits )
				this.domNode.addDependClass("limitless");

			this.domNode.find(OPTIONS.selector + "pointer").each(function( i ){
				var value = $this.settings.value.split(";")[i];
				if( value ){
					$this.o.pointers[i] = new jSliderPointer( this, i, $this );

					var prev = $this.settings.value.split(";")[i-1];
					if( prev && new Number(value) < new Number(prev) ) value = prev;

					value = value < $this.settings.from ? $this.settings.from : value;
					value = value > $this.settings.to ? $this.settings.to : value;

					$this.o.pointers[i].set( value, true );
				}
			});

			this.o.value = this.domNode.find(".v");
			this.is.init = true;

			$.each(this.o.pointers, function(i){
				$this.redraw(this);
			});

			(function(self){
				$(window).resize(function(){
					self.onresize();
				});
			})(this);

		},

		setSkin: function( skin ){
			if( this.skin_ )
				this.domNode.removeDependClass( this.skin_, "_" );

			this.domNode.addDependClass( this.skin_ = skin, "_" );
		},

		setPointersIndex: function( i ){
			$.each(this.getPointers(), function(i){
				this.index( i );
			});
		},

		getPointers: function(){
			return this.o.pointers;
		},

		generateScale: function(){
			if( this.settings.scale && this.settings.scale.length > 0 ){
				var str = "";
				var s = this.settings.scale;
				var prc = Math.round((100/(s.length-1))*10)/10;
				for( var i=0; i < s.length; i++ ){
					str += '<span style="left: ' + i*prc + '%">' + ( s[i] != '|' ? '<ins>' + s[i] + '</ins>' : '' ) + '</span>';
				};
				return str;
			} else return "";

			return "";
		},

		drawScale: function(){
			this.domNode.find(OPTIONS.selector + "scale span ins").each(function(){
				$(this).css({ marginLeft: -$(this).outerWidth()/2 });
			});
		},

		onresize: function(){
			var self = this;
			this.sizes = {
				domWidth: this.domNode.width(),
				domOffset: this.domNode.offset()
			};

			$.each(this.o.pointers, function(i){
				self.redraw(this);
			});
		},

		limits: function( x, pointer ){
			// smooth
			if( !this.settings.smooth ){
				var step = this.settings.step*100 / ( this.settings.interval );
				x = Math.round( x/step ) * step;
			}

			var another = this.o.pointers[1-pointer.uid];
			if( another && pointer.uid && x < another.value.prc ) x = another.value.prc;
			if( another && !pointer.uid && x > another.value.prc ) x = another.value.prc;

			// base limit
			if( x < 0 ) x = 0;
			if( x > 100 ) x = 100;

			return Math.round( x*10 ) / 10;
		},

		redraw: function( pointer ){
			if( !this.is.init ) return false;

			this.setValue();

			// redraw range line
			if( this.o.pointers[0] && this.o.pointers[1] )
				this.o.value.css({ left: this.o.pointers[0].value.prc + "%", width: ( this.o.pointers[1].value.prc - this.o.pointers[0].value.prc ) + "%" });

			this.o.labels[pointer.uid].value.html(
				this.nice(
					pointer.value.origin
				)
			);

			// redraw position of labels
			this.redrawLabels( pointer );

		},

		redrawLabels: function( pointer ){

			function setPosition( label, sizes, prc ){
				sizes.margin = -sizes.label/2;

				// left limit
				label_left = sizes.border + sizes.margin;
				if( label_left < 0 )
					sizes.margin -= label_left;

				// right limit
				if( sizes.border+sizes.label / 2 > self.sizes.domWidth ){
					sizes.margin = 0;
					sizes.right = true;
				} else
					sizes.right = false;

				label.o.css({ left: prc + "%", marginLeft: sizes.margin, right: "auto" });
				if( sizes.right ) label.o.css({ left: "auto", right: 0 });
				return sizes;
			}

			var self = this;
			var label = this.o.labels[pointer.uid];
			var prc = pointer.value.prc;

			var sizes = {
				label: label.o.outerWidth(),
				right: false,
				border: ( prc * this.sizes.domWidth ) / 100
			};

			//console.log(this.o.pointers[1-pointer.uid])
			if( !this.settings.single ){
				// glue if near;
				var another = this.o.pointers[1-pointer.uid];
				var another_label = this.o.labels[another.uid];

				switch( pointer.uid ){
					case 0:
						if( sizes.border+sizes.label / 2 > another_label.o.offset().left-this.sizes.domOffset.left ){
							another_label.o.css({ visibility: "hidden" });
							another_label.value.html( this.nice( another.value.origin ) );

							label.o.css({ visibility: "visible" });

							prc = ( another.value.prc - prc ) / 2 + prc;
							if( another.value.prc != pointer.value.prc ){
								label.value.html( this.nice(pointer.value.origin) + "&nbsp;&ndash;&nbsp;" + this.nice(another.value.origin) );
								sizes.label = label.o.outerWidth();
								sizes.border = ( prc * this.sizes.domWidth ) / 100;
							}
						} else {
							another_label.o.css({ visibility: "visible" });
						}
						break;

					case 1:
						if( sizes.border - sizes.label / 2 < another_label.o.offset().left - this.sizes.domOffset.left + another_label.o.outerWidth() ){
							another_label.o.css({ visibility: "hidden" });
							another_label.value.html( this.nice(another.value.origin) );

							label.o.css({ visibility: "visible" });

							prc = ( prc - another.value.prc ) / 2 + another.value.prc;
							if( another.value.prc != pointer.value.prc ){
								label.value.html( this.nice(another.value.origin) + "&nbsp;&ndash;&nbsp;" + this.nice(pointer.value.origin) );
								sizes.label = label.o.outerWidth();
								sizes.border = ( prc * this.sizes.domWidth ) / 100;
							}
						} else {
							another_label.o.css({ visibility: "visible" });
						}
						break;
				}
			}

			sizes = setPosition( label, sizes, prc );

			/* draw second label */
			if( another_label ){
				var sizes = {
					label: another_label.o.outerWidth(),
					right: false,
					border: ( another.value.prc * this.sizes.domWidth ) / 100
				};
				sizes = setPosition( another_label, sizes, another.value.prc );
			}

			this.redrawLimits();
		},

		redrawLimits: function(){
			if( this.settings.limits ){

				var limits = [ true, true ];

				for( key in this.o.pointers ){

					if( !this.settings.single || key == 0 ){

						var pointer = this.o.pointers[key];
						var label = this.o.labels[pointer.uid];
						var label_left = label.o.offset().left - this.sizes.domOffset.left;

						var limit = this.o.limits[0];
						if( label_left < limit.outerWidth() )
							limits[0] = false;

						var limit = this.o.limits[1];
						if( label_left + label.o.outerWidth() > this.sizes.domWidth - limit.outerWidth() )
							limits[1] = false;
					}

				};

				for( var i=0; i < limits.length; i++ ){
					if( limits[i] )
						this.o.limits[i].fadeIn("fast");
					else
						this.o.limits[i].fadeOut("fast");
				};

			}
		},

		setValue: function(){
			var value = this.getValue();
			this.inputNode.attr( "value", value );
			this.onstatechange.call( this, value );
		},
		getValue: function(){
			if(!this.is.init) return false;
			var $this = this;

			var value = "";
			$.each( this.o.pointers, function(i){
				if( this.value.prc != undefined && !isNaN(this.value.prc) ) value += (i > 0 ? ";" : "") + $this.prcToValue( this.value.prc );
			});
			return value;
		},
		getPrcValue: function(){
			if(!this.is.init) return false;
			var $this = this;

			var value = "";
			$.each( this.o.pointers, function(i){
				if( this.value.prc != undefined && !isNaN(this.value.prc) ) value += (i > 0 ? ";" : "") + this.value.prc;
			});
			return value;
		},
		prcToValue: function( prc ){

			if( this.settings.heterogeneity && this.settings.heterogeneity.length > 0 ){
				var h = this.settings.heterogeneity;

				var _start = 0;
				var _from = this.settings.from;

				for( var i=0; i <= h.length; i++ ){
					if( h[i] ) var v = h[i].split("/");
					else			 var v = [100, this.settings.to];

					v[0] = new Number(v[0]);
					v[1] = new Number(v[1]);

					if( prc >= _start && prc <= v[0] ) {
						var value = _from + ( (prc-_start) * (v[1]-_from) ) / (v[0]-_start);
					}

					_start = v[0];
					_from = v[1];
				};

			} else {
				var value = this.settings.from + ( prc * this.settings.interval ) / 100;
			}

			return this.round( value );
		},

		valueToPrc: function( value, pointer ){
			if( this.settings.heterogeneity && this.settings.heterogeneity.length > 0 ){
				var h = this.settings.heterogeneity;

				var _start = 0;
				var _from = this.settings.from;

				for (var i=0; i <= h.length; i++) {
					if(h[i]) var v = h[i].split("/");
					else		 var v = [100, this.settings.to];
					v[0] = new Number(v[0]); v[1] = new Number(v[1]);

					if(value >= _from && value <= v[1]){
						var prc = pointer.limits(_start + (value-_from)*(v[0]-_start)/(v[1]-_from));
					}

					_start = v[0]; _from = v[1];
				};

			} else {
				var prc = pointer.limits((value-this.settings.from)*100/this.settings.interval);
			}

			return prc;
		},

		round: function( value ){
			value = Math.round( value / this.settings.step ) * this.settings.step;
			if( this.settings.round ) value = Math.round( value * Math.pow(10, this.settings.round) ) / Math.pow(10, this.settings.round);
			else value = Math.round( value );
			return value;
		},

		nice: function( value ){
			value = value.toString().replace(/,/gi, ".");
			value = value.toString().replace(/ /gi, "");
			if( Number.prototype.jSliderNice )
				return (new Number(value)).jSliderNice(this.settings.round).replace(/-/gi, "&minus;");
			else
				return new Number(value);
		}

	};

	function jSliderPointer(){
		this.baseConstructor.apply(this, arguments);
	}

	jSliderPointer.inheritFrom(Draggable, {
		oninit: function( ptr, id, _constructor ){
			this.uid = id;
			this.parent = _constructor;
			this.value = {};
			this.settings = this.parent.settings;
		},
		onmousedown: function(evt){
			this._parent = {
				offset: this.parent.domNode.offset(),
				width: this.parent.domNode.width()
			};
			this.ptr.addDependClass("hover");
			this.setIndexOver();
		},
		onmousemove: function( evt, x ){
			var coords = this._getPageCoords( evt );
			this._set( this.calc( coords.x ) );
		},
		onmouseup: function( evt ){
			// var coords = this._getPageCoords( evt );
			// this._set( this.calc( coords.x ) );

			if( this.parent.settings.callback && $.isFunction(this.parent.settings.callback) )
				this.parent.settings.callback.call( this.parent, this.parent.getValue() );

			this.ptr.removeDependClass("hover");
		},

		setIndexOver: function(){
			this.parent.setPointersIndex( 1 );
			this.index( 2 );
		},

		index: function( i ){
			this.ptr.css({ zIndex: i });
		},

		limits: function( x ){
			return this.parent.limits( x, this );
		},

		calc: function(coords){
			var x = this.limits(((coords-this._parent.offset.left)*100)/this._parent.width);
			return x;
		},

		set: function( value, opt_origin ){
			this.value.origin = this.parent.round(value);
			this._set( this.parent.valueToPrc( value, this ), opt_origin );
		},
		_set: function( prc, opt_origin ){
			if( !opt_origin )
				this.value.origin = this.parent.prcToValue(prc);

			this.value.prc = prc;
			this.ptr.css({ left: prc + "%" });
			this.parent.redraw(this);
		}
	});
})(jQuery);

/* end */
