Subversion Repositories SmartDukaan

Rev

Rev 162 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
162 naveen 1
/*
2
 * jQuery UI Slider 1.8.1
3
 *
4
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
5
 * Dual licensed under the MIT (MIT-LICENSE.txt)
6
 * and GPL (GPL-LICENSE.txt) licenses.
7
 *
8
 * http://docs.jquery.com/UI/Slider
9
 *
10
 * Depends:
11
 *	jquery.ui.core.js
12
 *	jquery.ui.mouse.js
13
 *	jquery.ui.widget.js
14
 */
15
 
16
(function( $ ) {
17
 
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;
21
 
22
$.widget( "ui.slider", $.ui.mouse, {
23
 
24
	widgetEventPrefix: "slide",
25
 
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
36
	},
37
 
38
	_create: function() {
39
		var self = this,
40
			o = this.options;
41
 
42
		this._keySliding = false;
43
		this._mouseSliding = false;
44
		this._animateOff = true;
45
		this._handleIndex = null;
46
		this._detectOrientation();
47
		this._mouseInit();
48
 
49
		this.element
50
			.addClass( "ui-slider" +
51
				" ui-slider-" + this.orientation +
52
				" ui-widget" +
53
				" ui-widget-content" +
54
				" ui-corner-all" );
55
 
56
		if ( o.disabled ) {
57
			this.element.addClass( "ui-slider-disabled ui-disabled" );
58
		}
59
 
60
		this.range = $([]);
61
 
62
		if ( o.range ) {
63
			if ( o.range === true ) {
64
				this.range = $( "<div></div>" );
65
				if ( !o.values ) {
66
					o.values = [ this._valueMin(), this._valueMin() ];
67
				}
68
				if ( o.values.length && o.values.length !== 2 ) {
69
					o.values = [ o.values[0], o.values[0] ];
70
				}
71
			} else {
72
				this.range = $( "<div></div>" );
73
			}
74
 
75
			this.range
76
				.appendTo( this.element )
77
				.addClass( "ui-slider-range" );
78
 
79
			if ( o.range === "min" || o.range === "max" ) {
80
				this.range.addClass( "ui-slider-range-" + o.range );
81
			}
82
 
83
			// note: this isn't the most fittingly semantic framework class for this element,
84
			// but worked best visually with a variety of themes
85
			this.range.addClass( "ui-widget-header" );
86
		}
87
 
88
		if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
89
			$( "<a href='#'></a>" )
90
				.appendTo( this.element )
91
				.addClass( "ui-slider-handle" );
92
		}
93
 
94
		if ( o.values && o.values.length ) {
95
			while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
96
				$( "<a href='#'></a>" )
97
					.appendTo( this.element )
98
					.addClass( "ui-slider-handle" );
99
			}
100
		}
101
 
102
		this.handles = $( ".ui-slider-handle", this.element )
103
			.addClass( "ui-state-default" +
104
				" ui-corner-all" );
105
 
106
		this.handle = this.handles.eq( 0 );
107
 
108
		this.handles.add( this.range ).filter( "a" )
109
			.click(function( event ) {
110
				event.preventDefault();
111
			})
112
			.hover(function() {
113
				if ( !o.disabled ) {
114
					$( this ).addClass( "ui-state-hover" );
115
				}
116
			}, function() {
117
				$( this ).removeClass( "ui-state-hover" );
118
			})
119
			.focus(function() {
120
				if ( !o.disabled ) {
121
					$( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
122
					$( this ).addClass( "ui-state-focus" );
123
				} else {
124
					$( this ).blur();
125
				}
126
			})
127
			.blur(function() {
128
				$( this ).removeClass( "ui-state-focus" );
129
			});
130
 
131
		this.handles.each(function( i ) {
132
			$( this ).data( "index.ui-slider-handle", i );
133
		});
134
 
135
		this.handles
136
			.keydown(function( event ) {
137
				var ret = true,
138
					index = $( this ).data( "index.ui-slider-handle" ),
139
					allowed,
140
					curVal,
141
					newVal,
142
					step;
143
 
144
				if ( self.options.disabled ) {
145
					return;
146
				}
147
 
148
				switch ( event.keyCode ) {
149
					case $.ui.keyCode.HOME:
150
					case $.ui.keyCode.END:
151
					case $.ui.keyCode.PAGE_UP:
152
					case $.ui.keyCode.PAGE_DOWN:
153
					case $.ui.keyCode.UP:
154
					case $.ui.keyCode.RIGHT:
155
					case $.ui.keyCode.DOWN:
156
					case $.ui.keyCode.LEFT:
157
						ret = false;
158
						if ( !self._keySliding ) {
159
							self._keySliding = true;
160
							$( this ).addClass( "ui-state-active" );
161
							allowed = self._start( event, index );
162
							if ( allowed === false ) {
163
								return;
164
							}
165
						}
166
						break;
167
				}
168
 
169
				step = self.options.step;
170
				if ( self.options.values && self.options.values.length ) {
171
					curVal = newVal = self.values( index );
172
				} else {
173
					curVal = newVal = self.value();
174
				}
175
 
176
				switch ( event.keyCode ) {
177
					case $.ui.keyCode.HOME:
178
						newVal = self._valueMin();
179
						break;
180
					case $.ui.keyCode.END:
181
						newVal = self._valueMax();
182
						break;
183
					case $.ui.keyCode.PAGE_UP:
184
						newVal = curVal + ( (self._valueMax() - self._valueMin()) / numPages );
185
						break;
186
					case $.ui.keyCode.PAGE_DOWN:
187
						newVal = curVal - ( (self._valueMax() - self._valueMin()) / numPages );
188
						break;
189
					case $.ui.keyCode.UP:
190
					case $.ui.keyCode.RIGHT:
191
						if ( curVal === self._valueMax() ) {
192
							return;
193
						}
194
						newVal = curVal + step;
195
						break;
196
					case $.ui.keyCode.DOWN:
197
					case $.ui.keyCode.LEFT:
198
						if ( curVal === self._valueMin() ) {
199
							return;
200
						}
201
						newVal = curVal - step;
202
						break;
203
				}
204
 
205
				self._slide( event, index, newVal );
206
 
207
				return ret;
208
 
209
			})
210
			.keyup(function( event ) {
211
				var index = $( this ).data( "index.ui-slider-handle" );
212
 
213
				if ( self._keySliding ) {
214
					self._keySliding = false;
215
					self._stop( event, index );
216
					self._change( event, index );
217
					$( this ).removeClass( "ui-state-active" );
218
				}
219
 
220
			});
221
 
222
		this._refreshValue();
223
 
224
		this._animateOff = false;
225
	},
226
 
227
	destroy: function() {
228
		this.handles.remove();
229
		this.range.remove();
230
 
231
		this.element
232
			.removeClass( "ui-slider" +
233
				" ui-slider-horizontal" +
234
				" ui-slider-vertical" +
235
				" ui-slider-disabled" +
236
				" ui-widget" +
237
				" ui-widget-content" +
238
				" ui-corner-all" )
239
			.removeData( "slider" )
240
			.unbind( ".slider" );
241
 
242
		this._mouseDestroy();
243
 
244
		return this;
245
	},
246
 
247
	_mouseCapture: function( event ) {
248
		var o = this.options,
249
			position,
250
			normValue,
251
			distance,
252
			closestHandle,
253
			self,
254
			index,
255
			allowed,
256
			offset,
257
			mouseOverHandle;
258
 
259
		if ( o.disabled ) {
260
			return false;
261
		}
262
 
263
		this.elementSize = {
264
			width: this.element.outerWidth(),
265
			height: this.element.outerHeight()
266
		};
267
		this.elementOffset = this.element.offset();
268
 
269
		position = { x: event.pageX, y: event.pageY };
270
		normValue = this._normValueFromMouse( position );
271
		distance = this._valueMax() - this._valueMin() + 1;
272
		self = this;
273
		this.handles.each(function( i ) {
274
			var thisDistance = Math.abs( normValue - self.values(i) );
275
			if ( distance > thisDistance ) {
276
				distance = thisDistance;
277
				closestHandle = $( this );
278
				index = i;
279
			}
280
		});
281
 
282
		// workaround for bug #3736 (if both handles of a range are at 0,
283
		// the first is always used as the one with least distance,
284
		// and moving it is obviously prevented by preventing negative ranges)
285
		if( o.range === true && this.values(1) === o.min ) {
286
			index += 1;
287
			closestHandle = $( this.handles[index] );
288
		}
289
 
290
		allowed = this._start( event, index );
291
		if ( allowed === false ) {
292
			return false;
293
		}
294
		this._mouseSliding = true;
295
 
296
		self._handleIndex = index;
297
 
298
		closestHandle
299
			.addClass( "ui-state-active" )
300
			.focus();
301
 
302
		offset = closestHandle.offset();
303
		mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
304
		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
305
			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
306
			top: event.pageY - offset.top -
307
				( closestHandle.height() / 2 ) -
308
				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
309
				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
310
				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
311
		};
312
 
313
		normValue = this._normValueFromMouse( position );
314
		this._slide( event, index, normValue );
315
		this._animateOff = true;
316
		return true;
317
	},
318
 
319
	_mouseStart: function( event ) {
320
		return true;
321
	},
322
 
323
	_mouseDrag: function( event ) {
324
		var position = { x: event.pageX, y: event.pageY },
325
			normValue = this._normValueFromMouse( position );
326
 
327
		this._slide( event, this._handleIndex, normValue );
328
 
329
		return false;
330
	},
331
 
332
	_mouseStop: function( event ) {
333
		this.handles.removeClass( "ui-state-active" );
334
		this._mouseSliding = false;
335
 
336
		this._stop( event, this._handleIndex );
337
		this._change( event, this._handleIndex );
338
 
339
		this._handleIndex = null;
340
		this._clickOffset = null;
341
		this._animateOff = false;
342
 
343
		return false;
344
	},
345
 
346
	_detectOrientation: function() {
347
		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
348
	},
349
 
350
	_normValueFromMouse: function( position ) {
351
		var pixelTotal,
352
			pixelMouse,
353
			percentMouse,
354
			valueTotal,
355
			valueMouse;
356
 
357
		if ( this.orientation === "horizontal" ) {
358
			pixelTotal = this.elementSize.width;
359
			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
360
		} else {
361
			pixelTotal = this.elementSize.height;
362
			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
363
		}
364
 
365
		percentMouse = ( pixelMouse / pixelTotal );
366
		if ( percentMouse > 1 ) {
367
			percentMouse = 1;
368
		}
369
		if ( percentMouse < 0 ) {
370
			percentMouse = 0;
371
		}
372
		if ( this.orientation === "vertical" ) {
373
			percentMouse = 1 - percentMouse;
374
		}
375
 
376
		valueTotal = this._valueMax() - this._valueMin();
377
		valueMouse = this._valueMin() + percentMouse * valueTotal;
378
 
379
		return this._trimAlignValue( valueMouse );
380
	},
381
 
382
	_start: function( event, index ) {
383
		var uiHash = {
384
			handle: this.handles[ index ],
385
			value: this.value()
386
		};
387
		if ( this.options.values && this.options.values.length ) {
388
			uiHash.value = this.values( index );
389
			uiHash.values = this.values();
390
		}
391
		return this._trigger( "start", event, uiHash );
392
	},
393
 
394
	_slide: function( event, index, newVal ) {
395
		var otherVal,
396
			newValues,
397
			allowed;
398
 
399
		if ( this.options.values && this.options.values.length ) {
400
			otherVal = this.values( index ? 0 : 1 );
401
 
402
			if ( ( this.options.values.length === 2 && this.options.range === true ) && 
403
					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
404
				) {
405
				newVal = otherVal;
406
			}
407
 
408
			if ( newVal !== this.values( index ) ) {
409
				newValues = this.values();
410
				newValues[ index ] = newVal;
411
				// A slide can be canceled by returning false from the slide callback
412
				allowed = this._trigger( "slide", event, {
413
					handle: this.handles[ index ],
414
					value: newVal,
415
					values: newValues
416
				} );
417
				otherVal = this.values( index ? 0 : 1 );
418
				if ( allowed !== false ) {
419
					this.values( index, newVal, true );
420
				}
421
			}
422
		} else {
423
			if ( newVal !== this.value() ) {
424
				// A slide can be canceled by returning false from the slide callback
425
				allowed = this._trigger( "slide", event, {
426
					handle: this.handles[ index ],
427
					value: newVal
428
				} );
429
				if ( allowed !== false ) {
430
					this.value( newVal );
431
				}
432
			}
433
		}
434
	},
435
 
436
	_stop: function( event, index ) {
437
		var uiHash = {
438
			handle: this.handles[ index ],
439
			value: this.value()
440
		};
441
		if ( this.options.values && this.options.values.length ) {
442
			uiHash.value = this.values( index );
443
			uiHash.values = this.values();
444
		}
445
 
446
		this._trigger( "stop", event, uiHash );
447
	},
448
 
449
	_change: function( event, index ) {
450
		if ( !this._keySliding && !this._mouseSliding ) {
451
			var uiHash = {
452
				handle: this.handles[ index ],
453
				value: this.value()
454
			};
455
			if ( this.options.values && this.options.values.length ) {
456
				uiHash.value = this.values( index );
457
				uiHash.values = this.values();
458
			}
459
 
460
			this._trigger( "change", event, uiHash );
461
		}
462
	},
463
 
464
	value: function( newValue ) {
465
		if ( arguments.length ) {
466
			this.options.value = this._trimAlignValue( newValue );
467
			this._refreshValue();
468
			this._change( null, 0 );
469
		}
470
 
471
		return this._value();
472
	},
473
 
474
	values: function( index, newValue ) {
475
		var vals,
476
			newValues,
477
			i;
478
 
479
		if ( arguments.length > 1 ) {
480
			this.options.values[ index ] = this._trimAlignValue( newValue );
481
			this._refreshValue();
482
			this._change( null, index );
483
		}
484
 
485
		if ( arguments.length ) {
486
			if ( $.isArray( arguments[ 0 ] ) ) {
487
				vals = this.options.values;
488
				newValues = arguments[ 0 ];
489
				for ( i = 0; i < vals.length; i += 1 ) {
490
					vals[ i ] = this._trimAlignValue( newValues[ i ] );
491
					this._change( null, i );
492
				}
493
				this._refreshValue();
494
			} else {
495
				if ( this.options.values && this.options.values.length ) {
496
					return this._values( index );
497
				} else {
498
					return this.value();
499
				}
500
			}
501
		} else {
502
			return this._values();
503
		}
504
	},
505
 
506
	_setOption: function( key, value ) {
507
		var i,
508
			valsLength = 0;
509
 
510
		if ( $.isArray( this.options.values ) ) {
511
			valsLength = this.options.values.length;
512
		}
513
 
514
		$.Widget.prototype._setOption.apply( this, arguments );
515
 
516
		switch ( key ) {
517
			case "disabled":
518
				if ( value ) {
519
					this.handles.filter( ".ui-state-focus" ).blur();
520
					this.handles.removeClass( "ui-state-hover" );
521
					this.handles.attr( "disabled", "disabled" );
522
					this.element.addClass( "ui-disabled" );
523
				} else {
524
					this.handles.removeAttr( "disabled" );
525
					this.element.removeClass( "ui-disabled" );
526
				}
527
				break;
528
			case "orientation":
529
				this._detectOrientation();
530
				this.element
531
					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
532
					.addClass( "ui-slider-" + this.orientation );
533
				this._refreshValue();
534
				break;
535
			case "value":
536
				this._animateOff = true;
537
				this._refreshValue();
538
				this._change( null, 0 );
539
				this._animateOff = false;
540
				break;
541
			case "values":
542
				this._animateOff = true;
543
				this._refreshValue();
544
				for ( i = 0; i < valsLength; i += 1 ) {
545
					this._change( null, i );
546
				}
547
				this._animateOff = false;
548
				break;
549
		}
550
	},
551
 
552
	//internal value getter
553
	// _value() returns value trimmed by min and max, aligned by step
554
	_value: function() {
555
		var val = this.options.value;
556
		val = this._trimAlignValue( val );
557
 
558
		return val;
559
	},
560
 
561
	//internal values getter
562
	// _values() returns array of values trimmed by min and max, aligned by step
563
	// _values( index ) returns single value trimmed by min and max, aligned by step
564
	_values: function( index ) {
565
		var val,
566
			vals,
567
			i;
568
 
569
		if ( arguments.length ) {
570
			val = this.options.values[ index ];
571
			val = this._trimAlignValue( val );
572
 
573
			return val;
574
		} else {
575
			// .slice() creates a copy of the array
576
			// this copy gets trimmed by min and max and then returned
577
			vals = this.options.values.slice();
578
			for ( i = 0; i < vals.length; i+= 1) {
579
				vals[ i ] = this._trimAlignValue( vals[ i ] );
580
			}
581
 
582
			return vals;
583
		}
584
	},
585
 
586
	// returns the step-aligned value that val is closest to, between (inclusive) min and max
587
	_trimAlignValue: function( val ) {
588
		if ( val < this._valueMin() ) {
589
			return this._valueMin();
590
		}
591
		if ( val > this._valueMax() ) {
592
			return this._valueMax();
593
		}
594
		var step = this.options.step,
595
			valModStep = val % step,
596
			alignValue = val - valModStep;
597
 
598
		if ( valModStep >= ( step / 2 ) ) {
599
			alignValue += step;
600
		}
601
 
602
		// Since JavaScript has problems with large floats, round
603
		// the final value to 5 digits after the decimal point (see #4124)
604
		return parseFloat( alignValue.toFixed(5) );
605
	},
606
 
607
	_valueMin: function() {
608
		return this.options.min;
609
	},
610
 
611
	_valueMax: function() {
612
		return this.options.max;
613
	},
614
 
615
	_refreshValue: function() {
616
		var oRange = this.options.range,
617
			o = this.options,
618
			self = this,
619
			animate = ( !this._animateOff ) ? o.animate : false,
620
			valPercent,
621
			_set = {},
622
			lastValPercent,
623
			value,
624
			valueMin,
625
			valueMax;
626
 
627
		if ( this.options.values && this.options.values.length ) {
628
			this.handles.each(function( i, j ) {
629
				valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
630
				_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
631
				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
632
				if ( self.options.range === true ) {
633
					if ( self.orientation === "horizontal" ) {
634
						if ( i === 0 ) {
635
							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
636
						}
637
						if ( i === 1 ) {
638
							self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
639
						}
640
					} else {
641
						if ( i === 0 ) {
642
							self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
643
						}
644
						if ( i === 1 ) {
645
							self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
646
						}
647
					}
648
				}
649
				lastValPercent = valPercent;
650
			});
651
		} else {
652
			value = this.value();
653
			valueMin = this._valueMin();
654
			valueMax = this._valueMax();
655
			valPercent = ( valueMax !== valueMin ) ?
656
					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
657
					0;
658
			_set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
659
			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
660
 
661
			if ( oRange === "min" && this.orientation === "horizontal" ) {
662
				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
663
			}
664
			if ( oRange === "max" && this.orientation === "horizontal" ) {
665
				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
666
			}
667
			if ( oRange === "min" && this.orientation === "vertical" ) {
668
				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
669
			}
670
			if ( oRange === "max" && this.orientation === "vertical" ) {
671
				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
672
			}
673
		}
674
	}
675
 
676
});
677
 
678
$.extend( $.ui.slider, {
679
	version: "1.8.1"
680
});
681
 
682
}(jQuery));