run:R W Run
DIR
2026-04-08 19:41:33
R W Run
DIR
2026-04-08 19:29:28
R W Run
38.7 KB
2026-04-08 19:26:24
R W Run
1.49 KB
2026-04-08 19:26:23
R W Run
4.72 KB
2026-04-08 19:26:25
R W Run
3.02 KB
2026-04-08 19:26:25
R W Run
10.78 KB
2026-04-08 19:26:25
R W Run
7.35 KB
2026-04-08 19:26:23
R W Run
11.6 KB
2026-04-08 19:26:22
R W Run
10.43 KB
2026-04-08 19:26:24
R W Run
26.35 KB
2026-04-08 19:26:25
R W Run
12.68 KB
2026-04-08 19:26:24
R W Run
1.94 KB
2026-04-08 19:26:24
R W Run
7.14 KB
2026-04-08 19:26:24
R W Run
1.16 KB
2026-04-08 19:26:24
R W Run
4.77 KB
2026-04-08 19:26:22
R W Run
3.56 KB
2026-04-08 19:26:24
R W Run
5.43 KB
2026-04-08 19:26:23
R W Run
4.04 KB
2026-04-08 19:26:23
R W Run
11.09 KB
2026-04-08 19:26:23
R W Run
10.93 KB
2026-04-08 19:26:25
R W Run
8.78 KB
2026-04-08 19:26:23
R W Run
3.09 KB
2026-04-08 19:26:22
R W Run
38.75 KB
2026-04-08 19:26:24
R W Run
4.62 KB
2026-04-08 19:26:24
R W Run
1.9 KB
2026-04-08 19:26:24
R W Run
23.06 KB
2026-04-08 19:26:23
R W Run
6.79 KB
2026-04-08 19:26:22
R W Run
72.3 KB
2026-04-08 19:26:24
R W Run
42 By
2026-04-08 19:26:23
R W Run
69.61 KB
2026-04-08 19:26:23
R W Run
35.35 KB
2026-04-08 19:26:22
R W Run
425.48 KB
2026-04-08 19:26:25
R W Run
77.13 KB
2026-04-08 19:26:24
R W Run
1.42 KB
2026-04-08 19:26:22
R W Run
20.26 KB
2026-04-08 19:26:25
R W Run
94.89 KB
2026-04-08 19:26:24
R W Run
22.42 KB
2026-04-08 19:26:24
R W Run
18.09 KB
2026-04-08 19:26:23
R W Run
4.6 KB
2026-04-08 19:26:23
R W Run
3.56 KB
2026-04-08 19:26:24
R W Run
16.76 KB
2026-04-08 19:26:24
R W Run
5.18 KB
2026-04-08 19:26:23
R W Run
31.03 KB
2026-04-08 19:26:25
R W Run
96.29 KB
2026-04-08 19:26:25
R W Run
41.33 KB
2026-04-08 19:26:22
R W Run
2.76 KB
2026-04-08 19:26:25
R W Run
error_log
📄ion.rangeSlider.js
1// Ion.RangeSlider
2// version 2.0.13 Build: 335
3// © Denis Ineshin, 2015
4// https://github.com/IonDen
5//
6// Project page: http://ionden.com/a/plugins/ion.rangeSlider/en.html
7// GitHub page: https://github.com/IonDen/ion.rangeSlider
8//
9// Released under MIT licence:
10// http://ionden.com/a/plugins/licence-en.html
11// =====================================================================================================================
12
13;(function ($, document, window, navigator, undefined) {
14 "use strict";
15
16 // =================================================================================================================
17 // Service
18
19 var plugin_count = 0;
20
21 // IE8 fix
22 var is_old_ie = (function () {
23 var n = navigator.userAgent,
24 r = /msie\s\d+/i,
25 v;
26 if (n.search(r) > 0) {
27 v = r.exec(n).toString();
28 v = v.split(" ")[1];
29 if (v < 9) {
30 $("html").addClass("lt-ie9");
31 return true;
32 }
33 }
34 return false;
35 } ());
36 if (!Function.prototype.bind) {
37 Function.prototype.bind = function bind(that) {
38
39 var target = this;
40 var slice = [].slice;
41
42 if (typeof target != "function") {
43 throw new TypeError();
44 }
45
46 var args = slice.call(arguments, 1),
47 bound = function () {
48
49 if (this instanceof bound) {
50
51 var F = function(){};
52 F.prototype = target.prototype;
53 var self = new F();
54
55 var result = target.apply(
56 self,
57 args.concat(slice.call(arguments))
58 );
59 if (Object(result) === result) {
60 return result;
61 }
62 return self;
63
64 } else {
65
66 return target.apply(
67 that,
68 args.concat(slice.call(arguments))
69 );
70
71 }
72
73 };
74
75 return bound;
76 };
77 }
78 if (!Array.prototype.indexOf) {
79 Array.prototype.indexOf = function(searchElement, fromIndex) {
80 var k;
81 if (this == null) {
82 throw new TypeError('"this" is null or not defined');
83 }
84 var O = Object(this);
85 var len = O.length >>> 0;
86 if (len === 0) {
87 return -1;
88 }
89 var n = +fromIndex || 0;
90 if (Math.abs(n) === Infinity) {
91 n = 0;
92 }
93 if (n >= len) {
94 return -1;
95 }
96 k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
97 while (k < len) {
98 if (k in O && O[k] === searchElement) {
99 return k;
100 }
101 k++;
102 }
103 return -1;
104 };
105 }
106
107
108
109 // =================================================================================================================
110 // Template
111
112 var base_html =
113 '<span class="irs">' +
114 '<span class="irs-line" tabindex="-1"><span class="irs-line-left"></span><span class="irs-line-mid"></span><span class="irs-line-right"></span></span>' +
115 '<span class="irs-min">0</span><span class="irs-max">1</span>' +
116 '<span class="irs-from">0</span><span class="irs-to">0</span><span class="irs-single">0</span>' +
117 '</span>' +
118 '<span class="irs-grid"></span>' +
119 '<span class="irs-bar"></span>';
120
121 var single_html =
122 '<span class="irs-bar-edge"></span>' +
123 '<span class="irs-shadow shadow-single"></span>' +
124 '<span class="irs-slider single"></span>';
125
126 var double_html =
127 '<span class="irs-shadow shadow-from"></span>' +
128 '<span class="irs-shadow shadow-to"></span>' +
129 '<span class="irs-slider from"></span>' +
130 '<span class="irs-slider to"></span>';
131
132 var disable_html =
133 '<span class="irs-disable-mask"></span>';
134
135
136
137 // =================================================================================================================
138 // Core
139
140 /**
141 * Main plugin constructor
142 *
143 * @param input {object}
144 * @param options {object}
145 * @param plugin_count {number}
146 * @constructor
147 */
148 var IonRangeSlider = function (input, options, plugin_count) {
149 this.VERSION = "2.0.13";
150 this.input = input;
151 this.plugin_count = plugin_count;
152 this.current_plugin = 0;
153 this.calc_count = 0;
154 this.update_tm = 0;
155 this.old_from = 0;
156 this.old_to = 0;
157 this.raf_id = null;
158 this.dragging = false;
159 this.force_redraw = false;
160 this.is_key = false;
161 this.is_update = false;
162 this.is_start = true;
163 this.is_finish = false;
164 this.is_active = false;
165 this.is_resize = false;
166 this.is_click = false;
167
168 this.$cache = {
169 win: $(window),
170 body: $(document.body),
171 input: $(input),
172 cont: null,
173 rs: null,
174 min: null,
175 max: null,
176 from: null,
177 to: null,
178 single: null,
179 bar: null,
180 line: null,
181 s_single: null,
182 s_from: null,
183 s_to: null,
184 shad_single: null,
185 shad_from: null,
186 shad_to: null,
187 edge: null,
188 grid: null,
189 grid_labels: []
190 };
191
192 // get config data attributes
193 var $inp = this.$cache.input;
194 var data = {
195 type: $inp.data("type"),
196
197 min: $inp.data("min"),
198 max: $inp.data("max"),
199 from: $inp.data("from"),
200 to: $inp.data("to"),
201 step: $inp.data("step"),
202
203 min_interval: $inp.data("minInterval"),
204 max_interval: $inp.data("maxInterval"),
205 drag_interval: $inp.data("dragInterval"),
206
207 values: $inp.data("values"),
208
209 from_fixed: $inp.data("fromFixed"),
210 from_min: $inp.data("fromMin"),
211 from_max: $inp.data("fromMax"),
212 from_shadow: $inp.data("fromShadow"),
213
214 to_fixed: $inp.data("toFixed"),
215 to_min: $inp.data("toMin"),
216 to_max: $inp.data("toMax"),
217 to_shadow: $inp.data("toShadow"),
218
219 prettify_enabled: $inp.data("prettifyEnabled"),
220 prettify_separator: $inp.data("prettifySeparator"),
221
222 force_edges: $inp.data("forceEdges"),
223
224 keyboard: $inp.data("keyboard"),
225 keyboard_step: $inp.data("keyboardStep"),
226
227 grid: $inp.data("grid"),
228 grid_margin: $inp.data("gridMargin"),
229 grid_num: $inp.data("gridNum"),
230 grid_snap: $inp.data("gridSnap"),
231
232 hide_min_max: $inp.data("hideMinMax"),
233 hide_from_to: $inp.data("hideFromTo"),
234
235 prefix: $inp.data("prefix"),
236 postfix: $inp.data("postfix"),
237 max_postfix: $inp.data("maxPostfix"),
238 decorate_both: $inp.data("decorateBoth"),
239 values_separator: $inp.data("valuesSeparator"),
240
241 disable: $inp.data("disable")
242 };
243 data.values = data.values && data.values.split(",");
244
245 // get from and to out of input
246 var val = $inp.prop("value");
247 if (val) {
248 val = val.split(";");
249
250 if (val[0] && val[0] == +val[0]) {
251 val[0] = +val[0];
252 }
253 if (val[1] && val[1] == +val[1]) {
254 val[1] = +val[1];
255 }
256
257 if (options && options.values && options.values.length) {
258 data.from = val[0] && options.values.indexOf(val[0]);
259 data.to = val[1] && options.values.indexOf(val[1]);
260 } else {
261 data.from = val[0] && +val[0];
262 data.to = val[1] && +val[1];
263 }
264 }
265
266 // JS config has a priority
267 options = $.extend(data, options);
268
269 // get config from options
270 this.options = $.extend({
271 type: "single",
272
273 min: 10,
274 max: 100,
275 from: null,
276 to: null,
277 step: 1,
278
279 min_interval: 0,
280 max_interval: 0,
281 drag_interval: false,
282
283 values: [],
284 p_values: [],
285
286 from_fixed: false,
287 from_min: null,
288 from_max: null,
289 from_shadow: false,
290
291 to_fixed: false,
292 to_min: null,
293 to_max: null,
294 to_shadow: false,
295
296 prettify_enabled: true,
297 prettify_separator: " ",
298 prettify: null,
299
300 force_edges: false,
301
302 keyboard: false,
303 keyboard_step: 5,
304
305 grid: false,
306 grid_margin: true,
307 grid_num: 4,
308 grid_snap: false,
309
310 hide_min_max: false,
311 hide_from_to: false,
312
313 prefix: "",
314 postfix: "",
315 max_postfix: "",
316 decorate_both: true,
317 values_separator: " — ",
318
319 disable: false,
320
321 onStart: null,
322 onChange: null,
323 onFinish: null,
324 onUpdate: null
325 }, options);
326
327 this.validate();
328
329 this.result = {
330 input: this.$cache.input,
331 slider: null,
332
333 min: this.options.min,
334 max: this.options.max,
335
336 from: this.options.from,
337 from_percent: 0,
338 from_value: null,
339
340 to: this.options.to,
341 to_percent: 0,
342 to_value: null
343 };
344
345 this.coords = {
346 // left
347 x_gap: 0,
348 x_pointer: 0,
349
350 // width
351 w_rs: 0,
352 w_rs_old: 0,
353 w_handle: 0,
354
355 // percents
356 p_gap: 0,
357 p_gap_left: 0,
358 p_gap_right: 0,
359 p_step: 0,
360 p_pointer: 0,
361 p_handle: 0,
362 p_single: 0,
363 p_single_real: 0,
364 p_from: 0,
365 p_from_real: 0,
366 p_to: 0,
367 p_to_real: 0,
368 p_bar_x: 0,
369 p_bar_w: 0,
370
371 // grid
372 grid_gap: 0,
373 big_num: 0,
374 big: [],
375 big_w: [],
376 big_p: [],
377 big_x: []
378 };
379
380 this.labels = {
381 // width
382 w_min: 0,
383 w_max: 0,
384 w_from: 0,
385 w_to: 0,
386 w_single: 0,
387
388 // percents
389 p_min: 0,
390 p_max: 0,
391 p_from: 0,
392 p_from_left: 0,
393 p_to: 0,
394 p_to_left: 0,
395 p_single: 0,
396 p_single_left: 0
397 };
398
399 this.init();
400 };
401
402 IonRangeSlider.prototype = {
403 init: function (is_update) {
404 this.coords.p_step = this.options.step / ((this.options.max - this.options.min) / 100);
405 this.target = "base";
406
407 this.toggleInput();
408 this.append();
409 this.setMinMax();
410
411 if (is_update) {
412 this.force_redraw = true;
413 this.calc(true);
414
415 // callbacks called
416 this.callOnUpdate();
417 } else {
418 this.force_redraw = true;
419 this.calc(true);
420
421 // callbacks called
422 this.callOnStart();
423 }
424
425 this.updateScene();
426 },
427
428 append: function () {
429 var container_html = '<span class="irs js-irs-' + this.plugin_count + '"></span>';
430 this.$cache.input.before(container_html);
431 this.$cache.input.prop("readonly", true);
432 this.$cache.cont = this.$cache.input.prev();
433 this.result.slider = this.$cache.cont;
434
435 this.$cache.cont.html(base_html);
436 this.$cache.rs = this.$cache.cont.find(".irs");
437 this.$cache.min = this.$cache.cont.find(".irs-min");
438 this.$cache.max = this.$cache.cont.find(".irs-max");
439 this.$cache.from = this.$cache.cont.find(".irs-from");
440 this.$cache.to = this.$cache.cont.find(".irs-to");
441 this.$cache.single = this.$cache.cont.find(".irs-single");
442 this.$cache.bar = this.$cache.cont.find(".irs-bar");
443 this.$cache.line = this.$cache.cont.find(".irs-line");
444 this.$cache.grid = this.$cache.cont.find(".irs-grid");
445
446 if (this.options.type === "single") {
447 this.$cache.cont.append(single_html);
448 this.$cache.edge = this.$cache.cont.find(".irs-bar-edge");
449 this.$cache.s_single = this.$cache.cont.find(".single");
450 this.$cache.from[0].style.visibility = "hidden";
451 this.$cache.to[0].style.visibility = "hidden";
452 this.$cache.shad_single = this.$cache.cont.find(".shadow-single");
453 } else {
454 this.$cache.cont.append(double_html);
455 this.$cache.s_from = this.$cache.cont.find(".from");
456 this.$cache.s_to = this.$cache.cont.find(".to");
457 this.$cache.shad_from = this.$cache.cont.find(".shadow-from");
458 this.$cache.shad_to = this.$cache.cont.find(".shadow-to");
459
460 this.setTopHandler();
461 }
462
463 if (this.options.hide_from_to) {
464 this.$cache.from[0].style.display = "none";
465 this.$cache.to[0].style.display = "none";
466 this.$cache.single[0].style.display = "none";
467 }
468
469 this.appendGrid();
470
471 if (this.options.disable) {
472 this.appendDisableMask();
473 this.$cache.input[0].disabled = true;
474 } else {
475 this.$cache.cont.removeClass("irs-disabled");
476 this.$cache.input[0].disabled = false;
477 this.bindEvents();
478 }
479 },
480
481 setTopHandler: function () {
482 var min = this.options.min,
483 max = this.options.max,
484 from = this.options.from,
485 to = this.options.to;
486
487 if (from > min && to === max) {
488 this.$cache.s_from.addClass("type_last");
489 } else if (to < max) {
490 this.$cache.s_to.addClass("type_last");
491 }
492 },
493
494 appendDisableMask: function () {
495 this.$cache.cont.append(disable_html);
496 this.$cache.cont.addClass("irs-disabled");
497 },
498
499 remove: function () {
500 this.$cache.cont.remove();
501 this.$cache.cont = null;
502
503 this.$cache.line.off("keydown.irs_" + this.plugin_count);
504
505 this.$cache.body.off("touchmove.irs_" + this.plugin_count);
506 this.$cache.body.off("mousemove.irs_" + this.plugin_count);
507
508 this.$cache.win.off("touchend.irs_" + this.plugin_count);
509 this.$cache.win.off("mouseup.irs_" + this.plugin_count);
510
511 if (is_old_ie) {
512 this.$cache.body.off("mouseup.irs_" + this.plugin_count);
513 this.$cache.body.off("mouseleave.irs_" + this.plugin_count);
514 }
515
516 this.$cache.grid_labels = [];
517 this.coords.big = [];
518 this.coords.big_w = [];
519 this.coords.big_p = [];
520 this.coords.big_x = [];
521
522 cancelAnimationFrame(this.raf_id);
523 },
524
525 bindEvents: function () {
526 this.$cache.body.on("touchmove.irs_" + this.plugin_count, this.pointerMove.bind(this));
527 this.$cache.body.on("mousemove.irs_" + this.plugin_count, this.pointerMove.bind(this));
528
529 this.$cache.win.on("touchend.irs_" + this.plugin_count, this.pointerUp.bind(this));
530 this.$cache.win.on("mouseup.irs_" + this.plugin_count, this.pointerUp.bind(this));
531
532 this.$cache.line.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
533 this.$cache.line.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
534
535 if (this.options.drag_interval && this.options.type === "double") {
536 this.$cache.bar.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "both"));
537 this.$cache.bar.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "both"));
538 } else {
539 this.$cache.bar.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
540 this.$cache.bar.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
541 }
542
543 if (this.options.type === "single") {
544 this.$cache.single.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
545 this.$cache.s_single.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
546 this.$cache.shad_single.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
547
548 this.$cache.single.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
549 this.$cache.s_single.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
550 this.$cache.edge.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
551 this.$cache.shad_single.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
552 } else {
553 this.$cache.single.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
554 this.$cache.single.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
555
556 this.$cache.from.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
557 this.$cache.s_from.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
558 this.$cache.to.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
559 this.$cache.s_to.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
560 this.$cache.shad_from.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
561 this.$cache.shad_to.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
562
563 this.$cache.from.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
564 this.$cache.s_from.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
565 this.$cache.to.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
566 this.$cache.s_to.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
567 this.$cache.shad_from.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
568 this.$cache.shad_to.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
569 }
570
571 if (this.options.keyboard) {
572 this.$cache.line.on("keydown.irs_" + this.plugin_count, this.key.bind(this, "keyboard"));
573 }
574
575 if (is_old_ie) {
576 this.$cache.body.on("mouseup.irs_" + this.plugin_count, this.pointerUp.bind(this));
577 this.$cache.body.on("mouseleave.irs_" + this.plugin_count, this.pointerUp.bind(this));
578 }
579 },
580
581 pointerMove: function (e) {
582 if (!this.dragging) {
583 return;
584 }
585
586 var x = e.pageX || e.originalEvent.touches && e.originalEvent.touches[0].pageX;
587 this.coords.x_pointer = x - this.coords.x_gap;
588
589 this.calc();
590 },
591
592 pointerUp: function (e) {
593 if (this.current_plugin !== this.plugin_count) {
594 return;
595 }
596
597 if (this.is_active) {
598 this.is_active = false;
599 } else {
600 return;
601 }
602
603 // callbacks call
604 if ($.contains(this.$cache.cont[0], e.target) || this.dragging) {
605 this.is_finish = true;
606 this.callOnFinish();
607 }
608
609 this.$cache.cont.find(".state_hover").removeClass("state_hover");
610
611 this.force_redraw = true;
612 this.dragging = false;
613
614 if (is_old_ie) {
615 $("*").prop("unselectable", false);
616 }
617
618 this.updateScene();
619 },
620
621 changeLevel: function (target) {
622 switch (target) {
623 case "single":
624 this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_single);
625 break;
626 case "from":
627 this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_from);
628 this.$cache.s_from.addClass("state_hover");
629 this.$cache.s_from.addClass("type_last");
630 this.$cache.s_to.removeClass("type_last");
631 break;
632 case "to":
633 this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_to);
634 this.$cache.s_to.addClass("state_hover");
635 this.$cache.s_to.addClass("type_last");
636 this.$cache.s_from.removeClass("type_last");
637 break;
638 case "both":
639 this.coords.p_gap_left = this.toFixed(this.coords.p_pointer - this.coords.p_from);
640 this.coords.p_gap_right = this.toFixed(this.coords.p_to - this.coords.p_pointer);
641 this.$cache.s_to.removeClass("type_last");
642 this.$cache.s_from.removeClass("type_last");
643 break;
644 }
645 },
646
647 pointerDown: function (target, e) {
648 e.preventDefault();
649 var x = e.pageX || e.originalEvent.touches && e.originalEvent.touches[0].pageX;
650 if (e.button === 2) {
651 return;
652 }
653
654 this.current_plugin = this.plugin_count;
655 this.target = target;
656
657 this.is_active = true;
658 this.dragging = true;
659
660 this.coords.x_gap = this.$cache.rs.offset().left;
661 this.coords.x_pointer = x - this.coords.x_gap;
662
663 this.calcPointer();
664 this.changeLevel(target);
665
666 if (is_old_ie) {
667 $("*").prop("unselectable", true);
668 }
669
670 this.$cache.line.trigger("focus");
671
672 this.updateScene();
673 },
674
675 pointerClick: function (target, e) {
676 e.preventDefault();
677 var x = e.pageX || e.originalEvent.touches && e.originalEvent.touches[0].pageX;
678 if (e.button === 2) {
679 return;
680 }
681
682 this.current_plugin = this.plugin_count;
683 this.target = target;
684
685 this.is_click = true;
686 this.coords.x_gap = this.$cache.rs.offset().left;
687 this.coords.x_pointer = +(x - this.coords.x_gap).toFixed();
688
689 this.force_redraw = true;
690 this.calc();
691
692 this.$cache.line.trigger("focus");
693 },
694
695 key: function (target, e) {
696 if (this.current_plugin !== this.plugin_count || e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
697 return;
698 }
699
700 switch (e.which) {
701 case 83: // W
702 case 65: // A
703 case 40: // DOWN
704 case 37: // LEFT
705 e.preventDefault();
706 this.moveByKey(false);
707 break;
708
709 case 87: // S
710 case 68: // D
711 case 38: // UP
712 case 39: // RIGHT
713 e.preventDefault();
714 this.moveByKey(true);
715 break;
716 }
717
718 return true;
719 },
720
721 // Move by key. Beta
722 // TODO: refactor than have plenty of time
723 moveByKey: function (right) {
724 var p = this.coords.p_pointer;
725
726 if (right) {
727 p += this.options.keyboard_step;
728 } else {
729 p -= this.options.keyboard_step;
730 }
731
732 this.coords.x_pointer = this.toFixed(this.coords.w_rs / 100 * p);
733 this.is_key = true;
734 this.calc();
735 },
736
737 setMinMax: function () {
738 if (!this.options) {
739 return;
740 }
741
742 if (this.options.hide_min_max) {
743 this.$cache.min[0].style.display = "none";
744 this.$cache.max[0].style.display = "none";
745 return;
746 }
747
748 if (this.options.values.length) {
749 this.$cache.min.html(this.decorate(this.options.p_values[this.options.min]));
750 this.$cache.max.html(this.decorate(this.options.p_values[this.options.max]));
751 } else {
752 this.$cache.min.html(this.decorate(this._prettify(this.options.min), this.options.min));
753 this.$cache.max.html(this.decorate(this._prettify(this.options.max), this.options.max));
754 }
755
756 this.labels.w_min = this.$cache.min.outerWidth(false);
757 this.labels.w_max = this.$cache.max.outerWidth(false);
758 },
759
760
761
762 // =============================================================================================================
763 // Calculations
764
765 calc: function (update) {
766 if (!this.options) {
767 return;
768 }
769
770 this.calc_count++;
771
772 if (this.calc_count === 10 || update) {
773 this.calc_count = 0;
774 this.coords.w_rs = this.$cache.rs.outerWidth(false);
775 if (this.options.type === "single") {
776 this.coords.w_handle = this.$cache.s_single.outerWidth(false);
777 } else {
778 this.coords.w_handle = this.$cache.s_from.outerWidth(false);
779 }
780 }
781
782 if (!this.coords.w_rs) {
783 return;
784 }
785
786 this.calcPointer();
787
788 this.coords.p_handle = this.toFixed(this.coords.w_handle / this.coords.w_rs * 100);
789 var real_width = 100 - this.coords.p_handle,
790 real_x = this.toFixed(this.coords.p_pointer - this.coords.p_gap);
791
792 if (this.target === "click") {
793 this.coords.p_gap = this.coords.p_handle / 2;
794 real_x = this.toFixed(this.coords.p_pointer - this.coords.p_gap);
795 this.target = this.chooseHandle(real_x);
796 }
797
798 if (real_x < 0) {
799 real_x = 0;
800 } else if (real_x > real_width) {
801 real_x = real_width;
802 }
803
804 switch (this.target) {
805 case "base":
806 var w = (this.options.max - this.options.min) / 100,
807 f = (this.result.from - this.options.min) / w,
808 t = (this.result.to - this.options.min) / w;
809
810 this.coords.p_single_real = this.toFixed(f);
811 this.coords.p_from_real = this.toFixed(f);
812 this.coords.p_to_real = this.toFixed(t);
813
814 this.coords.p_single_real = this.checkDiapason(this.coords.p_single_real, this.options.from_min, this.options.from_max);
815 this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
816 this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
817
818 this.coords.p_single = this.toFixed(f - (this.coords.p_handle / 100 * f));
819 this.coords.p_from = this.toFixed(f - (this.coords.p_handle / 100 * f));
820 this.coords.p_to = this.toFixed(t - (this.coords.p_handle / 100 * t));
821
822 this.target = null;
823
824 break;
825
826 case "single":
827 if (this.options.from_fixed) {
828 break;
829 }
830
831 this.coords.p_single_real = this.calcWithStep(real_x / real_width * 100);
832 this.coords.p_single_real = this.checkDiapason(this.coords.p_single_real, this.options.from_min, this.options.from_max);
833 this.coords.p_single = this.toFixed(this.coords.p_single_real / 100 * real_width);
834
835 break;
836
837 case "from":
838 if (this.options.from_fixed) {
839 break;
840 }
841
842 this.coords.p_from_real = this.calcWithStep(real_x / real_width * 100);
843 if (this.coords.p_from_real > this.coords.p_to_real) {
844 this.coords.p_from_real = this.coords.p_to_real;
845 }
846 this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
847 this.coords.p_from_real = this.checkMinInterval(this.coords.p_from_real, this.coords.p_to_real, "from");
848 this.coords.p_from_real = this.checkMaxInterval(this.coords.p_from_real, this.coords.p_to_real, "from");
849 this.coords.p_from = this.toFixed(this.coords.p_from_real / 100 * real_width);
850
851 break;
852
853 case "to":
854 if (this.options.to_fixed) {
855 break;
856 }
857
858 this.coords.p_to_real = this.calcWithStep(real_x / real_width * 100);
859 if (this.coords.p_to_real < this.coords.p_from_real) {
860 this.coords.p_to_real = this.coords.p_from_real;
861 }
862 this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
863 this.coords.p_to_real = this.checkMinInterval(this.coords.p_to_real, this.coords.p_from_real, "to");
864 this.coords.p_to_real = this.checkMaxInterval(this.coords.p_to_real, this.coords.p_from_real, "to");
865 this.coords.p_to = this.toFixed(this.coords.p_to_real / 100 * real_width);
866
867 break;
868
869 case "both":
870 if (this.options.from_fixed || this.options.to_fixed) {
871 break;
872 }
873
874 real_x = this.toFixed(real_x + (this.coords.p_handle * 0.1));
875
876 this.coords.p_from_real = this.calcWithStep((real_x - this.coords.p_gap_left) / real_width * 100);
877 this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
878 this.coords.p_from_real = this.checkMinInterval(this.coords.p_from_real, this.coords.p_to_real, "from");
879 this.coords.p_from = this.toFixed(this.coords.p_from_real / 100 * real_width);
880
881 this.coords.p_to_real = this.calcWithStep((real_x + this.coords.p_gap_right) / real_width * 100);
882 this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
883 this.coords.p_to_real = this.checkMinInterval(this.coords.p_to_real, this.coords.p_from_real, "to");
884 this.coords.p_to = this.toFixed(this.coords.p_to_real / 100 * real_width);
885
886 break;
887 }
888
889 if (this.options.type === "single") {
890 this.coords.p_bar_x = (this.coords.p_handle / 2);
891 this.coords.p_bar_w = this.coords.p_single;
892
893 this.result.from_percent = this.coords.p_single_real;
894 this.result.from = this.calcReal(this.coords.p_single_real);
895 if (this.options.values.length) {
896 this.result.from_value = this.options.values[this.result.from];
897 }
898 } else {
899 this.coords.p_bar_x = this.toFixed(this.coords.p_from + (this.coords.p_handle / 2));
900 this.coords.p_bar_w = this.toFixed(this.coords.p_to - this.coords.p_from);
901
902 this.result.from_percent = this.coords.p_from_real;
903 this.result.from = this.calcReal(this.coords.p_from_real);
904 this.result.to_percent = this.coords.p_to_real;
905 this.result.to = this.calcReal(this.coords.p_to_real);
906 if (this.options.values.length) {
907 this.result.from_value = this.options.values[this.result.from];
908 this.result.to_value = this.options.values[this.result.to];
909 }
910 }
911
912 this.calcMinMax();
913 this.calcLabels();
914 },
915
916 calcPointer: function () {
917 if (!this.coords.w_rs) {
918 this.coords.p_pointer = 0;
919 return;
920 }
921
922 if (this.coords.x_pointer < 0 || isNaN(this.coords.x_pointer) ) {
923 this.coords.x_pointer = 0;
924 } else if (this.coords.x_pointer > this.coords.w_rs) {
925 this.coords.x_pointer = this.coords.w_rs;
926 }
927
928 this.coords.p_pointer = this.toFixed(this.coords.x_pointer / this.coords.w_rs * 100);
929 },
930
931 chooseHandle: function (real_x) {
932 if (this.options.type === "single") {
933 return "single";
934 } else {
935 var m_point = this.coords.p_from_real + ((this.coords.p_to_real - this.coords.p_from_real) / 2);
936 if (real_x >= m_point) {
937 return this.options.to_fixed ? "from" : "to";
938 } else {
939 return this.options.from_fixed ? "to" : "from";
940 }
941 }
942 },
943
944 calcMinMax: function () {
945 if (!this.coords.w_rs) {
946 return;
947 }
948
949 this.labels.p_min = this.labels.w_min / this.coords.w_rs * 100;
950 this.labels.p_max = this.labels.w_max / this.coords.w_rs * 100;
951 },
952
953 calcLabels: function () {
954 if (!this.coords.w_rs || this.options.hide_from_to) {
955 return;
956 }
957
958 if (this.options.type === "single") {
959
960 this.labels.w_single = this.$cache.single.outerWidth(false);
961 this.labels.p_single = this.labels.w_single / this.coords.w_rs * 100;
962 this.labels.p_single_left = this.coords.p_single + (this.coords.p_handle / 2) - (this.labels.p_single / 2);
963 this.labels.p_single_left = this.checkEdges(this.labels.p_single_left, this.labels.p_single);
964
965 } else {
966
967 this.labels.w_from = this.$cache.from.outerWidth(false);
968 this.labels.p_from = this.labels.w_from / this.coords.w_rs * 100;
969 this.labels.p_from_left = this.coords.p_from + (this.coords.p_handle / 2) - (this.labels.p_from / 2);
970 this.labels.p_from_left = this.toFixed(this.labels.p_from_left);
971 this.labels.p_from_left = this.checkEdges(this.labels.p_from_left, this.labels.p_from);
972
973 this.labels.w_to = this.$cache.to.outerWidth(false);
974 this.labels.p_to = this.labels.w_to / this.coords.w_rs * 100;
975 this.labels.p_to_left = this.coords.p_to + (this.coords.p_handle / 2) - (this.labels.p_to / 2);
976 this.labels.p_to_left = this.toFixed(this.labels.p_to_left);
977 this.labels.p_to_left = this.checkEdges(this.labels.p_to_left, this.labels.p_to);
978
979 this.labels.w_single = this.$cache.single.outerWidth(false);
980 this.labels.p_single = this.labels.w_single / this.coords.w_rs * 100;
981 this.labels.p_single_left = ((this.labels.p_from_left + this.labels.p_to_left + this.labels.p_to) / 2) - (this.labels.p_single / 2);
982 this.labels.p_single_left = this.toFixed(this.labels.p_single_left);
983 this.labels.p_single_left = this.checkEdges(this.labels.p_single_left, this.labels.p_single);
984
985 }
986 },
987
988
989
990 // =============================================================================================================
991 // Drawings
992
993 updateScene: function () {
994 if (this.raf_id) {
995 cancelAnimationFrame(this.raf_id);
996 this.raf_id = null;
997 }
998
999 clearTimeout(this.update_tm);
1000 this.update_tm = null;
1001
1002 if (!this.options) {
1003 return;
1004 }
1005
1006 this.drawHandles();
1007
1008 if (this.is_active) {
1009 this.raf_id = requestAnimationFrame(this.updateScene.bind(this));
1010 } else {
1011 this.update_tm = setTimeout(this.updateScene.bind(this), 300);
1012 }
1013 },
1014
1015 drawHandles: function () {
1016 this.coords.w_rs = this.$cache.rs.outerWidth(false);
1017
1018 if (!this.coords.w_rs) {
1019 return;
1020 }
1021
1022 if (this.coords.w_rs !== this.coords.w_rs_old) {
1023 this.target = "base";
1024 this.is_resize = true;
1025 }
1026
1027 if (this.coords.w_rs !== this.coords.w_rs_old || this.force_redraw) {
1028 this.setMinMax();
1029 this.calc(true);
1030 this.drawLabels();
1031 if (this.options.grid) {
1032 this.calcGridMargin();
1033 this.calcGridLabels();
1034 }
1035 this.force_redraw = true;
1036 this.coords.w_rs_old = this.coords.w_rs;
1037 this.drawShadow();
1038 }
1039
1040 if (!this.coords.w_rs) {
1041 return;
1042 }
1043
1044 if (!this.dragging && !this.force_redraw && !this.is_key) {
1045 return;
1046 }
1047
1048 if (this.old_from !== this.result.from || this.old_to !== this.result.to || this.force_redraw || this.is_key) {
1049
1050 this.drawLabels();
1051
1052 this.$cache.bar[0].style.left = this.coords.p_bar_x + "%";
1053 this.$cache.bar[0].style.width = this.coords.p_bar_w + "%";
1054
1055 if (this.options.type === "single") {
1056 this.$cache.s_single[0].style.left = this.coords.p_single + "%";
1057
1058 this.$cache.single[0].style.left = this.labels.p_single_left + "%";
1059
1060 if (this.options.values.length) {
1061 this.$cache.input.prop("value", this.result.from_value);
1062 this.$cache.input.data("from", this.result.from_value);
1063 } else {
1064 this.$cache.input.prop("value", this.result.from);
1065 this.$cache.input.data("from", this.result.from);
1066 }
1067 } else {
1068 this.$cache.s_from[0].style.left = this.coords.p_from + "%";
1069 this.$cache.s_to[0].style.left = this.coords.p_to + "%";
1070
1071 if (this.old_from !== this.result.from || this.force_redraw) {
1072 this.$cache.from[0].style.left = this.labels.p_from_left + "%";
1073 }
1074 if (this.old_to !== this.result.to || this.force_redraw) {
1075 this.$cache.to[0].style.left = this.labels.p_to_left + "%";
1076 }
1077
1078 this.$cache.single[0].style.left = this.labels.p_single_left + "%";
1079
1080 if (this.options.values.length) {
1081 this.$cache.input.prop("value", this.result.from_value + ";" + this.result.to_value);
1082 this.$cache.input.data("from", this.result.from_value);
1083 this.$cache.input.data("to", this.result.to_value);
1084 } else {
1085 this.$cache.input.prop("value", this.result.from + ";" + this.result.to);
1086 this.$cache.input.data("from", this.result.from);
1087 this.$cache.input.data("to", this.result.to);
1088 }
1089 }
1090
1091 if ((this.old_from !== this.result.from || this.old_to !== this.result.to) && !this.is_start) {
1092 this.$cache.input.trigger("change");
1093 }
1094
1095 this.old_from = this.result.from;
1096 this.old_to = this.result.to;
1097
1098 // callbacks call
1099 if (!this.is_resize && !this.is_update && !this.is_start && !this.is_finish) {
1100 this.callOnChange();
1101 }
1102 if (this.is_key || this.is_click) {
1103 this.callOnFinish();
1104 }
1105
1106 this.is_update = false;
1107 this.is_resize = false;
1108 this.is_finish = false;
1109 }
1110
1111 this.is_start = false;
1112 this.is_key = false;
1113 this.is_click = false;
1114 this.force_redraw = false;
1115 },
1116
1117 // callbacks
1118 callOnStart: function () {
1119 if (this.options.onStart && typeof this.options.onStart === "function") {
1120 this.options.onStart(this.result);
1121 }
1122 },
1123 callOnChange: function () {
1124 if (this.options.onChange && typeof this.options.onChange === "function") {
1125 this.options.onChange(this.result);
1126 }
1127 },
1128 callOnFinish: function () {
1129 if (this.options.onFinish && typeof this.options.onFinish === "function") {
1130 this.options.onFinish(this.result);
1131 }
1132 },
1133 callOnUpdate: function () {
1134 if (this.options.onUpdate && typeof this.options.onUpdate === "function") {
1135 this.options.onUpdate(this.result);
1136 }
1137 },
1138
1139 drawLabels: function () {
1140 if (!this.options) {
1141 return;
1142 }
1143
1144 var values_num = this.options.values.length,
1145 p_values = this.options.p_values,
1146 text_single,
1147 text_from,
1148 text_to;
1149
1150 if (this.options.hide_from_to) {
1151 return;
1152 }
1153
1154 if (this.options.type === "single") {
1155
1156 if (values_num) {
1157 text_single = this.decorate(p_values[this.result.from]);
1158 this.$cache.single.html(text_single);
1159 } else {
1160 text_single = this.decorate(this._prettify(this.result.from), this.result.from);
1161 this.$cache.single.html(text_single);
1162 }
1163
1164 this.calcLabels();
1165
1166 if (this.labels.p_single_left < this.labels.p_min + 1) {
1167 this.$cache.min[0].style.visibility = "hidden";
1168 } else {
1169 this.$cache.min[0].style.visibility = "visible";
1170 }
1171
1172 if (this.labels.p_single_left + this.labels.p_single > 100 - this.labels.p_max - 1) {
1173 this.$cache.max[0].style.visibility = "hidden";
1174 } else {
1175 this.$cache.max[0].style.visibility = "visible";
1176 }
1177
1178 } else {
1179
1180 if (values_num) {
1181
1182 if (this.options.decorate_both) {
1183 text_single = this.decorate(p_values[this.result.from]);
1184 text_single += this.options.values_separator;
1185 text_single += this.decorate(p_values[this.result.to]);
1186 } else {
1187 text_single = this.decorate(p_values[this.result.from] + this.options.values_separator + p_values[this.result.to]);
1188 }
1189 text_from = this.decorate(p_values[this.result.from]);
1190 text_to = this.decorate(p_values[this.result.to]);
1191
1192 this.$cache.single.html(text_single);
1193 this.$cache.from.html(text_from);
1194 this.$cache.to.html(text_to);
1195
1196 } else {
1197
1198 if (this.options.decorate_both) {
1199 text_single = this.decorate(this._prettify(this.result.from), this.result.from);
1200 text_single += this.options.values_separator;
1201 text_single += this.decorate(this._prettify(this.result.to), this.result.to);
1202 } else {
1203 text_single = this.decorate(this._prettify(this.result.from) + this.options.values_separator + this._prettify(this.result.to), this.result.to);
1204 }
1205 text_from = this.decorate(this._prettify(this.result.from), this.result.from);
1206 text_to = this.decorate(this._prettify(this.result.to), this.result.to);
1207
1208 this.$cache.single.html(text_single);
1209 this.$cache.from.html(text_from);
1210 this.$cache.to.html(text_to);
1211
1212 }
1213
1214 this.calcLabels();
1215
1216 var min = Math.min(this.labels.p_single_left, this.labels.p_from_left),
1217 single_left = this.labels.p_single_left + this.labels.p_single,
1218 to_left = this.labels.p_to_left + this.labels.p_to,
1219 max = Math.max(single_left, to_left);
1220
1221 if (this.labels.p_from_left + this.labels.p_from >= this.labels.p_to_left) {
1222 this.$cache.from[0].style.visibility = "hidden";
1223 this.$cache.to[0].style.visibility = "hidden";
1224 this.$cache.single[0].style.visibility = "visible";
1225
1226 if (this.result.from === this.result.to) {
1227 this.$cache.from[0].style.visibility = "visible";
1228 this.$cache.single[0].style.visibility = "hidden";
1229 max = to_left;
1230 } else {
1231 this.$cache.from[0].style.visibility = "hidden";
1232 this.$cache.single[0].style.visibility = "visible";
1233 max = Math.max(single_left, to_left);
1234 }
1235 } else {
1236 this.$cache.from[0].style.visibility = "visible";
1237 this.$cache.to[0].style.visibility = "visible";
1238 this.$cache.single[0].style.visibility = "hidden";
1239 }
1240
1241 if (min < this.labels.p_min + 1) {
1242 this.$cache.min[0].style.visibility = "hidden";
1243 } else {
1244 this.$cache.min[0].style.visibility = "visible";
1245 }
1246
1247 if (max > 100 - this.labels.p_max - 1) {
1248 this.$cache.max[0].style.visibility = "hidden";
1249 } else {
1250 this.$cache.max[0].style.visibility = "visible";
1251 }
1252
1253 }
1254 },
1255
1256 drawShadow: function () {
1257 var o = this.options,
1258 c = this.$cache,
1259
1260 is_from_min = typeof o.from_min === "number" && !isNaN(o.from_min),
1261 is_from_max = typeof o.from_max === "number" && !isNaN(o.from_max),
1262 is_to_min = typeof o.to_min === "number" && !isNaN(o.to_min),
1263 is_to_max = typeof o.to_max === "number" && !isNaN(o.to_max),
1264
1265 from_min,
1266 from_max,
1267 to_min,
1268 to_max;
1269
1270 if (o.type === "single") {
1271 if (o.from_shadow && (is_from_min || is_from_max)) {
1272 from_min = this.calcPercent(is_from_min ? o.from_min : o.min);
1273 from_max = this.calcPercent(is_from_max ? o.from_max : o.max) - from_min;
1274 from_min = this.toFixed(from_min - (this.coords.p_handle / 100 * from_min));
1275 from_max = this.toFixed(from_max - (this.coords.p_handle / 100 * from_max));
1276 from_min = from_min + (this.coords.p_handle / 2);
1277
1278 c.shad_single[0].style.display = "block";
1279 c.shad_single[0].style.left = from_min + "%";
1280 c.shad_single[0].style.width = from_max + "%";
1281 } else {
1282 c.shad_single[0].style.display = "none";
1283 }
1284 } else {
1285 if (o.from_shadow && (is_from_min || is_from_max)) {
1286 from_min = this.calcPercent(is_from_min ? o.from_min : o.min);
1287 from_max = this.calcPercent(is_from_max ? o.from_max : o.max) - from_min;
1288 from_min = this.toFixed(from_min - (this.coords.p_handle / 100 * from_min));
1289 from_max = this.toFixed(from_max - (this.coords.p_handle / 100 * from_max));
1290 from_min = from_min + (this.coords.p_handle / 2);
1291
1292 c.shad_from[0].style.display = "block";
1293 c.shad_from[0].style.left = from_min + "%";
1294 c.shad_from[0].style.width = from_max + "%";
1295 } else {
1296 c.shad_from[0].style.display = "none";
1297 }
1298
1299 if (o.to_shadow && (is_to_min || is_to_max)) {
1300 to_min = this.calcPercent(is_to_min ? o.to_min : o.min);
1301 to_max = this.calcPercent(is_to_max ? o.to_max : o.max) - to_min;
1302 to_min = this.toFixed(to_min - (this.coords.p_handle / 100 * to_min));
1303 to_max = this.toFixed(to_max - (this.coords.p_handle / 100 * to_max));
1304 to_min = to_min + (this.coords.p_handle / 2);
1305
1306 c.shad_to[0].style.display = "block";
1307 c.shad_to[0].style.left = to_min + "%";
1308 c.shad_to[0].style.width = to_max + "%";
1309 } else {
1310 c.shad_to[0].style.display = "none";
1311 }
1312 }
1313 },
1314
1315
1316
1317 // =============================================================================================================
1318 // Service methods
1319
1320 toggleInput: function () {
1321 this.$cache.input.toggleClass("irs-hidden-input");
1322 },
1323
1324 calcPercent: function (num) {
1325 var w = (this.options.max - this.options.min) / 100,
1326 percent = (num - this.options.min) / w;
1327
1328 return this.toFixed(percent);
1329 },
1330
1331 calcReal: function (percent) {
1332 var min = this.options.min,
1333 max = this.options.max,
1334 min_decimals = min.toString().split(".")[1],
1335 max_decimals = max.toString().split(".")[1],
1336 min_length, max_length,
1337 avg_decimals = 0,
1338 abs = 0;
1339
1340 if (percent === 0) {
1341 return this.options.min;
1342 }
1343 if (percent === 100) {
1344 return this.options.max;
1345 }
1346
1347
1348 if (min_decimals) {
1349 min_length = min_decimals.length;
1350 avg_decimals = min_length;
1351 }
1352 if (max_decimals) {
1353 max_length = max_decimals.length;
1354 avg_decimals = max_length;
1355 }
1356 if (min_length && max_length) {
1357 avg_decimals = (min_length >= max_length) ? min_length : max_length;
1358 }
1359
1360 if (min < 0) {
1361 abs = Math.abs(min);
1362 min = +(min + abs).toFixed(avg_decimals);
1363 max = +(max + abs).toFixed(avg_decimals);
1364 }
1365
1366 var number = ((max - min) / 100 * percent) + min,
1367 string = this.options.step.toString().split(".")[1],
1368 result;
1369
1370 if (string) {
1371 number = +number.toFixed(string.length);
1372 } else {
1373 number = number / this.options.step;
1374 number = number * this.options.step;
1375
1376 number = +number.toFixed(0);
1377 }
1378
1379 if (abs) {
1380 number -= abs;
1381 }
1382
1383 if (string) {
1384 result = +number.toFixed(string.length);
1385 } else {
1386 result = this.toFixed(number);
1387 }
1388
1389 if (result < this.options.min) {
1390 result = this.options.min;
1391 } else if (result > this.options.max) {
1392 result = this.options.max;
1393 }
1394
1395 return result;
1396 },
1397
1398 calcWithStep: function (percent) {
1399 var rounded = Math.round(percent / this.coords.p_step) * this.coords.p_step;
1400
1401 if (rounded > 100) {
1402 rounded = 100;
1403 }
1404 if (percent === 100) {
1405 rounded = 100;
1406 }
1407
1408 return this.toFixed(rounded);
1409 },
1410
1411 checkMinInterval: function (p_current, p_next, type) {
1412 var o = this.options,
1413 current,
1414 next;
1415
1416 if (!o.min_interval) {
1417 return p_current;
1418 }
1419
1420 current = this.calcReal(p_current);
1421 next = this.calcReal(p_next);
1422
1423 if (type === "from") {
1424
1425 if (next - current < o.min_interval) {
1426 current = next - o.min_interval;
1427 }
1428
1429 } else {
1430
1431 if (current - next < o.min_interval) {
1432 current = next + o.min_interval;
1433 }
1434
1435 }
1436
1437 return this.calcPercent(current);
1438 },
1439
1440 checkMaxInterval: function (p_current, p_next, type) {
1441 var o = this.options,
1442 current,
1443 next;
1444
1445 if (!o.max_interval) {
1446 return p_current;
1447 }
1448
1449 current = this.calcReal(p_current);
1450 next = this.calcReal(p_next);
1451
1452 if (type === "from") {
1453
1454 if (next - current > o.max_interval) {
1455 current = next - o.max_interval;
1456 }
1457
1458 } else {
1459
1460 if (current - next > o.max_interval) {
1461 current = next + o.max_interval;
1462 }
1463
1464 }
1465
1466 return this.calcPercent(current);
1467 },
1468
1469 checkDiapason: function (p_num, min, max) {
1470 var num = this.calcReal(p_num),
1471 o = this.options;
1472
1473 if (typeof min !== "number") {
1474 min = o.min;
1475 }
1476
1477 if (typeof max !== "number") {
1478 max = o.max;
1479 }
1480
1481 if (num < min) {
1482 num = min;
1483 }
1484
1485 if (num > max) {
1486 num = max;
1487 }
1488
1489 return this.calcPercent(num);
1490 },
1491
1492 toFixed: function (num) {
1493 num = num.toFixed(9);
1494 return +num;
1495 },
1496
1497 _prettify: function (num) {
1498 if (!this.options.prettify_enabled) {
1499 return num;
1500 }
1501
1502 if (this.options.prettify && typeof this.options.prettify === "function") {
1503 return this.options.prettify(num);
1504 } else {
1505 return this.prettify(num);
1506 }
1507 },
1508
1509 prettify: function (num) {
1510 var n = num.toString();
1511 return n.replace(/(\d{1,3}(?=(?:\d\d\d)+(?!\d)))/g, "$1" + this.options.prettify_separator);
1512 },
1513
1514 checkEdges: function (left, width) {
1515 if (!this.options.force_edges) {
1516 return this.toFixed(left);
1517 }
1518
1519 if (left < 0) {
1520 left = 0;
1521 } else if (left > 100 - width) {
1522 left = 100 - width;
1523 }
1524
1525 return this.toFixed(left);
1526 },
1527
1528 validate: function () {
1529 var o = this.options,
1530 r = this.result,
1531 v = o.values,
1532 vl = v.length,
1533 value,
1534 i;
1535
1536 if (typeof o.min === "string") o.min = +o.min;
1537 if (typeof o.max === "string") o.max = +o.max;
1538 if (typeof o.from === "string") o.from = +o.from;
1539 if (typeof o.to === "string") o.to = +o.to;
1540 if (typeof o.step === "string") o.step = +o.step;
1541
1542 if (typeof o.from_min === "string") o.from_min = +o.from_min;
1543 if (typeof o.from_max === "string") o.from_max = +o.from_max;
1544 if (typeof o.to_min === "string") o.to_min = +o.to_min;
1545 if (typeof o.to_max === "string") o.to_max = +o.to_max;
1546
1547 if (typeof o.keyboard_step === "string") o.keyboard_step = +o.keyboard_step;
1548 if (typeof o.grid_num === "string") o.grid_num = +o.grid_num;
1549
1550 if (o.max <= o.min) {
1551 if (o.min) {
1552 o.max = o.min * 2;
1553 } else {
1554 o.max = o.min + 1;
1555 }
1556 o.step = 1;
1557 }
1558
1559 if (vl) {
1560 o.p_values = [];
1561 o.min = 0;
1562 o.max = vl - 1;
1563 o.step = 1;
1564 o.grid_num = o.max;
1565 o.grid_snap = true;
1566
1567
1568 for (i = 0; i < vl; i++) {
1569 value = +v[i];
1570
1571 if (!isNaN(value)) {
1572 v[i] = value;
1573 value = this._prettify(value);
1574 } else {
1575 value = v[i];
1576 }
1577
1578 o.p_values.push(value);
1579 }
1580 }
1581
1582 if (typeof o.from !== "number" || isNaN(o.from)) {
1583 o.from = o.min;
1584 }
1585
1586 if (typeof o.to !== "number" || isNaN(o.from)) {
1587 o.to = o.max;
1588 }
1589
1590 if (o.type === "single") {
1591
1592 if (o.from < o.min) {
1593 o.from = o.min;
1594 }
1595
1596 if (o.from > o.max) {
1597 o.from = o.max;
1598 }
1599
1600 } else {
1601
1602 if (o.from < o.min || o.from > o.max) {
1603 o.from = o.min;
1604 }
1605 if (o.to > o.max || o.to < o.min) {
1606 o.to = o.max;
1607 }
1608 if (o.from > o.to) {
1609 o.from = o.to;
1610 }
1611
1612 }
1613
1614 if (typeof o.step !== "number" || isNaN(o.step) || !o.step || o.step < 0) {
1615 o.step = 1;
1616 }
1617
1618 if (typeof o.keyboard_step !== "number" || isNaN(o.keyboard_step) || !o.keyboard_step || o.keyboard_step < 0) {
1619 o.keyboard_step = 5;
1620 }
1621
1622 if (typeof o.from_min === "number" && o.from < o.from_min) {
1623 o.from = o.from_min;
1624 }
1625
1626 if (typeof o.from_max === "number" && o.from > o.from_max) {
1627 o.from = o.from_max;
1628 }
1629
1630 if (typeof o.to_min === "number" && o.to < o.to_min) {
1631 o.to = o.to_min;
1632 }
1633
1634 if (typeof o.to_max === "number" && o.from > o.to_max) {
1635 o.to = o.to_max;
1636 }
1637
1638 if (r) {
1639 if (r.min !== o.min) {
1640 r.min = o.min;
1641 }
1642
1643 if (r.max !== o.max) {
1644 r.max = o.max;
1645 }
1646
1647 if (r.from < r.min || r.from > r.max) {
1648 r.from = o.from;
1649 }
1650
1651 if (r.to < r.min || r.to > r.max) {
1652 r.to = o.to;
1653 }
1654 }
1655
1656 if (typeof o.min_interval !== "number" || isNaN(o.min_interval) || !o.min_interval || o.min_interval < 0) {
1657 o.min_interval = 0;
1658 }
1659
1660 if (typeof o.max_interval !== "number" || isNaN(o.max_interval) || !o.max_interval || o.max_interval < 0) {
1661 o.max_interval = 0;
1662 }
1663
1664 if (o.min_interval && o.min_interval > o.max - o.min) {
1665 o.min_interval = o.max - o.min;
1666 }
1667
1668 if (o.max_interval && o.max_interval > o.max - o.min) {
1669 o.max_interval = o.max - o.min;
1670 }
1671 },
1672
1673 decorate: function (num, original) {
1674 var decorated = "",
1675 o = this.options;
1676
1677 if (o.prefix) {
1678 decorated += o.prefix;
1679 }
1680
1681 decorated += num;
1682
1683 if (o.max_postfix) {
1684 if (o.values.length && num === o.p_values[o.max]) {
1685 decorated += o.max_postfix;
1686 if (o.postfix) {
1687 decorated += " ";
1688 }
1689 } else if (original === o.max) {
1690 decorated += o.max_postfix;
1691 if (o.postfix) {
1692 decorated += " ";
1693 }
1694 }
1695 }
1696
1697 if (o.postfix) {
1698 decorated += o.postfix;
1699 }
1700
1701 return decorated;
1702 },
1703
1704 updateFrom: function () {
1705 this.result.from = this.options.from;
1706 this.result.from_percent = this.calcPercent(this.result.from);
1707 if (this.options.values) {
1708 this.result.from_value = this.options.values[this.result.from];
1709 }
1710 },
1711
1712 updateTo: function () {
1713 this.result.to = this.options.to;
1714 this.result.to_percent = this.calcPercent(this.result.to);
1715 if (this.options.values) {
1716 this.result.to_value = this.options.values[this.result.to];
1717 }
1718 },
1719
1720 updateResult: function () {
1721 this.result.min = this.options.min;
1722 this.result.max = this.options.max;
1723 this.updateFrom();
1724 this.updateTo();
1725 },
1726
1727
1728 // =============================================================================================================
1729 // Grid
1730
1731 appendGrid: function () {
1732 if (!this.options.grid) {
1733 return;
1734 }
1735
1736 var o = this.options,
1737 i, z,
1738
1739 total = o.max - o.min,
1740 big_num = o.grid_num,
1741 big_p = 0,
1742 big_w = 0,
1743
1744 small_max = 4,
1745 local_small_max,
1746 small_p,
1747 small_w = 0,
1748
1749 result,
1750 html = '';
1751
1752
1753
1754 this.calcGridMargin();
1755
1756 if (o.grid_snap) {
1757 big_num = total / o.step;
1758 big_p = this.toFixed(o.step / (total / 100));
1759 } else {
1760 big_p = this.toFixed(100 / big_num);
1761 }
1762
1763 if (big_num > 4) {
1764 small_max = 3;
1765 }
1766 if (big_num > 7) {
1767 small_max = 2;
1768 }
1769 if (big_num > 14) {
1770 small_max = 1;
1771 }
1772 if (big_num > 28) {
1773 small_max = 0;
1774 }
1775
1776 for (i = 0; i < big_num + 1; i++) {
1777 local_small_max = small_max;
1778
1779 big_w = this.toFixed(big_p * i);
1780
1781 if (big_w > 100) {
1782 big_w = 100;
1783
1784 local_small_max -= 2;
1785 if (local_small_max < 0) {
1786 local_small_max = 0;
1787 }
1788 }
1789 this.coords.big[i] = big_w;
1790
1791 small_p = (big_w - (big_p * (i - 1))) / (local_small_max + 1);
1792
1793 for (z = 1; z <= local_small_max; z++) {
1794 if (big_w === 0) {
1795 break;
1796 }
1797
1798 small_w = this.toFixed(big_w - (small_p * z));
1799
1800 html += '<span class="irs-grid-pol small" style="left: ' + small_w + '%"></span>';
1801 }
1802
1803 html += '<span class="irs-grid-pol" style="left: ' + big_w + '%"></span>';
1804
1805 result = this.calcReal(big_w);
1806 if (o.values.length) {
1807 result = o.p_values[result];
1808 } else {
1809 result = this._prettify(result);
1810 }
1811
1812 html += '<span class="irs-grid-text js-grid-text-' + i + '" style="left: ' + big_w + '%">' + result + '</span>';
1813 }
1814 this.coords.big_num = Math.ceil(big_num + 1);
1815
1816
1817
1818 this.$cache.cont.addClass("irs-with-grid");
1819 this.$cache.grid.html(html);
1820 this.cacheGridLabels();
1821 },
1822
1823 cacheGridLabels: function () {
1824 var $label, i,
1825 num = this.coords.big_num;
1826
1827 for (i = 0; i < num; i++) {
1828 $label = this.$cache.grid.find(".js-grid-text-" + i);
1829 this.$cache.grid_labels.push($label);
1830 }
1831
1832 this.calcGridLabels();
1833 },
1834
1835 calcGridLabels: function () {
1836 var i, label, start = [], finish = [],
1837 num = this.coords.big_num;
1838
1839 for (i = 0; i < num; i++) {
1840 this.coords.big_w[i] = this.$cache.grid_labels[i].outerWidth(false);
1841 this.coords.big_p[i] = this.toFixed(this.coords.big_w[i] / this.coords.w_rs * 100);
1842 this.coords.big_x[i] = this.toFixed(this.coords.big_p[i] / 2);
1843
1844 start[i] = this.toFixed(this.coords.big[i] - this.coords.big_x[i]);
1845 finish[i] = this.toFixed(start[i] + this.coords.big_p[i]);
1846 }
1847
1848 if (this.options.force_edges) {
1849 if (start[0] < -this.coords.grid_gap) {
1850 start[0] = -this.coords.grid_gap;
1851 finish[0] = this.toFixed(start[0] + this.coords.big_p[0]);
1852
1853 this.coords.big_x[0] = this.coords.grid_gap;
1854 }
1855
1856 if (finish[num - 1] > 100 + this.coords.grid_gap) {
1857 finish[num - 1] = 100 + this.coords.grid_gap;
1858 start[num - 1] = this.toFixed(finish[num - 1] - this.coords.big_p[num - 1]);
1859
1860 this.coords.big_x[num - 1] = this.toFixed(this.coords.big_p[num - 1] - this.coords.grid_gap);
1861 }
1862 }
1863
1864 this.calcGridCollision(2, start, finish);
1865 this.calcGridCollision(4, start, finish);
1866
1867 for (i = 0; i < num; i++) {
1868 label = this.$cache.grid_labels[i][0];
1869 label.style.marginLeft = -this.coords.big_x[i] + "%";
1870 }
1871 },
1872
1873 // Collisions Calc Beta
1874 // TODO: Refactor then have plenty of time
1875 calcGridCollision: function (step, start, finish) {
1876 var i, next_i, label,
1877 num = this.coords.big_num;
1878
1879 for (i = 0; i < num; i += step) {
1880 next_i = i + (step / 2);
1881 if (next_i >= num) {
1882 break;
1883 }
1884
1885 label = this.$cache.grid_labels[next_i][0];
1886
1887 if (finish[i] <= start[next_i]) {
1888 label.style.visibility = "visible";
1889 } else {
1890 label.style.visibility = "hidden";
1891 }
1892 }
1893 },
1894
1895 calcGridMargin: function () {
1896 if (!this.options.grid_margin) {
1897 return;
1898 }
1899
1900 this.coords.w_rs = this.$cache.rs.outerWidth(false);
1901 if (!this.coords.w_rs) {
1902 return;
1903 }
1904
1905 if (this.options.type === "single") {
1906 this.coords.w_handle = this.$cache.s_single.outerWidth(false);
1907 } else {
1908 this.coords.w_handle = this.$cache.s_from.outerWidth(false);
1909 }
1910 this.coords.p_handle = this.toFixed(this.coords.w_handle / this.coords.w_rs * 100);
1911 this.coords.grid_gap = this.toFixed((this.coords.p_handle / 2) - 0.1);
1912
1913 this.$cache.grid[0].style.width = this.toFixed(100 - this.coords.p_handle) + "%";
1914 this.$cache.grid[0].style.left = this.coords.grid_gap + "%";
1915 },
1916
1917
1918
1919 // =============================================================================================================
1920 // Public methods
1921
1922 update: function (options) {
1923 if (!this.input) {
1924 return;
1925 }
1926
1927 this.is_update = true;
1928
1929 this.options.from = this.result.from;
1930 this.options.to = this.result.to;
1931
1932 this.options = $.extend(this.options, options);
1933 this.validate();
1934 this.updateResult(options);
1935
1936 this.toggleInput();
1937 this.remove();
1938 this.init(true);
1939 },
1940
1941 reset: function () {
1942 if (!this.input) {
1943 return;
1944 }
1945
1946 this.updateResult();
1947 this.update();
1948 },
1949
1950 destroy: function () {
1951 if (!this.input) {
1952 return;
1953 }
1954
1955 this.toggleInput();
1956 this.$cache.input.prop("readonly", false);
1957 $.data(this.input, "ionRangeSlider", null);
1958
1959 this.remove();
1960 this.input = null;
1961 this.options = null;
1962 }
1963 };
1964
1965 $.fn.ionRangeSlider = function (options) {
1966 return this.each(function() {
1967 if (!$.data(this, "ionRangeSlider")) {
1968 $.data(this, "ionRangeSlider", new IonRangeSlider(this, options, plugin_count++));
1969 }
1970 });
1971 };
1972
1973
1974
1975 // =================================================================================================================
1976 // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
1977 // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
1978
1979 // requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
1980
1981 // MIT license
1982
1983 (function() {
1984 var lastTime = 0;
1985 var vendors = ['ms', 'moz', 'webkit', 'o'];
1986 for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
1987 window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
1988 window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
1989 || window[vendors[x]+'CancelRequestAnimationFrame'];
1990 }
1991
1992 if (!window.requestAnimationFrame)
1993 window.requestAnimationFrame = function(callback, element) {
1994 var currTime = new Date().getTime();
1995 var timeToCall = Math.max(0, 16 - (currTime - lastTime));
1996 var id = window.setTimeout(function() { callback(currTime + timeToCall); },
1997 timeToCall);
1998 lastTime = currTime + timeToCall;
1999 return id;
2000 };
2001
2002 if (!window.cancelAnimationFrame)
2003 window.cancelAnimationFrame = function(id) {
2004 clearTimeout(id);
2005 };
2006 }());
2007
2008} (jQuery, document, window, navigator));
2009