PageSourceSearch

https://macgirvin.com/library/jRange/jquery.range.js?_v=5cad96cb434cf98424be2f121ca1b84f

js macgirvin.com collected 2026-10-02 07:10:40 UTC 10,900 bytes, 335 lines download raw bytes

vendor: 10,900 bytes, lines 1-335
1/*jshint multistr:true, curly: false */
2/*global jQuery:false, define: false */
3/**
4 * jRange - Awesome range control
5 *
6 * Written by
7 * ----------
8 * Nitin Hayaran ([email protected])
9 *
10 * Licensed under the MIT (MIT-LICENSE.txt).
11 *
12 * @author Nitin Hayaran
13 * @version 0.1-RELEASE
14 *
15 * Dependencies
16 * ------------
17 * jQuery (http://jquery.com)
18 *
19 **/
20;
21(function($, window, document, undefined) {
22	'use strict';
23
24	var jRange = function() {
25		return this.init.apply(this, arguments);
26	};
27	jRange.prototype = {
28		defaults: {
29			onstatechange: function() {},
30			isRange: false,
31			showLabels: true,
32			showScale: true,
33			step: 1,
34			format: '%s',
35			theme: 'theme-green',
36			width: 300,
37			disable: false
38		},
39		template: '<div class="slider-container">\
40			<div class="back-bar">\
41                <div class="selected-bar"></div>\
42                <div class="pointer low"></div><div class="pointer-label">123456</div>\
43                <div class="pointer high"></div><div class="pointer-label">456789</div>\
44                <div class="clickable-dummy"></div>\
45            </div>\
46            <div class="scale"></div>\
47		</div>',
48		init: function(node, options) {
49			this.options       = $.extend({}, this.defaults, options);
50			this.inputNode     = $(node);
51			this.options.value = this.inputNode.val() || (this.options.isRange ? this.options.from + ',' + this.options.from : this.options.from);
52			this.domNode       = $(this.template);
53			this.domNode.addClass(this.options.theme);
54			this.inputNode.after(this.domNode);
55			this.domNode.on('change', this.onChange);
56			this.pointers      = $('.pointer', this.domNode);
57			this.lowPointer    = this.pointers.first();
58			this.highPointer   = this.pointers.last();
59			this.labels        = $('.pointer-label', this.domNode);
60			this.lowLabel      = this.labels.first();
61			this.highLabel     = this.labels.last();
62			this.scale         = $('.scale', this.domNode);
63			this.bar           = $('.selected-bar', this.domNode);
64			this.clickableBar  = this.domNode.find('.clickable-dummy');
65			this.interval      = this.options.to - this.options.from;
66			this.render();
67		},
68		render: function() {
69			// Check if inputNode is visible, and have some width, so that we can set slider width accordingly.
70			if (this.inputNode.width() === 0 && !this.options.width) {
71				console.log('jRange : no width found, returning');
72				return;
73			} else {
74				this.domNode.width(this.options.width || this.inputNode.width());
75				this.inputNode.hide();
76			}
77
78			if (this.isSingle()) {
79				this.lowPointer.hide();
80				this.lowLabel.hide();
81			}
82			if (!this.options.showLabels) {
83				this.labels.hide();
84			}
85			this.attachEvents();
86			if (this.options.showScale) {
87				this.renderScale();
88			}
89			this.setValue(this.options.value);
90		},
91		isSingle: function() {
92			if (typeof(this.options.value) === 'number') {
93				return true;
94			}
95			return (this.options.value.indexOf(',') !== -1 || this.options.isRange) ?
96				false : true;
97		},
98		attachEvents: function() {
99			this.clickableBar.click($.proxy(this.barClicked, this));
100			this.pointers.on('mousedown touchstart', $.proxy(this.onDragStart, this));
101			this.pointers.bind('dragstart', function(event) {
102				event.preventDefault();
103			});
104		},
105		onDragStart: function(e) {
106			if ( this.options.disable || (e.type === 'mousedown' && e.which !== 1)) {
107				return;
108			}
109			e.stopPropagation();
110			e.preventDefault();
111			var pointer = $(e.target);
112			this.pointers.removeClass('last-active');
113			pointer.addClass('focused last-active');
114			this[(pointer.hasClass('low') ? 'low' : 'high') + 'Label'].addClass('focused');
115			$(document).on('mousemove.slider touchmove.slider', $.proxy(this.onDrag, this, pointer));
116			$(document).on('mouseup.slider touchend.slider touchcancel.slider', $.proxy(this.onDragEnd, this));
117		},
118		onDrag: function(pointer, e) {
119			e.stopPropagation();
120			e.preventDefault();
121
122			if (e.originalEvent.touches && e.originalEvent.touches.length) {
123				e = e.originalEvent.touches[0];
124			} else if (e.originalEvent.changedTouches && e.originalEvent.changedTouches.length) {
125				e = e.originalEvent.changedTouches[0];
126			}
127
128			var position = e.clientX - this.domNode.offset().left;
129			this.domNode.trigger('change', [this, pointer, position]);
130		},
131		onDragEnd: function(e) {
132			this.pointers.removeClass('focused');
133			this.labels.removeClass('focused');
134			$(document).off('.slider');
135		},
136		barClicked: function(e) {
137			if(this.options.disable) return;
138			var x = e.pageX - this.clickableBar.offset().left;
139			if (this.isSingle())
140				this.setPosition(this.pointers.last(), x, true, true);
141			else {
142				var pointer = Math.abs(parseInt(this.pointers.first().css('left'), 10) - x + this.pointers.first().width() / 2) < Math.abs(parseInt(this.pointers.last().css('left'), 10) - x + this.pointers.first().width() / 2) ?
143					this.pointers.first() : this.pointers.last();
144				this.setPosition(pointer, x, true, true);
145			}
146		},
147		onChange: function(e, self, pointer, position) {
148			var min, max;
149			if (self.isSingle()) {
150				min = 0;
151				max = self.domNode.width();
152			} else {
153				min = pointer.hasClass('high') ? self.lowPointer.position().left + self.lowPointer.width() / 2 : 0;
154				max = pointer.hasClass('low') ? self.highPointer.position().left + self.highPointer.width() / 2 : self.domNode.width();
155			}
156			var value = Math.min(Math.max(position, min), max);
157			self.setPosition(pointer, value, true);
158		},
159		setPosition: function(pointer, position, isPx, animate) {
160			var leftPos,
161				lowPos = this.lowPointer.position().left,
162				highPos = this.highPointer.position().left,
163				circleWidth = this.highPointer.width() / 2;
164			if (!isPx) {
165				position = this.prcToPx(position);
166			}
167			if (pointer[0] === this.highPointer[0]) {
168				highPos = Math.round(position - circleWidth);
169			} else {
170				lowPos = Math.round(position - circleWidth);
171			}
172			pointer[animate ? 'animate' : 'css']({
173				'left': Math.round(position - circleWidth)
174			});
175			if (this.isSingle()) {
176				leftPos = 0;
177			} else {
178				leftPos = lowPos + circleWidth;
179			}
180			this.bar[animate ? 'animate' : 'css']({
181				'width': Math.round(highPos + circleWidth - leftPos),
182				'left': leftPos
183			});
184			this.showPointerValue(pointer, position, animate);
185			this.isReadonly();
186		},
187		// will be called from outside
188		setValue: function(value) {
189			var values = value.toString().split(',');
190			this.options.value = value;
191			var prc = this.valuesToPrc(values.length === 2 ? values : [0, values[0]]);
192			if (this.isSingle()) {
193				this.setPosition(this.highPointer, prc[1]);
194			} else {
195				this.setPosition(this.lowPointer, prc[0]);
196				this.setPosition(this.highPointer, prc[1]);
197			}
198		},
199		renderScale: function() {
200			var s = this.options.scale || [this.options.from, this.options.to];
201			var prc = Math.round((100 / (s.length - 1)) * 10) / 10;
202			var str = '';
203			for (var i = 0; i < s.length; i++) {
204				str += '<span style="left: ' + i * prc + '%">' + (s[i] != '|' ? '<ins>' + s[i] + '</ins>' : '') + '</span>';
205			}
206			this.scale.html(str);
207
208			$('ins', this.scale).each(function() {
209				$(this).css({
210					marginLeft: -$(this).outerWidth() / 2
211				});
212			});
213		},
214		getBarWidth: function() {
215			var values = this.options.value.split(',');
216			if (values.length > 1) {
217				return parseInt(values[1], 10) - parseInt(values[0], 10);
218			} else {
219				return parseInt(values[0], 10);
220			}
221		},
222		showPointerValue: function(pointer, position, animate) {
223			var label = $('.pointer-label', this.domNode)[pointer.hasClass('low') ? 'first' : 'last']();
224			var text;
225			var value = this.positionToValue(position);
226			if ($.isFunction(this.options.format)) {
227				var type = this.isSingle() ? undefined : (pointer.hasClass('low') ? 'low' : 'high');
228				text = this.options.format(value, type);
229			} else {
230				text = this.options.format.replace('%s', value);
231			}
232
233			var width = label.html(text).width(),
234				left = position - width / 2;
235			left = Math.min(Math.max(left, 0), this.options.width - width);
236			label[animate ? 'animate' : 'css']({
237				left: left
238			});
239			this.setInputValue(pointer, value);
240		},
241		valuesToPrc: function(values) {
242			var lowPrc = ((values[0] - this.options.from) * 100 / this.interval),
243				highPrc = ((values[1] - this.options.from) * 100 / this.interval);
244			return [lowPrc, highPrc];
245		},
246		prcToPx: function(prc) {
247			return (this.domNode.width() * prc) / 100;
248		},
249		positionToValue: function(pos) {
250			var value = (pos / this.domNode.width()) * this.interval;
251			value = value + this.options.from;
252			return Math.round(value / this.options.step) * this.options.step;
253		},
254		setInputValue: function(pointer, v) {
255			// if(!isChanged) return;
256			if (this.isSingle()) {
257				this.options.value = v.toString();
258			} else {
259				var values = this.options.value.split(',');
260				if (pointer.hasClass('low')) {
261					this.options.value = v + ',' + values[1];
262				} else {
263					this.options.value = values[0] + ',' + v;
264				}
265			}
266			if (this.inputNode.val() !== this.options.value) {
267				this.inputNode.val(this.options.value);
268				this.options.onstatechange.call(this, this.options.value);
269			}
270		},
271		getValue: function() {
272			return this.options.value;
273		},
274		isReadonly: function(){
275			this.domNode.toggleClass('slider-readonly', this.options.disable);
276		},
277		disable: function(){
278			this.options.disable = true;
279			this.isReadonly();
280		},
281		enable: function(){
282			this.options.disable = false;
283			this.isReadonly();
284		},
285		toggleDisable: function(){
286			this.options.disable = !this.options.disable;
287			this.isReadonly();
288		}
289	};
290
291	/*$.jRange = function (node, options) {
292		var jNode = $(node);
293		if(!jNode.data('jrange')){
294			jNode.data('jrange', new jRange(node, options));
295		}
296		return jNode.data('jrange');
297	};
298
299	$.fn.jRange = function (options) {
300		return this.each(function(){
301			$.jRange(this, options);
302		});
303	};*/
304
305	var pluginName = 'jRange';
306	// A really lightweight plugin wrapper around the constructor,
307	// preventing against multiple instantiations
308	$.fn[pluginName] = function(option) {
309		var args = arguments,
310			result;
311
312		this.each(function() {
313			var $this = $(this),
314				data = $.data(this, 'plugin_' + pluginName),
315				options = typeof option === 'object' && option;
316			if (!data) {
317				$this.data('plugin_' + pluginName, (data = new jRange(this, options)));
318				$(window).resize(function() {
319					data.setValue(data.getValue());
320				}); // Update slider position when window is resized to keep it in sync with scale
321			}
322			// if first argument is a string, call silimarly named function
323			// this gives flexibility to call functions of the plugin e.g.
324			//   - $('.dial').plugin('destroy');
325			//   - $('.dial').plugin('render', $('.new-child'));
326			if (typeof option === 'string') {
327				result = data[option].apply(data, Array.prototype.slice.call(args, 1));
328			}
329		});
330
331		// To enable plugin returns values
332		return result || this;
333	};
334
335})(jQuery, window, document);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.