Brought in following assets that Kevin's EDI project will be using:
[openemr.git] / public / assets / jquery-ui-1-10-4 / ui / jquery.ui.slider.js
blob039c0ef1770d8e52c212dbcd1ba0c1d7af896e31
1 /*!
2  * jQuery UI Slider 1.10.4
3  * http://jqueryui.com
4  *
5  * Copyright 2014 jQuery Foundation and other contributors
6  * Released under the MIT license.
7  * http://jquery.org/license
8  *
9  * http://api.jqueryui.com/slider/
10  *
11  * Depends:
12  *      jquery.ui.core.js
13  *      jquery.ui.mouse.js
14  *      jquery.ui.widget.js
15  */
16 (function( $, undefined ) {
18 // number of pages in a slider
19 // (how many times can you page up/down to go through the whole range)
20 var numPages = 5;
22 $.widget( "ui.slider", $.ui.mouse, {
23         version: "1.10.4",
24         widgetEventPrefix: "slide",
26         options: {
27                 animate: false,
28                 distance: 0,
29                 max: 100,
30                 min: 0,
31                 orientation: "horizontal",
32                 range: false,
33                 step: 1,
34                 value: 0,
35                 values: null,
37                 // callbacks
38                 change: null,
39                 slide: null,
40                 start: null,
41                 stop: null
42         },
44         _create: function() {
45                 this._keySliding = false;
46                 this._mouseSliding = false;
47                 this._animateOff = true;
48                 this._handleIndex = null;
49                 this._detectOrientation();
50                 this._mouseInit();
52                 this.element
53                         .addClass( "ui-slider" +
54                                 " ui-slider-" + this.orientation +
55                                 " ui-widget" +
56                                 " ui-widget-content" +
57                                 " ui-corner-all");
59                 this._refresh();
60                 this._setOption( "disabled", this.options.disabled );
62                 this._animateOff = false;
63         },
65         _refresh: function() {
66                 this._createRange();
67                 this._createHandles();
68                 this._setupEvents();
69                 this._refreshValue();
70         },
72         _createHandles: function() {
73                 var i, handleCount,
74                         options = this.options,
75                         existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
76                         handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
77                         handles = [];
79                 handleCount = ( options.values && options.values.length ) || 1;
81                 if ( existingHandles.length > handleCount ) {
82                         existingHandles.slice( handleCount ).remove();
83                         existingHandles = existingHandles.slice( 0, handleCount );
84                 }
86                 for ( i = existingHandles.length; i < handleCount; i++ ) {
87                         handles.push( handle );
88                 }
90                 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
92                 this.handle = this.handles.eq( 0 );
94                 this.handles.each(function( i ) {
95                         $( this ).data( "ui-slider-handle-index", i );
96                 });
97         },
99         _createRange: function() {
100                 var options = this.options,
101                         classes = "";
103                 if ( options.range ) {
104                         if ( options.range === true ) {
105                                 if ( !options.values ) {
106                                         options.values = [ this._valueMin(), this._valueMin() ];
107                                 } else if ( options.values.length && options.values.length !== 2 ) {
108                                         options.values = [ options.values[0], options.values[0] ];
109                                 } else if ( $.isArray( options.values ) ) {
110                                         options.values = options.values.slice(0);
111                                 }
112                         }
114                         if ( !this.range || !this.range.length ) {
115                                 this.range = $( "<div></div>" )
116                                         .appendTo( this.element );
118                                 classes = "ui-slider-range" +
119                                 // note: this isn't the most fittingly semantic framework class for this element,
120                                 // but worked best visually with a variety of themes
121                                 " ui-widget-header ui-corner-all";
122                         } else {
123                                 this.range.removeClass( "ui-slider-range-min ui-slider-range-max" )
124                                         // Handle range switching from true to min/max
125                                         .css({
126                                                 "left": "",
127                                                 "bottom": ""
128                                         });
129                         }
131                         this.range.addClass( classes +
132                                 ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) );
133                 } else {
134                         if ( this.range ) {
135                                 this.range.remove();
136                         }
137                         this.range = null;
138                 }
139         },
141         _setupEvents: function() {
142                 var elements = this.handles.add( this.range ).filter( "a" );
143                 this._off( elements );
144                 this._on( elements, this._handleEvents );
145                 this._hoverable( elements );
146                 this._focusable( elements );
147         },
149         _destroy: function() {
150                 this.handles.remove();
151                 if ( this.range ) {
152                         this.range.remove();
153                 }
155                 this.element
156                         .removeClass( "ui-slider" +
157                                 " ui-slider-horizontal" +
158                                 " ui-slider-vertical" +
159                                 " ui-widget" +
160                                 " ui-widget-content" +
161                                 " ui-corner-all" );
163                 this._mouseDestroy();
164         },
166         _mouseCapture: function( event ) {
167                 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
168                         that = this,
169                         o = this.options;
171                 if ( o.disabled ) {
172                         return false;
173                 }
175                 this.elementSize = {
176                         width: this.element.outerWidth(),
177                         height: this.element.outerHeight()
178                 };
179                 this.elementOffset = this.element.offset();
181                 position = { x: event.pageX, y: event.pageY };
182                 normValue = this._normValueFromMouse( position );
183                 distance = this._valueMax() - this._valueMin() + 1;
184                 this.handles.each(function( i ) {
185                         var thisDistance = Math.abs( normValue - that.values(i) );
186                         if (( distance > thisDistance ) ||
187                                 ( distance === thisDistance &&
188                                         (i === that._lastChangedValue || that.values(i) === o.min ))) {
189                                 distance = thisDistance;
190                                 closestHandle = $( this );
191                                 index = i;
192                         }
193                 });
195                 allowed = this._start( event, index );
196                 if ( allowed === false ) {
197                         return false;
198                 }
199                 this._mouseSliding = true;
201                 this._handleIndex = index;
203                 closestHandle
204                         .addClass( "ui-state-active" )
205                         .focus();
207                 offset = closestHandle.offset();
208                 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
209                 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
210                         left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
211                         top: event.pageY - offset.top -
212                                 ( closestHandle.height() / 2 ) -
213                                 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
214                                 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
215                                 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
216                 };
218                 if ( !this.handles.hasClass( "ui-state-hover" ) ) {
219                         this._slide( event, index, normValue );
220                 }
221                 this._animateOff = true;
222                 return true;
223         },
225         _mouseStart: function() {
226                 return true;
227         },
229         _mouseDrag: function( event ) {
230                 var position = { x: event.pageX, y: event.pageY },
231                         normValue = this._normValueFromMouse( position );
233                 this._slide( event, this._handleIndex, normValue );
235                 return false;
236         },
238         _mouseStop: function( event ) {
239                 this.handles.removeClass( "ui-state-active" );
240                 this._mouseSliding = false;
242                 this._stop( event, this._handleIndex );
243                 this._change( event, this._handleIndex );
245                 this._handleIndex = null;
246                 this._clickOffset = null;
247                 this._animateOff = false;
249                 return false;
250         },
252         _detectOrientation: function() {
253                 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
254         },
256         _normValueFromMouse: function( position ) {
257                 var pixelTotal,
258                         pixelMouse,
259                         percentMouse,
260                         valueTotal,
261                         valueMouse;
263                 if ( this.orientation === "horizontal" ) {
264                         pixelTotal = this.elementSize.width;
265                         pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
266                 } else {
267                         pixelTotal = this.elementSize.height;
268                         pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
269                 }
271                 percentMouse = ( pixelMouse / pixelTotal );
272                 if ( percentMouse > 1 ) {
273                         percentMouse = 1;
274                 }
275                 if ( percentMouse < 0 ) {
276                         percentMouse = 0;
277                 }
278                 if ( this.orientation === "vertical" ) {
279                         percentMouse = 1 - percentMouse;
280                 }
282                 valueTotal = this._valueMax() - this._valueMin();
283                 valueMouse = this._valueMin() + percentMouse * valueTotal;
285                 return this._trimAlignValue( valueMouse );
286         },
288         _start: function( event, index ) {
289                 var uiHash = {
290                         handle: this.handles[ index ],
291                         value: this.value()
292                 };
293                 if ( this.options.values && this.options.values.length ) {
294                         uiHash.value = this.values( index );
295                         uiHash.values = this.values();
296                 }
297                 return this._trigger( "start", event, uiHash );
298         },
300         _slide: function( event, index, newVal ) {
301                 var otherVal,
302                         newValues,
303                         allowed;
305                 if ( this.options.values && this.options.values.length ) {
306                         otherVal = this.values( index ? 0 : 1 );
308                         if ( ( this.options.values.length === 2 && this.options.range === true ) &&
309                                         ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
310                                 ) {
311                                 newVal = otherVal;
312                         }
314                         if ( newVal !== this.values( index ) ) {
315                                 newValues = this.values();
316                                 newValues[ index ] = newVal;
317                                 // A slide can be canceled by returning false from the slide callback
318                                 allowed = this._trigger( "slide", event, {
319                                         handle: this.handles[ index ],
320                                         value: newVal,
321                                         values: newValues
322                                 } );
323                                 otherVal = this.values( index ? 0 : 1 );
324                                 if ( allowed !== false ) {
325                                         this.values( index, newVal );
326                                 }
327                         }
328                 } else {
329                         if ( newVal !== this.value() ) {
330                                 // A slide can be canceled by returning false from the slide callback
331                                 allowed = this._trigger( "slide", event, {
332                                         handle: this.handles[ index ],
333                                         value: newVal
334                                 } );
335                                 if ( allowed !== false ) {
336                                         this.value( newVal );
337                                 }
338                         }
339                 }
340         },
342         _stop: function( event, index ) {
343                 var uiHash = {
344                         handle: this.handles[ index ],
345                         value: this.value()
346                 };
347                 if ( this.options.values && this.options.values.length ) {
348                         uiHash.value = this.values( index );
349                         uiHash.values = this.values();
350                 }
352                 this._trigger( "stop", event, uiHash );
353         },
355         _change: function( event, index ) {
356                 if ( !this._keySliding && !this._mouseSliding ) {
357                         var uiHash = {
358                                 handle: this.handles[ index ],
359                                 value: this.value()
360                         };
361                         if ( this.options.values && this.options.values.length ) {
362                                 uiHash.value = this.values( index );
363                                 uiHash.values = this.values();
364                         }
366                         //store the last changed value index for reference when handles overlap
367                         this._lastChangedValue = index;
369                         this._trigger( "change", event, uiHash );
370                 }
371         },
373         value: function( newValue ) {
374                 if ( arguments.length ) {
375                         this.options.value = this._trimAlignValue( newValue );
376                         this._refreshValue();
377                         this._change( null, 0 );
378                         return;
379                 }
381                 return this._value();
382         },
384         values: function( index, newValue ) {
385                 var vals,
386                         newValues,
387                         i;
389                 if ( arguments.length > 1 ) {
390                         this.options.values[ index ] = this._trimAlignValue( newValue );
391                         this._refreshValue();
392                         this._change( null, index );
393                         return;
394                 }
396                 if ( arguments.length ) {
397                         if ( $.isArray( arguments[ 0 ] ) ) {
398                                 vals = this.options.values;
399                                 newValues = arguments[ 0 ];
400                                 for ( i = 0; i < vals.length; i += 1 ) {
401                                         vals[ i ] = this._trimAlignValue( newValues[ i ] );
402                                         this._change( null, i );
403                                 }
404                                 this._refreshValue();
405                         } else {
406                                 if ( this.options.values && this.options.values.length ) {
407                                         return this._values( index );
408                                 } else {
409                                         return this.value();
410                                 }
411                         }
412                 } else {
413                         return this._values();
414                 }
415         },
417         _setOption: function( key, value ) {
418                 var i,
419                         valsLength = 0;
421                 if ( key === "range" && this.options.range === true ) {
422                         if ( value === "min" ) {
423                                 this.options.value = this._values( 0 );
424                                 this.options.values = null;
425                         } else if ( value === "max" ) {
426                                 this.options.value = this._values( this.options.values.length-1 );
427                                 this.options.values = null;
428                         }
429                 }
431                 if ( $.isArray( this.options.values ) ) {
432                         valsLength = this.options.values.length;
433                 }
435                 $.Widget.prototype._setOption.apply( this, arguments );
437                 switch ( key ) {
438                         case "orientation":
439                                 this._detectOrientation();
440                                 this.element
441                                         .removeClass( "ui-slider-horizontal ui-slider-vertical" )
442                                         .addClass( "ui-slider-" + this.orientation );
443                                 this._refreshValue();
444                                 break;
445                         case "value":
446                                 this._animateOff = true;
447                                 this._refreshValue();
448                                 this._change( null, 0 );
449                                 this._animateOff = false;
450                                 break;
451                         case "values":
452                                 this._animateOff = true;
453                                 this._refreshValue();
454                                 for ( i = 0; i < valsLength; i += 1 ) {
455                                         this._change( null, i );
456                                 }
457                                 this._animateOff = false;
458                                 break;
459                         case "min":
460                         case "max":
461                                 this._animateOff = true;
462                                 this._refreshValue();
463                                 this._animateOff = false;
464                                 break;
465                         case "range":
466                                 this._animateOff = true;
467                                 this._refresh();
468                                 this._animateOff = false;
469                                 break;
470                 }
471         },
473         //internal value getter
474         // _value() returns value trimmed by min and max, aligned by step
475         _value: function() {
476                 var val = this.options.value;
477                 val = this._trimAlignValue( val );
479                 return val;
480         },
482         //internal values getter
483         // _values() returns array of values trimmed by min and max, aligned by step
484         // _values( index ) returns single value trimmed by min and max, aligned by step
485         _values: function( index ) {
486                 var val,
487                         vals,
488                         i;
490                 if ( arguments.length ) {
491                         val = this.options.values[ index ];
492                         val = this._trimAlignValue( val );
494                         return val;
495                 } else if ( this.options.values && this.options.values.length ) {
496                         // .slice() creates a copy of the array
497                         // this copy gets trimmed by min and max and then returned
498                         vals = this.options.values.slice();
499                         for ( i = 0; i < vals.length; i+= 1) {
500                                 vals[ i ] = this._trimAlignValue( vals[ i ] );
501                         }
503                         return vals;
504                 } else {
505                         return [];
506                 }
507         },
509         // returns the step-aligned value that val is closest to, between (inclusive) min and max
510         _trimAlignValue: function( val ) {
511                 if ( val <= this._valueMin() ) {
512                         return this._valueMin();
513                 }
514                 if ( val >= this._valueMax() ) {
515                         return this._valueMax();
516                 }
517                 var step = ( this.options.step > 0 ) ? this.options.step : 1,
518                         valModStep = (val - this._valueMin()) % step,
519                         alignValue = val - valModStep;
521                 if ( Math.abs(valModStep) * 2 >= step ) {
522                         alignValue += ( valModStep > 0 ) ? step : ( -step );
523                 }
525                 // Since JavaScript has problems with large floats, round
526                 // the final value to 5 digits after the decimal point (see #4124)
527                 return parseFloat( alignValue.toFixed(5) );
528         },
530         _valueMin: function() {
531                 return this.options.min;
532         },
534         _valueMax: function() {
535                 return this.options.max;
536         },
538         _refreshValue: function() {
539                 var lastValPercent, valPercent, value, valueMin, valueMax,
540                         oRange = this.options.range,
541                         o = this.options,
542                         that = this,
543                         animate = ( !this._animateOff ) ? o.animate : false,
544                         _set = {};
546                 if ( this.options.values && this.options.values.length ) {
547                         this.handles.each(function( i ) {
548                                 valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
549                                 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
550                                 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
551                                 if ( that.options.range === true ) {
552                                         if ( that.orientation === "horizontal" ) {
553                                                 if ( i === 0 ) {
554                                                         that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
555                                                 }
556                                                 if ( i === 1 ) {
557                                                         that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
558                                                 }
559                                         } else {
560                                                 if ( i === 0 ) {
561                                                         that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
562                                                 }
563                                                 if ( i === 1 ) {
564                                                         that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
565                                                 }
566                                         }
567                                 }
568                                 lastValPercent = valPercent;
569                         });
570                 } else {
571                         value = this.value();
572                         valueMin = this._valueMin();
573                         valueMax = this._valueMax();
574                         valPercent = ( valueMax !== valueMin ) ?
575                                         ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
576                                         0;
577                         _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
578                         this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
580                         if ( oRange === "min" && this.orientation === "horizontal" ) {
581                                 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
582                         }
583                         if ( oRange === "max" && this.orientation === "horizontal" ) {
584                                 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
585                         }
586                         if ( oRange === "min" && this.orientation === "vertical" ) {
587                                 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
588                         }
589                         if ( oRange === "max" && this.orientation === "vertical" ) {
590                                 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
591                         }
592                 }
593         },
595         _handleEvents: {
596                 keydown: function( event ) {
597                         var allowed, curVal, newVal, step,
598                                 index = $( event.target ).data( "ui-slider-handle-index" );
600                         switch ( event.keyCode ) {
601                                 case $.ui.keyCode.HOME:
602                                 case $.ui.keyCode.END:
603                                 case $.ui.keyCode.PAGE_UP:
604                                 case $.ui.keyCode.PAGE_DOWN:
605                                 case $.ui.keyCode.UP:
606                                 case $.ui.keyCode.RIGHT:
607                                 case $.ui.keyCode.DOWN:
608                                 case $.ui.keyCode.LEFT:
609                                         event.preventDefault();
610                                         if ( !this._keySliding ) {
611                                                 this._keySliding = true;
612                                                 $( event.target ).addClass( "ui-state-active" );
613                                                 allowed = this._start( event, index );
614                                                 if ( allowed === false ) {
615                                                         return;
616                                                 }
617                                         }
618                                         break;
619                         }
621                         step = this.options.step;
622                         if ( this.options.values && this.options.values.length ) {
623                                 curVal = newVal = this.values( index );
624                         } else {
625                                 curVal = newVal = this.value();
626                         }
628                         switch ( event.keyCode ) {
629                                 case $.ui.keyCode.HOME:
630                                         newVal = this._valueMin();
631                                         break;
632                                 case $.ui.keyCode.END:
633                                         newVal = this._valueMax();
634                                         break;
635                                 case $.ui.keyCode.PAGE_UP:
636                                         newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) );
637                                         break;
638                                 case $.ui.keyCode.PAGE_DOWN:
639                                         newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) );
640                                         break;
641                                 case $.ui.keyCode.UP:
642                                 case $.ui.keyCode.RIGHT:
643                                         if ( curVal === this._valueMax() ) {
644                                                 return;
645                                         }
646                                         newVal = this._trimAlignValue( curVal + step );
647                                         break;
648                                 case $.ui.keyCode.DOWN:
649                                 case $.ui.keyCode.LEFT:
650                                         if ( curVal === this._valueMin() ) {
651                                                 return;
652                                         }
653                                         newVal = this._trimAlignValue( curVal - step );
654                                         break;
655                         }
657                         this._slide( event, index, newVal );
658                 },
659                 click: function( event ) {
660                         event.preventDefault();
661                 },
662                 keyup: function( event ) {
663                         var index = $( event.target ).data( "ui-slider-handle-index" );
665                         if ( this._keySliding ) {
666                                 this._keySliding = false;
667                                 this._stop( event, index );
668                                 this._change( event, index );
669                                 $( event.target ).removeClass( "ui-state-active" );
670                         }
671                 }
672         }
676 }(jQuery));