/*! * jquery ui slider 1.10.4 * http://jqueryui.com * * copyright 2014 jquery foundation and other contributors * released under the mit license. * http://jquery.org/license * * http://api.jqueryui.com/slider/ * * depends: * jquery.ui.core.js * jquery.ui.mouse.js * jquery.ui.widget.js */ (function( $, undefined ) { // number of pages in a slider // (how many times can you page up/down to go through the whole range) var numpages = 5; $.widget( "ui.slider", $.ui.mouse, { version: "1.10.4", widgeteventprefix: "slide", options: { animate: false, distance: 0, max: 100, min: 0, orientation: "horizontal", range: false, step: 1, value: 0, values: null, // callbacks change: null, slide: null, start: null, stop: null }, _create: function() { this._keysliding = false; this._mousesliding = false; this._animateoff = true; this._handleindex = null; this._detectorientation(); this._mouseinit(); this.element .addclass( "ui-slider" + " ui-slider-" + this.orientation + " ui-widget" + " ui-widget-content" + " ui-corner-all"); this._refresh(); this._setoption( "disabled", this.options.disabled ); this._animateoff = false; }, _refresh: function() { this._createrange(); this._createhandles(); this._setupevents(); this._refreshvalue(); }, _createhandles: function() { var i, handlecount, options = this.options, existinghandles = this.element.find( ".ui-slider-handle" ).addclass( "ui-state-default ui-corner-all" ), handle = "", handles = []; handlecount = ( options.values && options.values.length ) || 1; if ( existinghandles.length > handlecount ) { existinghandles.slice( handlecount ).remove(); existinghandles = existinghandles.slice( 0, handlecount ); } for ( i = existinghandles.length; i < handlecount; i++ ) { handles.push( handle ); } this.handles = existinghandles.add( $( handles.join( "" ) ).appendto( this.element ) ); this.handle = this.handles.eq( 0 ); this.handles.each(function( i ) { $( this ).data( "ui-slider-handle-index", i ); }); }, _createrange: function() { var options = this.options, classes = ""; if ( options.range ) { if ( options.range === true ) { if ( !options.values ) { options.values = [ this._valuemin(), this._valuemin() ]; } else if ( options.values.length && options.values.length !== 2 ) { options.values = [ options.values[0], options.values[0] ]; } else if ( $.isarray( options.values ) ) { options.values = options.values.slice(0); } } if ( !this.range || !this.range.length ) { this.range = $( "
" ) .appendto( this.element ); classes = "ui-slider-range" + // note: this isn't the most fittingly semantic framework class for this element, // but worked best visually with a variety of themes " ui-widget-header ui-corner-all"; } else { this.range.removeclass( "ui-slider-range-min ui-slider-range-max" ) // handle range switching from true to min/max .css({ "left": "", "bottom": "" }); } this.range.addclass( classes + ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) ); } else { if ( this.range ) { this.range.remove(); } this.range = null; } }, _setupevents: function() { var elements = this.handles.add( this.range ).filter( "a" ); this._off( elements ); this._on( elements, this._handleevents ); this._hoverable( elements ); this._focusable( elements ); }, _destroy: function() { this.handles.remove(); if ( this.range ) { this.range.remove(); } this.element .removeclass( "ui-slider" + " ui-slider-horizontal" + " ui-slider-vertical" + " ui-widget" + " ui-widget-content" + " ui-corner-all" ); this._mousedestroy(); }, _mousecapture: function( event ) { var position, normvalue, distance, closesthandle, index, allowed, offset, mouseoverhandle, that = this, o = this.options; if ( o.disabled ) { return false; } this.elementsize = { width: this.element.outerwidth(), height: this.element.outerheight() }; this.elementoffset = this.element.offset(); position = { x: event.pagex, y: event.pagey }; normvalue = this._normvaluefrommouse( position ); distance = this._valuemax() - this._valuemin() + 1; this.handles.each(function( i ) { var thisdistance = math.abs( normvalue - that.values(i) ); if (( distance > thisdistance ) || ( distance === thisdistance && (i === that._lastchangedvalue || that.values(i) === o.min ))) { distance = thisdistance; closesthandle = $( this ); index = i; } }); allowed = this._start( event, index ); if ( allowed === false ) { return false; } this._mousesliding = true; this._handleindex = index; closesthandle .addclass( "ui-state-active" ) .focus(); offset = closesthandle.offset(); mouseoverhandle = !$( event.target ).parents().addback().is( ".ui-slider-handle" ); this._clickoffset = mouseoverhandle ? { left: 0, top: 0 } : { left: event.pagex - offset.left - ( closesthandle.width() / 2 ), top: event.pagey - offset.top - ( closesthandle.height() / 2 ) - ( parseint( closesthandle.css("bordertopwidth"), 10 ) || 0 ) - ( parseint( closesthandle.css("borderbottomwidth"), 10 ) || 0) + ( parseint( closesthandle.css("margintop"), 10 ) || 0) }; if ( !this.handles.hasclass( "ui-state-hover" ) ) { this._slide( event, index, normvalue ); } this._animateoff = true; return true; }, _mousestart: function() { return true; }, _mousedrag: function( event ) { var position = { x: event.pagex, y: event.pagey }, normvalue = this._normvaluefrommouse( position ); this._slide( event, this._handleindex, normvalue ); return false; }, _mousestop: function( event ) { this.handles.removeclass( "ui-state-active" ); this._mousesliding = false; this._stop( event, this._handleindex ); this._change( event, this._handleindex ); this._handleindex = null; this._clickoffset = null; this._animateoff = false; return false; }, _detectorientation: function() { this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; }, _normvaluefrommouse: function( position ) { var pixeltotal, pixelmouse, percentmouse, valuetotal, valuemouse; if ( this.orientation === "horizontal" ) { pixeltotal = this.elementsize.width; pixelmouse = position.x - this.elementoffset.left - ( this._clickoffset ? this._clickoffset.left : 0 ); } else { pixeltotal = this.elementsize.height; pixelmouse = position.y - this.elementoffset.top - ( this._clickoffset ? this._clickoffset.top : 0 ); } percentmouse = ( pixelmouse / pixeltotal ); if ( percentmouse > 1 ) { percentmouse = 1; } if ( percentmouse < 0 ) { percentmouse = 0; } if ( this.orientation === "vertical" ) { percentmouse = 1 - percentmouse; } valuetotal = this._valuemax() - this._valuemin(); valuemouse = this._valuemin() + percentmouse * valuetotal; return this._trimalignvalue( valuemouse ); }, _start: function( event, index ) { var uihash = { handle: this.handles[ index ], value: this.value() }; if ( this.options.values && this.options.values.length ) { uihash.value = this.values( index ); uihash.values = this.values(); } return this._trigger( "start", event, uihash ); }, _slide: function( event, index, newval ) { var otherval, newvalues, allowed; if ( this.options.values && this.options.values.length ) { otherval = this.values( index ? 0 : 1 ); if ( ( this.options.values.length === 2 && this.options.range === true ) && ( ( index === 0 && newval > otherval) || ( index === 1 && newval < otherval ) ) ) { newval = otherval; } if ( newval !== this.values( index ) ) { newvalues = this.values(); newvalues[ index ] = newval; // a slide can be canceled by returning false from the slide callback allowed = this._trigger( "slide", event, { handle: this.handles[ index ], value: newval, values: newvalues } ); otherval = this.values( index ? 0 : 1 ); if ( allowed !== false ) { this.values( index, newval ); } } } else { if ( newval !== this.value() ) { // a slide can be canceled by returning false from the slide callback allowed = this._trigger( "slide", event, { handle: this.handles[ index ], value: newval } ); if ( allowed !== false ) { this.value( newval ); } } } }, _stop: function( event, index ) { var uihash = { handle: this.handles[ index ], value: this.value() }; if ( this.options.values && this.options.values.length ) { uihash.value = this.values( index ); uihash.values = this.values(); } this._trigger( "stop", event, uihash ); }, _change: function( event, index ) { if ( !this._keysliding && !this._mousesliding ) { var uihash = { handle: this.handles[ index ], value: this.value() }; if ( this.options.values && this.options.values.length ) { uihash.value = this.values( index ); uihash.values = this.values(); } //store the last changed value index for reference when handles overlap this._lastchangedvalue = index; this._trigger( "change", event, uihash ); } }, value: function( newvalue ) { if ( arguments.length ) { this.options.value = this._trimalignvalue( newvalue ); this._refreshvalue(); this._change( null, 0 ); return; } return this._value(); }, values: function( index, newvalue ) { var vals, newvalues, i; if ( arguments.length > 1 ) { this.options.values[ index ] = this._trimalignvalue( newvalue ); this._refreshvalue(); this._change( null, index ); return; } if ( arguments.length ) { if ( $.isarray( arguments[ 0 ] ) ) { vals = this.options.values; newvalues = arguments[ 0 ]; for ( i = 0; i < vals.length; i += 1 ) { vals[ i ] = this._trimalignvalue( newvalues[ i ] ); this._change( null, i ); } this._refreshvalue(); } else { if ( this.options.values && this.options.values.length ) { return this._values( index ); } else { return this.value(); } } } else { return this._values(); } }, _setoption: function( key, value ) { var i, valslength = 0; if ( key === "range" && this.options.range === true ) { if ( value === "min" ) { this.options.value = this._values( 0 ); this.options.values = null; } else if ( value === "max" ) { this.options.value = this._values( this.options.values.length-1 ); this.options.values = null; } } if ( $.isarray( this.options.values ) ) { valslength = this.options.values.length; } $.widget.prototype._setoption.apply( this, arguments ); switch ( key ) { case "orientation": this._detectorientation(); this.element .removeclass( "ui-slider-horizontal ui-slider-vertical" ) .addclass( "ui-slider-" + this.orientation ); this._refreshvalue(); break; case "value": this._animateoff = true; this._refreshvalue(); this._change( null, 0 ); this._animateoff = false; break; case "values": this._animateoff = true; this._refreshvalue(); for ( i = 0; i < valslength; i += 1 ) { this._change( null, i ); } this._animateoff = false; break; case "min": case "max": this._animateoff = true; this._refreshvalue(); this._animateoff = false; break; case "range": this._animateoff = true; this._refresh(); this._animateoff = false; break; } }, //internal value getter // _value() returns value trimmed by min and max, aligned by step _value: function() { var val = this.options.value; val = this._trimalignvalue( val ); return val; }, //internal values getter // _values() returns array of values trimmed by min and max, aligned by step // _values( index ) returns single value trimmed by min and max, aligned by step _values: function( index ) { var val, vals, i; if ( arguments.length ) { val = this.options.values[ index ]; val = this._trimalignvalue( val ); return val; } else if ( this.options.values && this.options.values.length ) { // .slice() creates a copy of the array // this copy gets trimmed by min and max and then returned vals = this.options.values.slice(); for ( i = 0; i < vals.length; i+= 1) { vals[ i ] = this._trimalignvalue( vals[ i ] ); } return vals; } else { return []; } }, // returns the step-aligned value that val is closest to, between (inclusive) min and max _trimalignvalue: function( val ) { if ( val <= this._valuemin() ) { return this._valuemin(); } if ( val >= this._valuemax() ) { return this._valuemax(); } var step = ( this.options.step > 0 ) ? this.options.step : 1, valmodstep = (val - this._valuemin()) % step, alignvalue = val - valmodstep; if ( math.abs(valmodstep) * 2 >= step ) { alignvalue += ( valmodstep > 0 ) ? step : ( -step ); } // since javascript has problems with large floats, round // the final value to 5 digits after the decimal point (see #4124) return parsefloat( alignvalue.tofixed(5) ); }, _valuemin: function() { return this.options.min; }, _valuemax: function() { return this.options.max; }, _refreshvalue: function() { var lastvalpercent, valpercent, value, valuemin, valuemax, orange = this.options.range, o = this.options, that = this, animate = ( !this._animateoff ) ? o.animate : false, _set = {}; if ( this.options.values && this.options.values.length ) { this.handles.each(function( i ) { valpercent = ( that.values(i) - that._valuemin() ) / ( that._valuemax() - that._valuemin() ) * 100; _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valpercent + "%"; $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); if ( that.options.range === true ) { if ( that.orientation === "horizontal" ) { if ( i === 0 ) { that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valpercent + "%" }, o.animate ); } if ( i === 1 ) { that.range[ animate ? "animate" : "css" ]( { width: ( valpercent - lastvalpercent ) + "%" }, { queue: false, duration: o.animate } ); } } else { if ( i === 0 ) { that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valpercent ) + "%" }, o.animate ); } if ( i === 1 ) { that.range[ animate ? "animate" : "css" ]( { height: ( valpercent - lastvalpercent ) + "%" }, { queue: false, duration: o.animate } ); } } } lastvalpercent = valpercent; }); } else { value = this.value(); valuemin = this._valuemin(); valuemax = this._valuemax(); valpercent = ( valuemax !== valuemin ) ? ( value - valuemin ) / ( valuemax - valuemin ) * 100 : 0; _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valpercent + "%"; this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); if ( orange === "min" && this.orientation === "horizontal" ) { this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valpercent + "%" }, o.animate ); } if ( orange === "max" && this.orientation === "horizontal" ) { this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valpercent ) + "%" }, { queue: false, duration: o.animate } ); } if ( orange === "min" && this.orientation === "vertical" ) { this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valpercent + "%" }, o.animate ); } if ( orange === "max" && this.orientation === "vertical" ) { this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valpercent ) + "%" }, { queue: false, duration: o.animate } ); } } }, _handleevents: { keydown: function( event ) { var allowed, curval, newval, step, index = $( event.target ).data( "ui-slider-handle-index" ); switch ( event.keycode ) { case $.ui.keycode.home: case $.ui.keycode.end: case $.ui.keycode.page_up: case $.ui.keycode.page_down: case $.ui.keycode.up: case $.ui.keycode.right: case $.ui.keycode.down: case $.ui.keycode.left: event.preventdefault(); if ( !this._keysliding ) { this._keysliding = true; $( event.target ).addclass( "ui-state-active" ); allowed = this._start( event, index ); if ( allowed === false ) { return; } } break; } step = this.options.step; if ( this.options.values && this.options.values.length ) { curval = newval = this.values( index ); } else { curval = newval = this.value(); } switch ( event.keycode ) { case $.ui.keycode.home: newval = this._valuemin(); break; case $.ui.keycode.end: newval = this._valuemax(); break; case $.ui.keycode.page_up: newval = this._trimalignvalue( curval + ( (this._valuemax() - this._valuemin()) / numpages ) ); break; case $.ui.keycode.page_down: newval = this._trimalignvalue( curval - ( (this._valuemax() - this._valuemin()) / numpages ) ); break; case $.ui.keycode.up: case $.ui.keycode.right: if ( curval === this._valuemax() ) { return; } newval = this._trimalignvalue( curval + step ); break; case $.ui.keycode.down: case $.ui.keycode.left: if ( curval === this._valuemin() ) { return; } newval = this._trimalignvalue( curval - step ); break; } this._slide( event, index, newval ); }, click: function( event ) { event.preventdefault(); }, keyup: function( event ) { var index = $( event.target ).data( "ui-slider-handle-index" ); if ( this._keysliding ) { this._keysliding = false; this._stop( event, index ); this._change( event, index ); $( event.target ).removeclass( "ui-state-active" ); } } } }); }(jquery));