LaravelTest
2449 строк · 82.7 Кб
1// Ion.RangeSlider
2// version 2.3.1 Build: 382
3// © Denis Ineshin, 2019
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(factory) {14if ((typeof jQuery === 'undefined' || !jQuery) && typeof define === "function" && define.amd) {15define(["jquery"], function (jQuery) {16return factory(jQuery, document, window, navigator);17});18} else if ((typeof jQuery === 'undefined' || !jQuery) && typeof exports === "object") {19factory(require("jquery"), document, window, navigator);20} else {21factory(jQuery, document, window, navigator);22}23} (function ($, document, window, navigator, undefined) {24"use strict";25
26// =================================================================================================================27// Service28
29var plugin_count = 0;30
31// IE8 fix32var is_old_ie = (function () {33var n = navigator.userAgent,34r = /msie\s\d+/i,35v;36if (n.search(r) > 0) {37v = r.exec(n).toString();38v = v.split(" ")[1];39if (v < 9) {40$("html").addClass("lt-ie9");41return true;42}43}44return false;45} ());46if (!Function.prototype.bind) {47Function.prototype.bind = function bind(that) {48
49var target = this;50var slice = [].slice;51
52if (typeof target != "function") {53throw new TypeError();54}55
56var args = slice.call(arguments, 1),57bound = function () {58
59if (this instanceof bound) {60
61var F = function(){};62F.prototype = target.prototype;63var self = new F();64
65var result = target.apply(66self,67args.concat(slice.call(arguments))68);69if (Object(result) === result) {70return result;71}72return self;73
74} else {75
76return target.apply(77that,78args.concat(slice.call(arguments))79);80
81}82
83};84
85return bound;86};87}88if (!Array.prototype.indexOf) {89Array.prototype.indexOf = function(searchElement, fromIndex) {90var k;91if (this == null) {92throw new TypeError('"this" is null or not defined');93}94var O = Object(this);95var len = O.length >>> 0;96if (len === 0) {97return -1;98}99var n = +fromIndex || 0;100if (Math.abs(n) === Infinity) {101n = 0;102}103if (n >= len) {104return -1;105}106k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);107while (k < len) {108if (k in O && O[k] === searchElement) {109return k;110}111k++;112}113return -1;114};115}116
117
118
119// =================================================================================================================120// Template121
122var base_html =123'<span class="irs">' +124'<span class="irs-line" tabindex="0"></span>' +125'<span class="irs-min">0</span><span class="irs-max">1</span>' +126'<span class="irs-from">0</span><span class="irs-to">0</span><span class="irs-single">0</span>' +127'</span>' +128'<span class="irs-grid"></span>';129
130var single_html =131'<span class="irs-bar irs-bar--single"></span>' +132'<span class="irs-shadow shadow-single"></span>' +133'<span class="irs-handle single"><i></i><i></i><i></i></span>';134
135var double_html =136'<span class="irs-bar"></span>' +137'<span class="irs-shadow shadow-from"></span>' +138'<span class="irs-shadow shadow-to"></span>' +139'<span class="irs-handle from"><i></i><i></i><i></i></span>' +140'<span class="irs-handle to"><i></i><i></i><i></i></span>';141
142var disable_html =143'<span class="irs-disable-mask"></span>';144
145
146
147// =================================================================================================================148// Core149
150/**151* Main plugin constructor
152*
153* @param input {Object} link to base input element
154* @param options {Object} slider config
155* @param plugin_count {Number}
156* @constructor
157*/
158var IonRangeSlider = function (input, options, plugin_count) {159this.VERSION = "2.3.1";160this.input = input;161this.plugin_count = plugin_count;162this.current_plugin = 0;163this.calc_count = 0;164this.update_tm = 0;165this.old_from = 0;166this.old_to = 0;167this.old_min_interval = null;168this.raf_id = null;169this.dragging = false;170this.force_redraw = false;171this.no_diapason = false;172this.has_tab_index = true;173this.is_key = false;174this.is_update = false;175this.is_start = true;176this.is_finish = false;177this.is_active = false;178this.is_resize = false;179this.is_click = false;180
181options = options || {};182
183// cache for links to all DOM elements184this.$cache = {185win: $(window),186body: $(document.body),187input: $(input),188cont: null,189rs: null,190min: null,191max: null,192from: null,193to: null,194single: null,195bar: null,196line: null,197s_single: null,198s_from: null,199s_to: null,200shad_single: null,201shad_from: null,202shad_to: null,203edge: null,204grid: null,205grid_labels: []206};207
208// storage for measure variables209this.coords = {210// left211x_gap: 0,212x_pointer: 0,213
214// width215w_rs: 0,216w_rs_old: 0,217w_handle: 0,218
219// percents220p_gap: 0,221p_gap_left: 0,222p_gap_right: 0,223p_step: 0,224p_pointer: 0,225p_handle: 0,226p_single_fake: 0,227p_single_real: 0,228p_from_fake: 0,229p_from_real: 0,230p_to_fake: 0,231p_to_real: 0,232p_bar_x: 0,233p_bar_w: 0,234
235// grid236grid_gap: 0,237big_num: 0,238big: [],239big_w: [],240big_p: [],241big_x: []242};243
244// storage for labels measure variables245this.labels = {246// width247w_min: 0,248w_max: 0,249w_from: 0,250w_to: 0,251w_single: 0,252
253// percents254p_min: 0,255p_max: 0,256p_from_fake: 0,257p_from_left: 0,258p_to_fake: 0,259p_to_left: 0,260p_single_fake: 0,261p_single_left: 0262};263
264
265
266/**267* get and validate config
268*/
269var $inp = this.$cache.input,270val = $inp.prop("value"),271config, config_from_data, prop;272
273// default config274config = {275skin: "flat",276type: "single",277
278min: 10,279max: 100,280from: null,281to: null,282step: 1,283
284min_interval: 0,285max_interval: 0,286drag_interval: false,287
288values: [],289p_values: [],290
291from_fixed: false,292from_min: null,293from_max: null,294from_shadow: false,295
296to_fixed: false,297to_min: null,298to_max: null,299to_shadow: false,300
301prettify_enabled: true,302prettify_separator: " ",303prettify: null,304
305force_edges: false,306
307keyboard: true,308
309grid: false,310grid_margin: true,311grid_num: 4,312grid_snap: false,313
314hide_min_max: false,315hide_from_to: false,316
317prefix: "",318postfix: "",319max_postfix: "",320decorate_both: true,321values_separator: " — ",322
323input_values_separator: ";",324
325disable: false,326block: false,327
328extra_classes: "",329
330scope: null,331onStart: null,332onChange: null,333onFinish: null,334onUpdate: null335};336
337
338// check if base element is input339if ($inp[0].nodeName !== "INPUT") {340console && console.warn && console.warn("Base element should be <input>!", $inp[0]);341}342
343
344// config from data-attributes extends js config345config_from_data = {346skin: $inp.data("skin"),347type: $inp.data("type"),348
349min: $inp.data("min"),350max: $inp.data("max"),351from: $inp.data("from"),352to: $inp.data("to"),353step: $inp.data("step"),354
355min_interval: $inp.data("minInterval"),356max_interval: $inp.data("maxInterval"),357drag_interval: $inp.data("dragInterval"),358
359values: $inp.data("values"),360
361from_fixed: $inp.data("fromFixed"),362from_min: $inp.data("fromMin"),363from_max: $inp.data("fromMax"),364from_shadow: $inp.data("fromShadow"),365
366to_fixed: $inp.data("toFixed"),367to_min: $inp.data("toMin"),368to_max: $inp.data("toMax"),369to_shadow: $inp.data("toShadow"),370
371prettify_enabled: $inp.data("prettifyEnabled"),372prettify_separator: $inp.data("prettifySeparator"),373
374force_edges: $inp.data("forceEdges"),375
376keyboard: $inp.data("keyboard"),377
378grid: $inp.data("grid"),379grid_margin: $inp.data("gridMargin"),380grid_num: $inp.data("gridNum"),381grid_snap: $inp.data("gridSnap"),382
383hide_min_max: $inp.data("hideMinMax"),384hide_from_to: $inp.data("hideFromTo"),385
386prefix: $inp.data("prefix"),387postfix: $inp.data("postfix"),388max_postfix: $inp.data("maxPostfix"),389decorate_both: $inp.data("decorateBoth"),390values_separator: $inp.data("valuesSeparator"),391
392input_values_separator: $inp.data("inputValuesSeparator"),393
394disable: $inp.data("disable"),395block: $inp.data("block"),396
397extra_classes: $inp.data("extraClasses"),398};399config_from_data.values = config_from_data.values && config_from_data.values.split(",");400
401for (prop in config_from_data) {402if (config_from_data.hasOwnProperty(prop)) {403if (config_from_data[prop] === undefined || config_from_data[prop] === "") {404delete config_from_data[prop];405}406}407}408
409
410// input value extends default config411if (val !== undefined && val !== "") {412val = val.split(config_from_data.input_values_separator || options.input_values_separator || ";");413
414if (val[0] && val[0] == +val[0]) {415val[0] = +val[0];416}417if (val[1] && val[1] == +val[1]) {418val[1] = +val[1];419}420
421if (options && options.values && options.values.length) {422config.from = val[0] && options.values.indexOf(val[0]);423config.to = val[1] && options.values.indexOf(val[1]);424} else {425config.from = val[0] && +val[0];426config.to = val[1] && +val[1];427}428}429
430
431
432// js config extends default config433$.extend(config, options);434
435
436// data config extends config437$.extend(config, config_from_data);438this.options = config;439
440
441
442// validate config, to be sure that all data types are correct443this.update_check = {};444this.validate();445
446
447
448// default result object, returned to callbacks449this.result = {450input: this.$cache.input,451slider: null,452
453min: this.options.min,454max: this.options.max,455
456from: this.options.from,457from_percent: 0,458from_value: null,459
460to: this.options.to,461to_percent: 0,462to_value: null463};464
465
466
467this.init();468};469
470IonRangeSlider.prototype = {471
472/**473* Starts or updates the plugin instance
474*
475* @param [is_update] {boolean}
476*/
477init: function (is_update) {478this.no_diapason = false;479this.coords.p_step = this.convertToPercent(this.options.step, true);480
481this.target = "base";482
483this.toggleInput();484this.append();485this.setMinMax();486
487if (is_update) {488this.force_redraw = true;489this.calc(true);490
491// callbacks called492this.callOnUpdate();493} else {494this.force_redraw = true;495this.calc(true);496
497// callbacks called498this.callOnStart();499}500
501this.updateScene();502},503
504/**505* Appends slider template to a DOM
506*/
507append: function () {508var container_html = '<span class="irs irs--' + this.options.skin + ' js-irs-' + this.plugin_count + ' ' + this.options.extra_classes + '"></span>';509this.$cache.input.before(container_html);510this.$cache.input.prop("readonly", true);511this.$cache.cont = this.$cache.input.prev();512this.result.slider = this.$cache.cont;513
514this.$cache.cont.html(base_html);515this.$cache.rs = this.$cache.cont.find(".irs");516this.$cache.min = this.$cache.cont.find(".irs-min");517this.$cache.max = this.$cache.cont.find(".irs-max");518this.$cache.from = this.$cache.cont.find(".irs-from");519this.$cache.to = this.$cache.cont.find(".irs-to");520this.$cache.single = this.$cache.cont.find(".irs-single");521this.$cache.line = this.$cache.cont.find(".irs-line");522this.$cache.grid = this.$cache.cont.find(".irs-grid");523
524if (this.options.type === "single") {525this.$cache.cont.append(single_html);526this.$cache.bar = this.$cache.cont.find(".irs-bar");527this.$cache.edge = this.$cache.cont.find(".irs-bar-edge");528this.$cache.s_single = this.$cache.cont.find(".single");529this.$cache.from[0].style.visibility = "hidden";530this.$cache.to[0].style.visibility = "hidden";531this.$cache.shad_single = this.$cache.cont.find(".shadow-single");532} else {533this.$cache.cont.append(double_html);534this.$cache.bar = this.$cache.cont.find(".irs-bar");535this.$cache.s_from = this.$cache.cont.find(".from");536this.$cache.s_to = this.$cache.cont.find(".to");537this.$cache.shad_from = this.$cache.cont.find(".shadow-from");538this.$cache.shad_to = this.$cache.cont.find(".shadow-to");539
540this.setTopHandler();541}542
543if (this.options.hide_from_to) {544this.$cache.from[0].style.display = "none";545this.$cache.to[0].style.display = "none";546this.$cache.single[0].style.display = "none";547}548
549this.appendGrid();550
551if (this.options.disable) {552this.appendDisableMask();553this.$cache.input[0].disabled = true;554} else {555this.$cache.input[0].disabled = false;556this.removeDisableMask();557this.bindEvents();558}559
560// block only if not disabled561if (!this.options.disable) {562if (this.options.block) {563this.appendDisableMask();564} else {565this.removeDisableMask();566}567}568
569if (this.options.drag_interval) {570this.$cache.bar[0].style.cursor = "ew-resize";571}572},573
574/**575* Determine which handler has a priority
576* works only for double slider type
577*/
578setTopHandler: function () {579var min = this.options.min,580max = this.options.max,581from = this.options.from,582to = this.options.to;583
584if (from > min && to === max) {585this.$cache.s_from.addClass("type_last");586} else if (to < max) {587this.$cache.s_to.addClass("type_last");588}589},590
591/**592* Determine which handles was clicked last
593* and which handler should have hover effect
594*
595* @param target {String}
596*/
597changeLevel: function (target) {598switch (target) {599case "single":600this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_single_fake);601this.$cache.s_single.addClass("state_hover");602break;603case "from":604this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_from_fake);605this.$cache.s_from.addClass("state_hover");606this.$cache.s_from.addClass("type_last");607this.$cache.s_to.removeClass("type_last");608break;609case "to":610this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_to_fake);611this.$cache.s_to.addClass("state_hover");612this.$cache.s_to.addClass("type_last");613this.$cache.s_from.removeClass("type_last");614break;615case "both":616this.coords.p_gap_left = this.toFixed(this.coords.p_pointer - this.coords.p_from_fake);617this.coords.p_gap_right = this.toFixed(this.coords.p_to_fake - this.coords.p_pointer);618this.$cache.s_to.removeClass("type_last");619this.$cache.s_from.removeClass("type_last");620break;621}622},623
624/**625* Then slider is disabled
626* appends extra layer with opacity
627*/
628appendDisableMask: function () {629this.$cache.cont.append(disable_html);630this.$cache.cont.addClass("irs-disabled");631},632
633/**634* Then slider is not disabled
635* remove disable mask
636*/
637removeDisableMask: function () {638this.$cache.cont.remove(".irs-disable-mask");639this.$cache.cont.removeClass("irs-disabled");640},641
642/**643* Remove slider instance
644* and unbind all events
645*/
646remove: function () {647this.$cache.cont.remove();648this.$cache.cont = null;649
650this.$cache.line.off("keydown.irs_" + this.plugin_count);651
652this.$cache.body.off("touchmove.irs_" + this.plugin_count);653this.$cache.body.off("mousemove.irs_" + this.plugin_count);654
655this.$cache.win.off("touchend.irs_" + this.plugin_count);656this.$cache.win.off("mouseup.irs_" + this.plugin_count);657
658if (is_old_ie) {659this.$cache.body.off("mouseup.irs_" + this.plugin_count);660this.$cache.body.off("mouseleave.irs_" + this.plugin_count);661}662
663this.$cache.grid_labels = [];664this.coords.big = [];665this.coords.big_w = [];666this.coords.big_p = [];667this.coords.big_x = [];668
669cancelAnimationFrame(this.raf_id);670},671
672/**673* bind all slider events
674*/
675bindEvents: function () {676if (this.no_diapason) {677return;678}679
680this.$cache.body.on("touchmove.irs_" + this.plugin_count, this.pointerMove.bind(this));681this.$cache.body.on("mousemove.irs_" + this.plugin_count, this.pointerMove.bind(this));682
683this.$cache.win.on("touchend.irs_" + this.plugin_count, this.pointerUp.bind(this));684this.$cache.win.on("mouseup.irs_" + this.plugin_count, this.pointerUp.bind(this));685
686this.$cache.line.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));687this.$cache.line.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));688
689this.$cache.line.on("focus.irs_" + this.plugin_count, this.pointerFocus.bind(this));690
691if (this.options.drag_interval && this.options.type === "double") {692this.$cache.bar.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "both"));693this.$cache.bar.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "both"));694} else {695this.$cache.bar.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));696this.$cache.bar.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));697}698
699if (this.options.type === "single") {700this.$cache.single.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));701this.$cache.s_single.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));702this.$cache.shad_single.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));703
704this.$cache.single.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));705this.$cache.s_single.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));706this.$cache.edge.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));707this.$cache.shad_single.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));708} else {709this.$cache.single.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, null));710this.$cache.single.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, null));711
712this.$cache.from.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));713this.$cache.s_from.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));714this.$cache.to.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));715this.$cache.s_to.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));716this.$cache.shad_from.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));717this.$cache.shad_to.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));718
719this.$cache.from.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));720this.$cache.s_from.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));721this.$cache.to.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));722this.$cache.s_to.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));723this.$cache.shad_from.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));724this.$cache.shad_to.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));725}726
727if (this.options.keyboard) {728this.$cache.line.on("keydown.irs_" + this.plugin_count, this.key.bind(this, "keyboard"));729}730
731if (is_old_ie) {732this.$cache.body.on("mouseup.irs_" + this.plugin_count, this.pointerUp.bind(this));733this.$cache.body.on("mouseleave.irs_" + this.plugin_count, this.pointerUp.bind(this));734}735},736
737/**738* Focus with tabIndex
739*
740* @param e {Object} event object
741*/
742pointerFocus: function (e) {743if (!this.target) {744var x;745var $handle;746
747if (this.options.type === "single") {748$handle = this.$cache.single;749} else {750$handle = this.$cache.from;751}752
753x = $handle.offset().left;754x += ($handle.width() / 2) - 1;755
756this.pointerClick("single", {preventDefault: function () {}, pageX: x});757}758},759
760/**761* Mousemove or touchmove
762* only for handlers
763*
764* @param e {Object} event object
765*/
766pointerMove: function (e) {767if (!this.dragging) {768return;769}770
771var x = e.pageX || e.originalEvent.touches && e.originalEvent.touches[0].pageX;772this.coords.x_pointer = x - this.coords.x_gap;773
774this.calc();775},776
777/**778* Mouseup or touchend
779* only for handlers
780*
781* @param e {Object} event object
782*/
783pointerUp: function (e) {784if (this.current_plugin !== this.plugin_count) {785return;786}787
788if (this.is_active) {789this.is_active = false;790} else {791return;792}793
794this.$cache.cont.find(".state_hover").removeClass("state_hover");795
796this.force_redraw = true;797
798if (is_old_ie) {799$("*").prop("unselectable", false);800}801
802this.updateScene();803this.restoreOriginalMinInterval();804
805// callbacks call806if ($.contains(this.$cache.cont[0], e.target) || this.dragging) {807this.callOnFinish();808}809
810this.dragging = false;811},812
813/**814* Mousedown or touchstart
815* only for handlers
816*
817* @param target {String|null}
818* @param e {Object} event object
819*/
820pointerDown: function (target, e) {821e.preventDefault();822var x = e.pageX || e.originalEvent.touches && e.originalEvent.touches[0].pageX;823if (e.button === 2) {824return;825}826
827if (target === "both") {828this.setTempMinInterval();829}830
831if (!target) {832target = this.target || "from";833}834
835this.current_plugin = this.plugin_count;836this.target = target;837
838this.is_active = true;839this.dragging = true;840
841this.coords.x_gap = this.$cache.rs.offset().left;842this.coords.x_pointer = x - this.coords.x_gap;843
844this.calcPointerPercent();845this.changeLevel(target);846
847if (is_old_ie) {848$("*").prop("unselectable", true);849}850
851this.$cache.line.trigger("focus");852
853this.updateScene();854},855
856/**857* Mousedown or touchstart
858* for other slider elements, like diapason line
859*
860* @param target {String}
861* @param e {Object} event object
862*/
863pointerClick: function (target, e) {864e.preventDefault();865var x = e.pageX || e.originalEvent.touches && e.originalEvent.touches[0].pageX;866if (e.button === 2) {867return;868}869
870this.current_plugin = this.plugin_count;871this.target = target;872
873this.is_click = true;874this.coords.x_gap = this.$cache.rs.offset().left;875this.coords.x_pointer = +(x - this.coords.x_gap).toFixed();876
877this.force_redraw = true;878this.calc();879
880this.$cache.line.trigger("focus");881},882
883/**884* Keyborard controls for focused slider
885*
886* @param target {String}
887* @param e {Object} event object
888* @returns {boolean|undefined}
889*/
890key: function (target, e) {891if (this.current_plugin !== this.plugin_count || e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {892return;893}894
895switch (e.which) {896case 83: // W897case 65: // A898case 40: // DOWN899case 37: // LEFT900e.preventDefault();901this.moveByKey(false);902break;903
904case 87: // S905case 68: // D906case 38: // UP907case 39: // RIGHT908e.preventDefault();909this.moveByKey(true);910break;911}912
913return true;914},915
916/**917* Move by key
918*
919* @param right {boolean} direction to move
920*/
921moveByKey: function (right) {922var p = this.coords.p_pointer;923var p_step = (this.options.max - this.options.min) / 100;924p_step = this.options.step / p_step;925
926if (right) {927p += p_step;928} else {929p -= p_step;930}931
932this.coords.x_pointer = this.toFixed(this.coords.w_rs / 100 * p);933this.is_key = true;934this.calc();935},936
937/**938* Set visibility and content
939* of Min and Max labels
940*/
941setMinMax: function () {942if (!this.options) {943return;944}945
946if (this.options.hide_min_max) {947this.$cache.min[0].style.display = "none";948this.$cache.max[0].style.display = "none";949return;950}951
952if (this.options.values.length) {953this.$cache.min.html(this.decorate(this.options.p_values[this.options.min]));954this.$cache.max.html(this.decorate(this.options.p_values[this.options.max]));955} else {956var min_pretty = this._prettify(this.options.min);957var max_pretty = this._prettify(this.options.max);958
959this.result.min_pretty = min_pretty;960this.result.max_pretty = max_pretty;961
962this.$cache.min.html(this.decorate(min_pretty, this.options.min));963this.$cache.max.html(this.decorate(max_pretty, this.options.max));964}965
966this.labels.w_min = this.$cache.min.outerWidth(false);967this.labels.w_max = this.$cache.max.outerWidth(false);968},969
970/**971* Then dragging interval, prevent interval collapsing
972* using min_interval option
973*/
974setTempMinInterval: function () {975var interval = this.result.to - this.result.from;976
977if (this.old_min_interval === null) {978this.old_min_interval = this.options.min_interval;979}980
981this.options.min_interval = interval;982},983
984/**985* Restore min_interval option to original
986*/
987restoreOriginalMinInterval: function () {988if (this.old_min_interval !== null) {989this.options.min_interval = this.old_min_interval;990this.old_min_interval = null;991}992},993
994
995
996// =============================================================================================================997// Calculations998
999/**1000* All calculations and measures start here
1001*
1002* @param update {boolean=}
1003*/
1004calc: function (update) {1005if (!this.options) {1006return;1007}1008
1009this.calc_count++;1010
1011if (this.calc_count === 10 || update) {1012this.calc_count = 0;1013this.coords.w_rs = this.$cache.rs.outerWidth(false);1014
1015this.calcHandlePercent();1016}1017
1018if (!this.coords.w_rs) {1019return;1020}1021
1022this.calcPointerPercent();1023var handle_x = this.getHandleX();1024
1025
1026if (this.target === "both") {1027this.coords.p_gap = 0;1028handle_x = this.getHandleX();1029}1030
1031if (this.target === "click") {1032this.coords.p_gap = this.coords.p_handle / 2;1033handle_x = this.getHandleX();1034
1035if (this.options.drag_interval) {1036this.target = "both_one";1037} else {1038this.target = this.chooseHandle(handle_x);1039}1040}1041
1042switch (this.target) {1043case "base":1044var w = (this.options.max - this.options.min) / 100,1045f = (this.result.from - this.options.min) / w,1046t = (this.result.to - this.options.min) / w;1047
1048this.coords.p_single_real = this.toFixed(f);1049this.coords.p_from_real = this.toFixed(f);1050this.coords.p_to_real = this.toFixed(t);1051
1052this.coords.p_single_real = this.checkDiapason(this.coords.p_single_real, this.options.from_min, this.options.from_max);1053this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);1054this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);1055
1056this.coords.p_single_fake = this.convertToFakePercent(this.coords.p_single_real);1057this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real);1058this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real);1059
1060this.target = null;1061
1062break;1063
1064case "single":1065if (this.options.from_fixed) {1066break;1067}1068
1069this.coords.p_single_real = this.convertToRealPercent(handle_x);1070this.coords.p_single_real = this.calcWithStep(this.coords.p_single_real);1071this.coords.p_single_real = this.checkDiapason(this.coords.p_single_real, this.options.from_min, this.options.from_max);1072
1073this.coords.p_single_fake = this.convertToFakePercent(this.coords.p_single_real);1074
1075break;1076
1077case "from":1078if (this.options.from_fixed) {1079break;1080}1081
1082this.coords.p_from_real = this.convertToRealPercent(handle_x);1083this.coords.p_from_real = this.calcWithStep(this.coords.p_from_real);1084if (this.coords.p_from_real > this.coords.p_to_real) {1085this.coords.p_from_real = this.coords.p_to_real;1086}1087this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);1088this.coords.p_from_real = this.checkMinInterval(this.coords.p_from_real, this.coords.p_to_real, "from");1089this.coords.p_from_real = this.checkMaxInterval(this.coords.p_from_real, this.coords.p_to_real, "from");1090
1091this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real);1092
1093break;1094
1095case "to":1096if (this.options.to_fixed) {1097break;1098}1099
1100this.coords.p_to_real = this.convertToRealPercent(handle_x);1101this.coords.p_to_real = this.calcWithStep(this.coords.p_to_real);1102if (this.coords.p_to_real < this.coords.p_from_real) {1103this.coords.p_to_real = this.coords.p_from_real;1104}1105this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);1106this.coords.p_to_real = this.checkMinInterval(this.coords.p_to_real, this.coords.p_from_real, "to");1107this.coords.p_to_real = this.checkMaxInterval(this.coords.p_to_real, this.coords.p_from_real, "to");1108
1109this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real);1110
1111break;1112
1113case "both":1114if (this.options.from_fixed || this.options.to_fixed) {1115break;1116}1117
1118handle_x = this.toFixed(handle_x + (this.coords.p_handle * 0.001));1119
1120this.coords.p_from_real = this.convertToRealPercent(handle_x) - this.coords.p_gap_left;1121this.coords.p_from_real = this.calcWithStep(this.coords.p_from_real);1122this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);1123this.coords.p_from_real = this.checkMinInterval(this.coords.p_from_real, this.coords.p_to_real, "from");1124this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real);1125
1126this.coords.p_to_real = this.convertToRealPercent(handle_x) + this.coords.p_gap_right;1127this.coords.p_to_real = this.calcWithStep(this.coords.p_to_real);1128this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);1129this.coords.p_to_real = this.checkMinInterval(this.coords.p_to_real, this.coords.p_from_real, "to");1130this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real);1131
1132break;1133
1134case "both_one":1135if (this.options.from_fixed || this.options.to_fixed) {1136break;1137}1138
1139var real_x = this.convertToRealPercent(handle_x),1140from = this.result.from_percent,1141to = this.result.to_percent,1142full = to - from,1143half = full / 2,1144new_from = real_x - half,1145new_to = real_x + half;1146
1147if (new_from < 0) {1148new_from = 0;1149new_to = new_from + full;1150}1151
1152if (new_to > 100) {1153new_to = 100;1154new_from = new_to - full;1155}1156
1157this.coords.p_from_real = this.calcWithStep(new_from);1158this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);1159this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real);1160
1161this.coords.p_to_real = this.calcWithStep(new_to);1162this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);1163this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real);1164
1165break;1166}1167
1168if (this.options.type === "single") {1169this.coords.p_bar_x = (this.coords.p_handle / 2);1170this.coords.p_bar_w = this.coords.p_single_fake;1171
1172this.result.from_percent = this.coords.p_single_real;1173this.result.from = this.convertToValue(this.coords.p_single_real);1174this.result.from_pretty = this._prettify(this.result.from);1175
1176if (this.options.values.length) {1177this.result.from_value = this.options.values[this.result.from];1178}1179} else {1180this.coords.p_bar_x = this.toFixed(this.coords.p_from_fake + (this.coords.p_handle / 2));1181this.coords.p_bar_w = this.toFixed(this.coords.p_to_fake - this.coords.p_from_fake);1182
1183this.result.from_percent = this.coords.p_from_real;1184this.result.from = this.convertToValue(this.coords.p_from_real);1185this.result.from_pretty = this._prettify(this.result.from);1186this.result.to_percent = this.coords.p_to_real;1187this.result.to = this.convertToValue(this.coords.p_to_real);1188this.result.to_pretty = this._prettify(this.result.to);1189
1190if (this.options.values.length) {1191this.result.from_value = this.options.values[this.result.from];1192this.result.to_value = this.options.values[this.result.to];1193}1194}1195
1196this.calcMinMax();1197this.calcLabels();1198},1199
1200
1201/**1202* calculates pointer X in percent
1203*/
1204calcPointerPercent: function () {1205if (!this.coords.w_rs) {1206this.coords.p_pointer = 0;1207return;1208}1209
1210if (this.coords.x_pointer < 0 || isNaN(this.coords.x_pointer) ) {1211this.coords.x_pointer = 0;1212} else if (this.coords.x_pointer > this.coords.w_rs) {1213this.coords.x_pointer = this.coords.w_rs;1214}1215
1216this.coords.p_pointer = this.toFixed(this.coords.x_pointer / this.coords.w_rs * 100);1217},1218
1219convertToRealPercent: function (fake) {1220var full = 100 - this.coords.p_handle;1221return fake / full * 100;1222},1223
1224convertToFakePercent: function (real) {1225var full = 100 - this.coords.p_handle;1226return real / 100 * full;1227},1228
1229getHandleX: function () {1230var max = 100 - this.coords.p_handle,1231x = this.toFixed(this.coords.p_pointer - this.coords.p_gap);1232
1233if (x < 0) {1234x = 0;1235} else if (x > max) {1236x = max;1237}1238
1239return x;1240},1241
1242calcHandlePercent: function () {1243if (this.options.type === "single") {1244this.coords.w_handle = this.$cache.s_single.outerWidth(false);1245} else {1246this.coords.w_handle = this.$cache.s_from.outerWidth(false);1247}1248
1249this.coords.p_handle = this.toFixed(this.coords.w_handle / this.coords.w_rs * 100);1250},1251
1252/**1253* Find closest handle to pointer click
1254*
1255* @param real_x {Number}
1256* @returns {String}
1257*/
1258chooseHandle: function (real_x) {1259if (this.options.type === "single") {1260return "single";1261} else {1262var m_point = this.coords.p_from_real + ((this.coords.p_to_real - this.coords.p_from_real) / 2);1263if (real_x >= m_point) {1264return this.options.to_fixed ? "from" : "to";1265} else {1266return this.options.from_fixed ? "to" : "from";1267}1268}1269},1270
1271/**1272* Measure Min and Max labels width in percent
1273*/
1274calcMinMax: function () {1275if (!this.coords.w_rs) {1276return;1277}1278
1279this.labels.p_min = this.labels.w_min / this.coords.w_rs * 100;1280this.labels.p_max = this.labels.w_max / this.coords.w_rs * 100;1281},1282
1283/**1284* Measure labels width and X in percent
1285*/
1286calcLabels: function () {1287if (!this.coords.w_rs || this.options.hide_from_to) {1288return;1289}1290
1291if (this.options.type === "single") {1292
1293this.labels.w_single = this.$cache.single.outerWidth(false);1294this.labels.p_single_fake = this.labels.w_single / this.coords.w_rs * 100;1295this.labels.p_single_left = this.coords.p_single_fake + (this.coords.p_handle / 2) - (this.labels.p_single_fake / 2);1296this.labels.p_single_left = this.checkEdges(this.labels.p_single_left, this.labels.p_single_fake);1297
1298} else {1299
1300this.labels.w_from = this.$cache.from.outerWidth(false);1301this.labels.p_from_fake = this.labels.w_from / this.coords.w_rs * 100;1302this.labels.p_from_left = this.coords.p_from_fake + (this.coords.p_handle / 2) - (this.labels.p_from_fake / 2);1303this.labels.p_from_left = this.toFixed(this.labels.p_from_left);1304this.labels.p_from_left = this.checkEdges(this.labels.p_from_left, this.labels.p_from_fake);1305
1306this.labels.w_to = this.$cache.to.outerWidth(false);1307this.labels.p_to_fake = this.labels.w_to / this.coords.w_rs * 100;1308this.labels.p_to_left = this.coords.p_to_fake + (this.coords.p_handle / 2) - (this.labels.p_to_fake / 2);1309this.labels.p_to_left = this.toFixed(this.labels.p_to_left);1310this.labels.p_to_left = this.checkEdges(this.labels.p_to_left, this.labels.p_to_fake);1311
1312this.labels.w_single = this.$cache.single.outerWidth(false);1313this.labels.p_single_fake = this.labels.w_single / this.coords.w_rs * 100;1314this.labels.p_single_left = ((this.labels.p_from_left + this.labels.p_to_left + this.labels.p_to_fake) / 2) - (this.labels.p_single_fake / 2);1315this.labels.p_single_left = this.toFixed(this.labels.p_single_left);1316this.labels.p_single_left = this.checkEdges(this.labels.p_single_left, this.labels.p_single_fake);1317
1318}1319},1320
1321
1322
1323// =============================================================================================================1324// Drawings1325
1326/**1327* Main function called in request animation frame
1328* to update everything
1329*/
1330updateScene: function () {1331if (this.raf_id) {1332cancelAnimationFrame(this.raf_id);1333this.raf_id = null;1334}1335
1336clearTimeout(this.update_tm);1337this.update_tm = null;1338
1339if (!this.options) {1340return;1341}1342
1343this.drawHandles();1344
1345if (this.is_active) {1346this.raf_id = requestAnimationFrame(this.updateScene.bind(this));1347} else {1348this.update_tm = setTimeout(this.updateScene.bind(this), 300);1349}1350},1351
1352/**1353* Draw handles
1354*/
1355drawHandles: function () {1356this.coords.w_rs = this.$cache.rs.outerWidth(false);1357
1358if (!this.coords.w_rs) {1359return;1360}1361
1362if (this.coords.w_rs !== this.coords.w_rs_old) {1363this.target = "base";1364this.is_resize = true;1365}1366
1367if (this.coords.w_rs !== this.coords.w_rs_old || this.force_redraw) {1368this.setMinMax();1369this.calc(true);1370this.drawLabels();1371if (this.options.grid) {1372this.calcGridMargin();1373this.calcGridLabels();1374}1375this.force_redraw = true;1376this.coords.w_rs_old = this.coords.w_rs;1377this.drawShadow();1378}1379
1380if (!this.coords.w_rs) {1381return;1382}1383
1384if (!this.dragging && !this.force_redraw && !this.is_key) {1385return;1386}1387
1388if (this.old_from !== this.result.from || this.old_to !== this.result.to || this.force_redraw || this.is_key) {1389
1390this.drawLabels();1391
1392this.$cache.bar[0].style.left = this.coords.p_bar_x + "%";1393this.$cache.bar[0].style.width = this.coords.p_bar_w + "%";1394
1395if (this.options.type === "single") {1396this.$cache.bar[0].style.left = 0;1397this.$cache.bar[0].style.width = this.coords.p_bar_w + this.coords.p_bar_x + "%";1398
1399this.$cache.s_single[0].style.left = this.coords.p_single_fake + "%";1400
1401this.$cache.single[0].style.left = this.labels.p_single_left + "%";1402} else {1403this.$cache.s_from[0].style.left = this.coords.p_from_fake + "%";1404this.$cache.s_to[0].style.left = this.coords.p_to_fake + "%";1405
1406if (this.old_from !== this.result.from || this.force_redraw) {1407this.$cache.from[0].style.left = this.labels.p_from_left + "%";1408}1409if (this.old_to !== this.result.to || this.force_redraw) {1410this.$cache.to[0].style.left = this.labels.p_to_left + "%";1411}1412
1413this.$cache.single[0].style.left = this.labels.p_single_left + "%";1414}1415
1416this.writeToInput();1417
1418if ((this.old_from !== this.result.from || this.old_to !== this.result.to) && !this.is_start) {1419this.$cache.input.trigger("change");1420this.$cache.input.trigger("input");1421}1422
1423this.old_from = this.result.from;1424this.old_to = this.result.to;1425
1426// callbacks call1427if (!this.is_resize && !this.is_update && !this.is_start && !this.is_finish) {1428this.callOnChange();1429}1430if (this.is_key || this.is_click) {1431this.is_key = false;1432this.is_click = false;1433this.callOnFinish();1434}1435
1436this.is_update = false;1437this.is_resize = false;1438this.is_finish = false;1439}1440
1441this.is_start = false;1442this.is_key = false;1443this.is_click = false;1444this.force_redraw = false;1445},1446
1447/**1448* Draw labels
1449* measure labels collisions
1450* collapse close labels
1451*/
1452drawLabels: function () {1453if (!this.options) {1454return;1455}1456
1457var values_num = this.options.values.length;1458var p_values = this.options.p_values;1459var text_single;1460var text_from;1461var text_to;1462var from_pretty;1463var to_pretty;1464
1465if (this.options.hide_from_to) {1466return;1467}1468
1469if (this.options.type === "single") {1470
1471if (values_num) {1472text_single = this.decorate(p_values[this.result.from]);1473this.$cache.single.html(text_single);1474} else {1475from_pretty = this._prettify(this.result.from);1476
1477text_single = this.decorate(from_pretty, this.result.from);1478this.$cache.single.html(text_single);1479}1480
1481this.calcLabels();1482
1483if (this.labels.p_single_left < this.labels.p_min + 1) {1484this.$cache.min[0].style.visibility = "hidden";1485} else {1486this.$cache.min[0].style.visibility = "visible";1487}1488
1489if (this.labels.p_single_left + this.labels.p_single_fake > 100 - this.labels.p_max - 1) {1490this.$cache.max[0].style.visibility = "hidden";1491} else {1492this.$cache.max[0].style.visibility = "visible";1493}1494
1495} else {1496
1497if (values_num) {1498
1499if (this.options.decorate_both) {1500text_single = this.decorate(p_values[this.result.from]);1501text_single += this.options.values_separator;1502text_single += this.decorate(p_values[this.result.to]);1503} else {1504text_single = this.decorate(p_values[this.result.from] + this.options.values_separator + p_values[this.result.to]);1505}1506text_from = this.decorate(p_values[this.result.from]);1507text_to = this.decorate(p_values[this.result.to]);1508
1509this.$cache.single.html(text_single);1510this.$cache.from.html(text_from);1511this.$cache.to.html(text_to);1512
1513} else {1514from_pretty = this._prettify(this.result.from);1515to_pretty = this._prettify(this.result.to);1516
1517if (this.options.decorate_both) {1518text_single = this.decorate(from_pretty, this.result.from);1519text_single += this.options.values_separator;1520text_single += this.decorate(to_pretty, this.result.to);1521} else {1522text_single = this.decorate(from_pretty + this.options.values_separator + to_pretty, this.result.to);1523}1524text_from = this.decorate(from_pretty, this.result.from);1525text_to = this.decorate(to_pretty, this.result.to);1526
1527this.$cache.single.html(text_single);1528this.$cache.from.html(text_from);1529this.$cache.to.html(text_to);1530
1531}1532
1533this.calcLabels();1534
1535var min = Math.min(this.labels.p_single_left, this.labels.p_from_left),1536single_left = this.labels.p_single_left + this.labels.p_single_fake,1537to_left = this.labels.p_to_left + this.labels.p_to_fake,1538max = Math.max(single_left, to_left);1539
1540if (this.labels.p_from_left + this.labels.p_from_fake >= this.labels.p_to_left) {1541this.$cache.from[0].style.visibility = "hidden";1542this.$cache.to[0].style.visibility = "hidden";1543this.$cache.single[0].style.visibility = "visible";1544
1545if (this.result.from === this.result.to) {1546if (this.target === "from") {1547this.$cache.from[0].style.visibility = "visible";1548} else if (this.target === "to") {1549this.$cache.to[0].style.visibility = "visible";1550} else if (!this.target) {1551this.$cache.from[0].style.visibility = "visible";1552}1553this.$cache.single[0].style.visibility = "hidden";1554max = to_left;1555} else {1556this.$cache.from[0].style.visibility = "hidden";1557this.$cache.to[0].style.visibility = "hidden";1558this.$cache.single[0].style.visibility = "visible";1559max = Math.max(single_left, to_left);1560}1561} else {1562this.$cache.from[0].style.visibility = "visible";1563this.$cache.to[0].style.visibility = "visible";1564this.$cache.single[0].style.visibility = "hidden";1565}1566
1567if (min < this.labels.p_min + 1) {1568this.$cache.min[0].style.visibility = "hidden";1569} else {1570this.$cache.min[0].style.visibility = "visible";1571}1572
1573if (max > 100 - this.labels.p_max - 1) {1574this.$cache.max[0].style.visibility = "hidden";1575} else {1576this.$cache.max[0].style.visibility = "visible";1577}1578
1579}1580},1581
1582/**1583* Draw shadow intervals
1584*/
1585drawShadow: function () {1586var o = this.options,1587c = this.$cache,1588
1589is_from_min = typeof o.from_min === "number" && !isNaN(o.from_min),1590is_from_max = typeof o.from_max === "number" && !isNaN(o.from_max),1591is_to_min = typeof o.to_min === "number" && !isNaN(o.to_min),1592is_to_max = typeof o.to_max === "number" && !isNaN(o.to_max),1593
1594from_min,1595from_max,1596to_min,1597to_max;1598
1599if (o.type === "single") {1600if (o.from_shadow && (is_from_min || is_from_max)) {1601from_min = this.convertToPercent(is_from_min ? o.from_min : o.min);1602from_max = this.convertToPercent(is_from_max ? o.from_max : o.max) - from_min;1603from_min = this.toFixed(from_min - (this.coords.p_handle / 100 * from_min));1604from_max = this.toFixed(from_max - (this.coords.p_handle / 100 * from_max));1605from_min = from_min + (this.coords.p_handle / 2);1606
1607c.shad_single[0].style.display = "block";1608c.shad_single[0].style.left = from_min + "%";1609c.shad_single[0].style.width = from_max + "%";1610} else {1611c.shad_single[0].style.display = "none";1612}1613} else {1614if (o.from_shadow && (is_from_min || is_from_max)) {1615from_min = this.convertToPercent(is_from_min ? o.from_min : o.min);1616from_max = this.convertToPercent(is_from_max ? o.from_max : o.max) - from_min;1617from_min = this.toFixed(from_min - (this.coords.p_handle / 100 * from_min));1618from_max = this.toFixed(from_max - (this.coords.p_handle / 100 * from_max));1619from_min = from_min + (this.coords.p_handle / 2);1620
1621c.shad_from[0].style.display = "block";1622c.shad_from[0].style.left = from_min + "%";1623c.shad_from[0].style.width = from_max + "%";1624} else {1625c.shad_from[0].style.display = "none";1626}1627
1628if (o.to_shadow && (is_to_min || is_to_max)) {1629to_min = this.convertToPercent(is_to_min ? o.to_min : o.min);1630to_max = this.convertToPercent(is_to_max ? o.to_max : o.max) - to_min;1631to_min = this.toFixed(to_min - (this.coords.p_handle / 100 * to_min));1632to_max = this.toFixed(to_max - (this.coords.p_handle / 100 * to_max));1633to_min = to_min + (this.coords.p_handle / 2);1634
1635c.shad_to[0].style.display = "block";1636c.shad_to[0].style.left = to_min + "%";1637c.shad_to[0].style.width = to_max + "%";1638} else {1639c.shad_to[0].style.display = "none";1640}1641}1642},1643
1644
1645
1646/**1647* Write values to input element
1648*/
1649writeToInput: function () {1650if (this.options.type === "single") {1651if (this.options.values.length) {1652this.$cache.input.prop("value", this.result.from_value);1653} else {1654this.$cache.input.prop("value", this.result.from);1655}1656this.$cache.input.data("from", this.result.from);1657} else {1658if (this.options.values.length) {1659this.$cache.input.prop("value", this.result.from_value + this.options.input_values_separator + this.result.to_value);1660} else {1661this.$cache.input.prop("value", this.result.from + this.options.input_values_separator + this.result.to);1662}1663this.$cache.input.data("from", this.result.from);1664this.$cache.input.data("to", this.result.to);1665}1666},1667
1668
1669
1670// =============================================================================================================1671// Callbacks1672
1673callOnStart: function () {1674this.writeToInput();1675
1676if (this.options.onStart && typeof this.options.onStart === "function") {1677if (this.options.scope) {1678this.options.onStart.call(this.options.scope, this.result);1679} else {1680this.options.onStart(this.result);1681}1682}1683},1684callOnChange: function () {1685this.writeToInput();1686
1687if (this.options.onChange && typeof this.options.onChange === "function") {1688if (this.options.scope) {1689this.options.onChange.call(this.options.scope, this.result);1690} else {1691this.options.onChange(this.result);1692}1693}1694},1695callOnFinish: function () {1696this.writeToInput();1697
1698if (this.options.onFinish && typeof this.options.onFinish === "function") {1699if (this.options.scope) {1700this.options.onFinish.call(this.options.scope, this.result);1701} else {1702this.options.onFinish(this.result);1703}1704}1705},1706callOnUpdate: function () {1707this.writeToInput();1708
1709if (this.options.onUpdate && typeof this.options.onUpdate === "function") {1710if (this.options.scope) {1711this.options.onUpdate.call(this.options.scope, this.result);1712} else {1713this.options.onUpdate(this.result);1714}1715}1716},1717
1718
1719
1720
1721// =============================================================================================================1722// Service methods1723
1724toggleInput: function () {1725this.$cache.input.toggleClass("irs-hidden-input");1726
1727if (this.has_tab_index) {1728this.$cache.input.prop("tabindex", -1);1729} else {1730this.$cache.input.removeProp("tabindex");1731}1732
1733this.has_tab_index = !this.has_tab_index;1734},1735
1736/**1737* Convert real value to percent
1738*
1739* @param value {Number} X in real
1740* @param no_min {boolean=} don't use min value
1741* @returns {Number} X in percent
1742*/
1743convertToPercent: function (value, no_min) {1744var diapason = this.options.max - this.options.min,1745one_percent = diapason / 100,1746val, percent;1747
1748if (!diapason) {1749this.no_diapason = true;1750return 0;1751}1752
1753if (no_min) {1754val = value;1755} else {1756val = value - this.options.min;1757}1758
1759percent = val / one_percent;1760
1761return this.toFixed(percent);1762},1763
1764/**1765* Convert percent to real values
1766*
1767* @param percent {Number} X in percent
1768* @returns {Number} X in real
1769*/
1770convertToValue: function (percent) {1771var min = this.options.min,1772max = this.options.max,1773min_decimals = min.toString().split(".")[1],1774max_decimals = max.toString().split(".")[1],1775min_length, max_length,1776avg_decimals = 0,1777abs = 0;1778
1779if (percent === 0) {1780return this.options.min;1781}1782if (percent === 100) {1783return this.options.max;1784}1785
1786
1787if (min_decimals) {1788min_length = min_decimals.length;1789avg_decimals = min_length;1790}1791if (max_decimals) {1792max_length = max_decimals.length;1793avg_decimals = max_length;1794}1795if (min_length && max_length) {1796avg_decimals = (min_length >= max_length) ? min_length : max_length;1797}1798
1799if (min < 0) {1800abs = Math.abs(min);1801min = +(min + abs).toFixed(avg_decimals);1802max = +(max + abs).toFixed(avg_decimals);1803}1804
1805var number = ((max - min) / 100 * percent) + min,1806string = this.options.step.toString().split(".")[1],1807result;1808
1809if (string) {1810number = +number.toFixed(string.length);1811} else {1812number = number / this.options.step;1813number = number * this.options.step;1814
1815number = +number.toFixed(0);1816}1817
1818if (abs) {1819number -= abs;1820}1821
1822if (string) {1823result = +number.toFixed(string.length);1824} else {1825result = this.toFixed(number);1826}1827
1828if (result < this.options.min) {1829result = this.options.min;1830} else if (result > this.options.max) {1831result = this.options.max;1832}1833
1834return result;1835},1836
1837/**1838* Round percent value with step
1839*
1840* @param percent {Number}
1841* @returns percent {Number} rounded
1842*/
1843calcWithStep: function (percent) {1844var rounded = Math.round(percent / this.coords.p_step) * this.coords.p_step;1845
1846if (rounded > 100) {1847rounded = 100;1848}1849if (percent === 100) {1850rounded = 100;1851}1852
1853return this.toFixed(rounded);1854},1855
1856checkMinInterval: function (p_current, p_next, type) {1857var o = this.options,1858current,1859next;1860
1861if (!o.min_interval) {1862return p_current;1863}1864
1865current = this.convertToValue(p_current);1866next = this.convertToValue(p_next);1867
1868if (type === "from") {1869
1870if (next - current < o.min_interval) {1871current = next - o.min_interval;1872}1873
1874} else {1875
1876if (current - next < o.min_interval) {1877current = next + o.min_interval;1878}1879
1880}1881
1882return this.convertToPercent(current);1883},1884
1885checkMaxInterval: function (p_current, p_next, type) {1886var o = this.options,1887current,1888next;1889
1890if (!o.max_interval) {1891return p_current;1892}1893
1894current = this.convertToValue(p_current);1895next = this.convertToValue(p_next);1896
1897if (type === "from") {1898
1899if (next - current > o.max_interval) {1900current = next - o.max_interval;1901}1902
1903} else {1904
1905if (current - next > o.max_interval) {1906current = next + o.max_interval;1907}1908
1909}1910
1911return this.convertToPercent(current);1912},1913
1914checkDiapason: function (p_num, min, max) {1915var num = this.convertToValue(p_num),1916o = this.options;1917
1918if (typeof min !== "number") {1919min = o.min;1920}1921
1922if (typeof max !== "number") {1923max = o.max;1924}1925
1926if (num < min) {1927num = min;1928}1929
1930if (num > max) {1931num = max;1932}1933
1934return this.convertToPercent(num);1935},1936
1937toFixed: function (num) {1938num = num.toFixed(20);1939return +num;1940},1941
1942_prettify: function (num) {1943if (!this.options.prettify_enabled) {1944return num;1945}1946
1947if (this.options.prettify && typeof this.options.prettify === "function") {1948return this.options.prettify(num);1949} else {1950return this.prettify(num);1951}1952},1953
1954prettify: function (num) {1955var n = num.toString();1956return n.replace(/(\d{1,3}(?=(?:\d\d\d)+(?!\d)))/g, "$1" + this.options.prettify_separator);1957},1958
1959checkEdges: function (left, width) {1960if (!this.options.force_edges) {1961return this.toFixed(left);1962}1963
1964if (left < 0) {1965left = 0;1966} else if (left > 100 - width) {1967left = 100 - width;1968}1969
1970return this.toFixed(left);1971},1972
1973validate: function () {1974var o = this.options,1975r = this.result,1976v = o.values,1977vl = v.length,1978value,1979i;1980
1981if (typeof o.min === "string") o.min = +o.min;1982if (typeof o.max === "string") o.max = +o.max;1983if (typeof o.from === "string") o.from = +o.from;1984if (typeof o.to === "string") o.to = +o.to;1985if (typeof o.step === "string") o.step = +o.step;1986
1987if (typeof o.from_min === "string") o.from_min = +o.from_min;1988if (typeof o.from_max === "string") o.from_max = +o.from_max;1989if (typeof o.to_min === "string") o.to_min = +o.to_min;1990if (typeof o.to_max === "string") o.to_max = +o.to_max;1991
1992if (typeof o.grid_num === "string") o.grid_num = +o.grid_num;1993
1994if (o.max < o.min) {1995o.max = o.min;1996}1997
1998if (vl) {1999o.p_values = [];2000o.min = 0;2001o.max = vl - 1;2002o.step = 1;2003o.grid_num = o.max;2004o.grid_snap = true;2005
2006for (i = 0; i < vl; i++) {2007value = +v[i];2008
2009if (!isNaN(value)) {2010v[i] = value;2011value = this._prettify(value);2012} else {2013value = v[i];2014}2015
2016o.p_values.push(value);2017}2018}2019
2020if (typeof o.from !== "number" || isNaN(o.from)) {2021o.from = o.min;2022}2023
2024if (typeof o.to !== "number" || isNaN(o.to)) {2025o.to = o.max;2026}2027
2028if (o.type === "single") {2029
2030if (o.from < o.min) o.from = o.min;2031if (o.from > o.max) o.from = o.max;2032
2033} else {2034
2035if (o.from < o.min) o.from = o.min;2036if (o.from > o.max) o.from = o.max;2037
2038if (o.to < o.min) o.to = o.min;2039if (o.to > o.max) o.to = o.max;2040
2041if (this.update_check.from) {2042
2043if (this.update_check.from !== o.from) {2044if (o.from > o.to) o.from = o.to;2045}2046if (this.update_check.to !== o.to) {2047if (o.to < o.from) o.to = o.from;2048}2049
2050}2051
2052if (o.from > o.to) o.from = o.to;2053if (o.to < o.from) o.to = o.from;2054
2055}2056
2057if (typeof o.step !== "number" || isNaN(o.step) || !o.step || o.step < 0) {2058o.step = 1;2059}2060
2061if (typeof o.from_min === "number" && o.from < o.from_min) {2062o.from = o.from_min;2063}2064
2065if (typeof o.from_max === "number" && o.from > o.from_max) {2066o.from = o.from_max;2067}2068
2069if (typeof o.to_min === "number" && o.to < o.to_min) {2070o.to = o.to_min;2071}2072
2073if (typeof o.to_max === "number" && o.from > o.to_max) {2074o.to = o.to_max;2075}2076
2077if (r) {2078if (r.min !== o.min) {2079r.min = o.min;2080}2081
2082if (r.max !== o.max) {2083r.max = o.max;2084}2085
2086if (r.from < r.min || r.from > r.max) {2087r.from = o.from;2088}2089
2090if (r.to < r.min || r.to > r.max) {2091r.to = o.to;2092}2093}2094
2095if (typeof o.min_interval !== "number" || isNaN(o.min_interval) || !o.min_interval || o.min_interval < 0) {2096o.min_interval = 0;2097}2098
2099if (typeof o.max_interval !== "number" || isNaN(o.max_interval) || !o.max_interval || o.max_interval < 0) {2100o.max_interval = 0;2101}2102
2103if (o.min_interval && o.min_interval > o.max - o.min) {2104o.min_interval = o.max - o.min;2105}2106
2107if (o.max_interval && o.max_interval > o.max - o.min) {2108o.max_interval = o.max - o.min;2109}2110},2111
2112decorate: function (num, original) {2113var decorated = "",2114o = this.options;2115
2116if (o.prefix) {2117decorated += o.prefix;2118}2119
2120decorated += num;2121
2122if (o.max_postfix) {2123if (o.values.length && num === o.p_values[o.max]) {2124decorated += o.max_postfix;2125if (o.postfix) {2126decorated += " ";2127}2128} else if (original === o.max) {2129decorated += o.max_postfix;2130if (o.postfix) {2131decorated += " ";2132}2133}2134}2135
2136if (o.postfix) {2137decorated += o.postfix;2138}2139
2140return decorated;2141},2142
2143updateFrom: function () {2144this.result.from = this.options.from;2145this.result.from_percent = this.convertToPercent(this.result.from);2146this.result.from_pretty = this._prettify(this.result.from);2147if (this.options.values) {2148this.result.from_value = this.options.values[this.result.from];2149}2150},2151
2152updateTo: function () {2153this.result.to = this.options.to;2154this.result.to_percent = this.convertToPercent(this.result.to);2155this.result.to_pretty = this._prettify(this.result.to);2156if (this.options.values) {2157this.result.to_value = this.options.values[this.result.to];2158}2159},2160
2161updateResult: function () {2162this.result.min = this.options.min;2163this.result.max = this.options.max;2164this.updateFrom();2165this.updateTo();2166},2167
2168
2169// =============================================================================================================2170// Grid2171
2172appendGrid: function () {2173if (!this.options.grid) {2174return;2175}2176
2177var o = this.options,2178i, z,2179
2180total = o.max - o.min,2181big_num = o.grid_num,2182big_p = 0,2183big_w = 0,2184
2185small_max = 4,2186local_small_max,2187small_p,2188small_w = 0,2189
2190result,2191html = '';2192
2193
2194
2195this.calcGridMargin();2196
2197if (o.grid_snap) {2198big_num = total / o.step;2199}2200
2201if (big_num > 50) big_num = 50;2202big_p = this.toFixed(100 / big_num);2203
2204if (big_num > 4) {2205small_max = 3;2206}2207if (big_num > 7) {2208small_max = 2;2209}2210if (big_num > 14) {2211small_max = 1;2212}2213if (big_num > 28) {2214small_max = 0;2215}2216
2217for (i = 0; i < big_num + 1; i++) {2218local_small_max = small_max;2219
2220big_w = this.toFixed(big_p * i);2221
2222if (big_w > 100) {2223big_w = 100;2224}2225this.coords.big[i] = big_w;2226
2227small_p = (big_w - (big_p * (i - 1))) / (local_small_max + 1);2228
2229for (z = 1; z <= local_small_max; z++) {2230if (big_w === 0) {2231break;2232}2233
2234small_w = this.toFixed(big_w - (small_p * z));2235
2236html += '<span class="irs-grid-pol small" style="left: ' + small_w + '%"></span>';2237}2238
2239html += '<span class="irs-grid-pol" style="left: ' + big_w + '%"></span>';2240
2241result = this.convertToValue(big_w);2242if (o.values.length) {2243result = o.p_values[result];2244} else {2245result = this._prettify(result);2246}2247
2248html += '<span class="irs-grid-text js-grid-text-' + i + '" style="left: ' + big_w + '%">' + result + '</span>';2249}2250this.coords.big_num = Math.ceil(big_num + 1);2251
2252
2253
2254this.$cache.cont.addClass("irs-with-grid");2255this.$cache.grid.html(html);2256this.cacheGridLabels();2257},2258
2259cacheGridLabels: function () {2260var $label, i,2261num = this.coords.big_num;2262
2263for (i = 0; i < num; i++) {2264$label = this.$cache.grid.find(".js-grid-text-" + i);2265this.$cache.grid_labels.push($label);2266}2267
2268this.calcGridLabels();2269},2270
2271calcGridLabels: function () {2272var i, label, start = [], finish = [],2273num = this.coords.big_num;2274
2275for (i = 0; i < num; i++) {2276this.coords.big_w[i] = this.$cache.grid_labels[i].outerWidth(false);2277this.coords.big_p[i] = this.toFixed(this.coords.big_w[i] / this.coords.w_rs * 100);2278this.coords.big_x[i] = this.toFixed(this.coords.big_p[i] / 2);2279
2280start[i] = this.toFixed(this.coords.big[i] - this.coords.big_x[i]);2281finish[i] = this.toFixed(start[i] + this.coords.big_p[i]);2282}2283
2284if (this.options.force_edges) {2285if (start[0] < -this.coords.grid_gap) {2286start[0] = -this.coords.grid_gap;2287finish[0] = this.toFixed(start[0] + this.coords.big_p[0]);2288
2289this.coords.big_x[0] = this.coords.grid_gap;2290}2291
2292if (finish[num - 1] > 100 + this.coords.grid_gap) {2293finish[num - 1] = 100 + this.coords.grid_gap;2294start[num - 1] = this.toFixed(finish[num - 1] - this.coords.big_p[num - 1]);2295
2296this.coords.big_x[num - 1] = this.toFixed(this.coords.big_p[num - 1] - this.coords.grid_gap);2297}2298}2299
2300this.calcGridCollision(2, start, finish);2301this.calcGridCollision(4, start, finish);2302
2303for (i = 0; i < num; i++) {2304label = this.$cache.grid_labels[i][0];2305
2306if (this.coords.big_x[i] !== Number.POSITIVE_INFINITY) {2307label.style.marginLeft = -this.coords.big_x[i] + "%";2308}2309}2310},2311
2312// Collisions Calc Beta2313// TODO: Refactor then have plenty of time2314calcGridCollision: function (step, start, finish) {2315var i, next_i, label,2316num = this.coords.big_num;2317
2318for (i = 0; i < num; i += step) {2319next_i = i + (step / 2);2320if (next_i >= num) {2321break;2322}2323
2324label = this.$cache.grid_labels[next_i][0];2325
2326if (finish[i] <= start[next_i]) {2327label.style.visibility = "visible";2328} else {2329label.style.visibility = "hidden";2330}2331}2332},2333
2334calcGridMargin: function () {2335if (!this.options.grid_margin) {2336return;2337}2338
2339this.coords.w_rs = this.$cache.rs.outerWidth(false);2340if (!this.coords.w_rs) {2341return;2342}2343
2344if (this.options.type === "single") {2345this.coords.w_handle = this.$cache.s_single.outerWidth(false);2346} else {2347this.coords.w_handle = this.$cache.s_from.outerWidth(false);2348}2349this.coords.p_handle = this.toFixed(this.coords.w_handle / this.coords.w_rs * 100);2350this.coords.grid_gap = this.toFixed((this.coords.p_handle / 2) - 0.1);2351
2352this.$cache.grid[0].style.width = this.toFixed(100 - this.coords.p_handle) + "%";2353this.$cache.grid[0].style.left = this.coords.grid_gap + "%";2354},2355
2356
2357
2358// =============================================================================================================2359// Public methods2360
2361update: function (options) {2362if (!this.input) {2363return;2364}2365
2366this.is_update = true;2367
2368this.options.from = this.result.from;2369this.options.to = this.result.to;2370this.update_check.from = this.result.from;2371this.update_check.to = this.result.to;2372
2373this.options = $.extend(this.options, options);2374this.validate();2375this.updateResult(options);2376
2377this.toggleInput();2378this.remove();2379this.init(true);2380},2381
2382reset: function () {2383if (!this.input) {2384return;2385}2386
2387this.updateResult();2388this.update();2389},2390
2391destroy: function () {2392if (!this.input) {2393return;2394}2395
2396this.toggleInput();2397this.$cache.input.prop("readonly", false);2398$.data(this.input, "ionRangeSlider", null);2399
2400this.remove();2401this.input = null;2402this.options = null;2403}2404};2405
2406$.fn.ionRangeSlider = function (options) {2407return this.each(function() {2408if (!$.data(this, "ionRangeSlider")) {2409$.data(this, "ionRangeSlider", new IonRangeSlider(this, options, plugin_count++));2410}2411});2412};2413
2414
2415
2416// =================================================================================================================2417// http://paulirish.com/2011/requestanimationframe-for-smart-animating/2418// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating2419
2420// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel2421
2422// MIT license2423
2424(function() {2425var lastTime = 0;2426var vendors = ['ms', 'moz', 'webkit', 'o'];2427for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {2428window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];2429window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']2430|| window[vendors[x]+'CancelRequestAnimationFrame'];2431}2432
2433if (!window.requestAnimationFrame)2434window.requestAnimationFrame = function(callback, element) {2435var currTime = new Date().getTime();2436var timeToCall = Math.max(0, 16 - (currTime - lastTime));2437var id = window.setTimeout(function() { callback(currTime + timeToCall); },2438timeToCall);2439lastTime = currTime + timeToCall;2440return id;2441};2442
2443if (!window.cancelAnimationFrame)2444window.cancelAnimationFrame = function(id) {2445clearTimeout(id);2446};2447}());2448
2449}));2450