ion.rangeSlider.js 65 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888
  1. // Ion.RangeSlider
  2. // version 2.0.6 Build: 300
  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. ;(function ($, document, window, navigator, undefined) {
  13. "use strict";
  14. // =================================================================================================================
  15. // Service
  16. var plugin_count = 0;
  17. var is_old_ie = (function () {
  18. var n = navigator.userAgent,
  19. r = /msie\s\d+/i,
  20. v;
  21. if (n.search(r) > 0) {
  22. v = r.exec(n).toString();
  23. v = v.split(" ")[1];
  24. if (v < 9) {
  25. $("html").addClass("lt-ie9");
  26. return true;
  27. }
  28. }
  29. return false;
  30. } ());
  31. // IE8 fix
  32. if (!Function.prototype.bind) {
  33. Function.prototype.bind = function bind(that) {
  34. var target = this;
  35. var slice = [].slice;
  36. if (typeof target != "function") {
  37. throw new TypeError();
  38. }
  39. var args = slice.call(arguments, 1),
  40. bound = function () {
  41. if (this instanceof bound) {
  42. var F = function(){};
  43. F.prototype = target.prototype;
  44. var self = new F();
  45. var result = target.apply(
  46. self,
  47. args.concat(slice.call(arguments))
  48. );
  49. if (Object(result) === result) {
  50. return result;
  51. }
  52. return self;
  53. } else {
  54. return target.apply(
  55. that,
  56. args.concat(slice.call(arguments))
  57. );
  58. }
  59. };
  60. return bound;
  61. };
  62. }
  63. if (!Array.prototype.indexOf) {
  64. Array.prototype.indexOf = function(searchElement, fromIndex) {
  65. var k;
  66. if (this == null) {
  67. throw new TypeError('"this" is null or not defined');
  68. }
  69. var O = Object(this);
  70. var len = O.length >>> 0;
  71. if (len === 0) {
  72. return -1;
  73. }
  74. var n = +fromIndex || 0;
  75. if (Math.abs(n) === Infinity) {
  76. n = 0;
  77. }
  78. if (n >= len) {
  79. return -1;
  80. }
  81. k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
  82. while (k < len) {
  83. if (k in O && O[k] === searchElement) {
  84. return k;
  85. }
  86. k++;
  87. }
  88. return -1;
  89. };
  90. }
  91. // =================================================================================================================
  92. // Template
  93. var base_html =
  94. '<span class="irs">' +
  95. '<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>' +
  96. '<span class="irs-min">0</span><span class="irs-max">1</span>' +
  97. '<span class="irs-from">0</span><span class="irs-to">0</span><span class="irs-single">0</span>' +
  98. '</span>' +
  99. '<span class="irs-grid"></span>' +
  100. '<span class="irs-bar"></span>';
  101. var single_html =
  102. '<span class="irs-bar-edge"></span>' +
  103. '<span class="irs-shadow shadow-single"></span>' +
  104. '<span class="irs-slider single"></span>';
  105. var double_html =
  106. '<span class="irs-shadow shadow-from"></span>' +
  107. '<span class="irs-shadow shadow-to"></span>' +
  108. '<span class="irs-slider from"></span>' +
  109. '<span class="irs-slider to"></span>';
  110. var disable_html =
  111. '<span class="irs-disable-mask"></span>';
  112. // =================================================================================================================
  113. // Core
  114. var IonRangeSlider = function (input, options, plugin_count) {
  115. this.VERSION = "2.0.6";
  116. this.input = input;
  117. this.plugin_count = plugin_count;
  118. this.current_plugin = 0;
  119. this.calc_count = 0;
  120. this.old_from = 0;
  121. this.old_to = 0;
  122. this.raf_id = null;
  123. this.dragging = false;
  124. this.force_redraw = false;
  125. this.is_key = false;
  126. this.is_update = false;
  127. this.is_start = true;
  128. this.is_active = false;
  129. this.is_resize = false;
  130. this.is_click = false;
  131. this.$cache = {
  132. win: $(window),
  133. body: $(document.body),
  134. input: $(input),
  135. cont: null,
  136. rs: null,
  137. min: null,
  138. max: null,
  139. from: null,
  140. to: null,
  141. single: null,
  142. bar: null,
  143. line: null,
  144. s_single: null,
  145. s_from: null,
  146. s_to: null,
  147. shad_single: null,
  148. shad_from: null,
  149. shad_to: null,
  150. grid: null,
  151. grid_labels: []
  152. };
  153. // get config data attributes
  154. var $inp = this.$cache.input;
  155. var data = {
  156. type: $inp.data("type"),
  157. min: $inp.data("min"),
  158. max: $inp.data("max"),
  159. from: $inp.data("from"),
  160. to: $inp.data("to"),
  161. step: $inp.data("step"),
  162. min_interval: $inp.data("minInterval"),
  163. max_interval: $inp.data("maxInterval"),
  164. drag_interval: $inp.data("dragInterval"),
  165. values: $inp.data("values"),
  166. from_fixed: $inp.data("fromFixed"),
  167. from_min: $inp.data("fromMin"),
  168. from_max: $inp.data("fromMax"),
  169. from_shadow: $inp.data("fromShadow"),
  170. to_fixed: $inp.data("toFixed"),
  171. to_min: $inp.data("toMin"),
  172. to_max: $inp.data("toMax"),
  173. to_shadow: $inp.data("toShadow"),
  174. prettify_enabled: $inp.data("prettifyEnabled"),
  175. prettify_separator: $inp.data("prettifySeparator"),
  176. force_edges: $inp.data("forceEdges"),
  177. keyboard: $inp.data("keyboard"),
  178. keyboard_step: $inp.data("keyboardStep"),
  179. grid: $inp.data("grid"),
  180. grid_margin: $inp.data("gridMargin"),
  181. grid_num: $inp.data("gridNum"),
  182. grid_snap: $inp.data("gridSnap"),
  183. hide_min_max: $inp.data("hideMinMax"),
  184. hide_from_to: $inp.data("hideFromTo"),
  185. prefix: $inp.data("prefix"),
  186. postfix: $inp.data("postfix"),
  187. max_postfix: $inp.data("maxPostfix"),
  188. decorate_both: $inp.data("decorateBoth"),
  189. values_separator: $inp.data("valuesSeparator"),
  190. disable: $inp.data("disable")
  191. };
  192. data.values = data.values && data.values.split(",");
  193. options = $.extend(data, options);
  194. // get from and to out of input
  195. var val = $inp.prop("value");
  196. if (val) {
  197. val = val.split(";");
  198. if (val[0] && val[0] == +val[0]) {
  199. val[0] = +val[0];
  200. }
  201. if (val[1] && val[1] == +val[1]) {
  202. val[1] = +val[1];
  203. }
  204. if (options.values && options.values.length) {
  205. data.from = val[0] && options.values.indexOf(val[0]);
  206. data.to = val[1] && options.values.indexOf(val[1]);
  207. } else {
  208. data.from = val[0] && +val[0];
  209. data.to = val[1] && +val[1];
  210. }
  211. }
  212. // get config from options
  213. this.options = $.extend({
  214. type: "single",
  215. min: 10,
  216. max: 100,
  217. from: null,
  218. to: null,
  219. step: 1,
  220. min_interval: 0,
  221. max_interval: 0,
  222. drag_interval: false,
  223. values: [],
  224. p_values: [],
  225. from_fixed: false,
  226. from_min: null,
  227. from_max: null,
  228. from_shadow: false,
  229. to_fixed: false,
  230. to_min: null,
  231. to_max: null,
  232. to_shadow: false,
  233. prettify_enabled: true,
  234. prettify_separator: " ",
  235. prettify: null,
  236. force_edges: false,
  237. keyboard: false,
  238. keyboard_step: 5,
  239. grid: false,
  240. grid_margin: true,
  241. grid_num: 4,
  242. grid_snap: false,
  243. hide_min_max: false,
  244. hide_from_to: false,
  245. prefix: "",
  246. postfix: "",
  247. max_postfix: "",
  248. decorate_both: true,
  249. values_separator: " — ",
  250. disable: false,
  251. onStart: null,
  252. onChange: null,
  253. onFinish: null,
  254. onUpdate: null
  255. }, options);
  256. this.validate();
  257. this.result = {
  258. input: this.$cache.input,
  259. slider: null,
  260. min: this.options.min,
  261. max: this.options.max,
  262. from: this.options.from,
  263. from_percent: 0,
  264. from_value: null,
  265. to: this.options.to,
  266. to_percent: 0,
  267. to_value: null
  268. };
  269. this.coords = {
  270. // left
  271. x_gap: 0,
  272. x_pointer: 0,
  273. // width
  274. w_rs: 0,
  275. w_rs_old: 0,
  276. w_handle: 0,
  277. // percents
  278. p_gap: 0,
  279. p_gap_left: 0,
  280. p_gap_right: 0,
  281. p_step: 0,
  282. p_pointer: 0,
  283. p_handle: 0,
  284. p_single: 0,
  285. p_single_real: 0,
  286. p_from: 0,
  287. p_from_real: 0,
  288. p_to: 0,
  289. p_to_real: 0,
  290. p_bar_x: 0,
  291. p_bar_w: 0,
  292. // grid
  293. grid_gap: 0,
  294. big_num: 0,
  295. big: [],
  296. big_w: [],
  297. big_p: [],
  298. big_x: []
  299. };
  300. this.labels = {
  301. // width
  302. w_min: 0,
  303. w_max: 0,
  304. w_from: 0,
  305. w_to: 0,
  306. w_single: 0,
  307. // percents
  308. p_min: 0,
  309. p_max: 0,
  310. p_from: 0,
  311. p_from_left: 0,
  312. p_to: 0,
  313. p_to_left: 0,
  314. p_single: 0,
  315. p_single_left: 0
  316. };
  317. this.init();
  318. };
  319. IonRangeSlider.prototype = {
  320. init: function (is_update) {
  321. this.coords.p_step = this.options.step / ((this.options.max - this.options.min) / 100);
  322. this.target = "base";
  323. this.toggleInput();
  324. this.append();
  325. this.setMinMax();
  326. if (is_update) {
  327. this.force_redraw = true;
  328. this.calc(true);
  329. if (this.options.onUpdate && typeof this.options.onUpdate === "function") {
  330. this.options.onUpdate(this.result);
  331. }
  332. } else {
  333. this.force_redraw = true;
  334. this.calc(true);
  335. if (this.options.onStart && typeof this.options.onStart === "function") {
  336. this.options.onStart(this.result);
  337. }
  338. }
  339. this.updateScene();
  340. this.raf_id = requestAnimationFrame(this.updateScene.bind(this));
  341. },
  342. append: function () {
  343. var container_html = '<span class="irs js-irs-' + this.plugin_count + '"></span>';
  344. this.$cache.input.before(container_html);
  345. this.$cache.input.prop("readonly", true);
  346. this.$cache.cont = this.$cache.input.prev();
  347. this.result.slider = this.$cache.cont;
  348. this.$cache.cont.html(base_html);
  349. this.$cache.rs = this.$cache.cont.find(".irs");
  350. this.$cache.min = this.$cache.cont.find(".irs-min");
  351. this.$cache.max = this.$cache.cont.find(".irs-max");
  352. this.$cache.from = this.$cache.cont.find(".irs-from");
  353. this.$cache.to = this.$cache.cont.find(".irs-to");
  354. this.$cache.single = this.$cache.cont.find(".irs-single");
  355. this.$cache.bar = this.$cache.cont.find(".irs-bar");
  356. this.$cache.line = this.$cache.cont.find(".irs-line");
  357. this.$cache.grid = this.$cache.cont.find(".irs-grid");
  358. if (this.options.type === "single") {
  359. this.$cache.cont.append(single_html);
  360. this.$cache.s_single = this.$cache.cont.find(".single");
  361. this.$cache.from[0].style.visibility = "hidden";
  362. this.$cache.to[0].style.visibility = "hidden";
  363. this.$cache.shad_single = this.$cache.cont.find(".shadow-single");
  364. } else {
  365. this.$cache.cont.append(double_html);
  366. this.$cache.s_from = this.$cache.cont.find(".from");
  367. this.$cache.s_to = this.$cache.cont.find(".to");
  368. this.$cache.shad_from = this.$cache.cont.find(".shadow-from");
  369. this.$cache.shad_to = this.$cache.cont.find(".shadow-to");
  370. }
  371. if (this.options.hide_from_to) {
  372. this.$cache.from[0].style.display = "none";
  373. this.$cache.to[0].style.display = "none";
  374. this.$cache.single[0].style.display = "none";
  375. }
  376. this.appendGrid();
  377. if (this.options.disable) {
  378. this.appendDisableMask();
  379. this.$cache.input[0].disabled = true;
  380. } else {
  381. this.$cache.cont.removeClass("irs-disabled");
  382. this.$cache.input[0].disabled = false;
  383. this.bindEvents();
  384. }
  385. },
  386. appendDisableMask: function () {
  387. this.$cache.cont.append(disable_html);
  388. this.$cache.cont.addClass("irs-disabled");
  389. },
  390. remove: function () {
  391. this.$cache.cont.remove();
  392. this.$cache.cont = null;
  393. this.$cache.line.off("keydown.irs_" + this.plugin_count);
  394. this.$cache.body.off("touchmove.irs_" + this.plugin_count);
  395. this.$cache.body.off("mousemove.irs_" + this.plugin_count);
  396. this.$cache.win.off("touchend.irs_" + this.plugin_count);
  397. this.$cache.win.off("mouseup.irs_" + this.plugin_count);
  398. if (is_old_ie) {
  399. this.$cache.body.off("mouseup.irs_" + this.plugin_count);
  400. this.$cache.body.off("mouseleave.irs_" + this.plugin_count);
  401. }
  402. this.$cache.grid_labels = [];
  403. this.coords.big = [];
  404. this.coords.big_w = [];
  405. this.coords.big_p = [];
  406. this.coords.big_x = [];
  407. cancelAnimationFrame(this.raf_id);
  408. },
  409. bindEvents: function () {
  410. this.$cache.body.on("touchmove.irs_" + this.plugin_count, this.pointerMove.bind(this));
  411. this.$cache.body.on("mousemove.irs_" + this.plugin_count, this.pointerMove.bind(this));
  412. this.$cache.win.on("touchend.irs_" + this.plugin_count, this.pointerUp.bind(this));
  413. this.$cache.win.on("mouseup.irs_" + this.plugin_count, this.pointerUp.bind(this));
  414. this.$cache.line.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
  415. this.$cache.line.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
  416. if (this.options.drag_interval && this.options.type === "double") {
  417. this.$cache.bar.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "both"));
  418. this.$cache.bar.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "both"));
  419. } else {
  420. this.$cache.bar.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
  421. this.$cache.bar.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
  422. }
  423. if (this.options.type === "single") {
  424. this.$cache.s_single.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
  425. this.$cache.shad_single.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
  426. this.$cache.s_single.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
  427. this.$cache.shad_single.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
  428. } else {
  429. this.$cache.s_from.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
  430. this.$cache.s_to.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
  431. this.$cache.shad_from.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
  432. this.$cache.shad_to.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
  433. this.$cache.s_from.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
  434. this.$cache.s_to.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
  435. this.$cache.shad_from.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
  436. this.$cache.shad_to.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
  437. }
  438. if (this.options.keyboard) {
  439. this.$cache.line.on("keydown.irs_" + this.plugin_count, this.key.bind(this, "keyboard"));
  440. }
  441. if (is_old_ie) {
  442. this.$cache.body.on("mouseup.irs_" + this.plugin_count, this.pointerUp.bind(this));
  443. this.$cache.body.on("mouseleave.irs_" + this.plugin_count, this.pointerUp.bind(this));
  444. }
  445. },
  446. pointerMove: function (e) {
  447. if (!this.dragging) {
  448. return;
  449. }
  450. var x = e.pageX || e.originalEvent.touches && e.originalEvent.touches[0].pageX;
  451. this.coords.x_pointer = x - this.coords.x_gap;
  452. this.calc();
  453. },
  454. pointerUp: function (e) {
  455. if (this.current_plugin !== this.plugin_count) {
  456. return;
  457. }
  458. if (this.is_active) {
  459. this.is_active = false;
  460. } else {
  461. return;
  462. }
  463. var is_function = this.options.onFinish && typeof this.options.onFinish === "function",
  464. is_original = $.contains(this.$cache.cont[0], e.target) || this.dragging;
  465. if (is_function && is_original) {
  466. this.options.onFinish(this.result);
  467. }
  468. this.$cache.cont.find(".state_hover").removeClass("state_hover");
  469. this.force_redraw = true;
  470. this.dragging = false;
  471. if (is_old_ie) {
  472. $("*").prop("unselectable", false);
  473. }
  474. },
  475. pointerDown: function (target, e) {
  476. e.preventDefault();
  477. var x = e.pageX || e.originalEvent.touches && e.originalEvent.touches[0].pageX;
  478. if (e.button === 2) {
  479. return;
  480. }
  481. this.current_plugin = this.plugin_count;
  482. this.target = target;
  483. this.is_active = true;
  484. this.dragging = true;
  485. this.coords.x_gap = this.$cache.rs.offset().left;
  486. this.coords.x_pointer = x - this.coords.x_gap;
  487. this.calcPointer();
  488. switch (target) {
  489. case "single":
  490. this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_single);
  491. break;
  492. case "from":
  493. this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_from);
  494. this.$cache.s_from.addClass("state_hover");
  495. this.$cache.s_from.addClass("type_last");
  496. this.$cache.s_to.removeClass("type_last");
  497. break;
  498. case "to":
  499. this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_to);
  500. this.$cache.s_to.addClass("state_hover");
  501. this.$cache.s_to.addClass("type_last");
  502. this.$cache.s_from.removeClass("type_last");
  503. break;
  504. case "both":
  505. this.coords.p_gap_left = this.toFixed(this.coords.p_pointer - this.coords.p_from);
  506. this.coords.p_gap_right = this.toFixed(this.coords.p_to - this.coords.p_pointer);
  507. this.$cache.s_to.removeClass("type_last");
  508. this.$cache.s_from.removeClass("type_last");
  509. break;
  510. }
  511. if (is_old_ie) {
  512. $("*").prop("unselectable", true);
  513. }
  514. this.$cache.line.trigger("focus");
  515. },
  516. pointerClick: function (target, e) {
  517. e.preventDefault();
  518. var x = e.pageX || e.originalEvent.touches && e.originalEvent.touches[0].pageX;
  519. if (e.button === 2) {
  520. return;
  521. }
  522. this.current_plugin = this.plugin_count;
  523. this.target = target;
  524. this.is_click = true;
  525. this.coords.x_gap = this.$cache.rs.offset().left;
  526. this.coords.x_pointer = +(x - this.coords.x_gap).toFixed();
  527. this.force_redraw = true;
  528. this.calc();
  529. this.$cache.line.trigger("focus");
  530. },
  531. key: function (target, e) {
  532. if (this.current_plugin !== this.plugin_count || e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
  533. return;
  534. }
  535. switch (e.which) {
  536. case 83: // W
  537. case 65: // A
  538. case 40: // DOWN
  539. case 37: // LEFT
  540. e.preventDefault();
  541. this.moveByKey(false);
  542. break;
  543. case 87: // S
  544. case 68: // D
  545. case 38: // UP
  546. case 39: // RIGHT
  547. e.preventDefault();
  548. this.moveByKey(true);
  549. break;
  550. }
  551. return true;
  552. },
  553. // Move by key beta
  554. // TODO: refactor than have plenty of time
  555. moveByKey: function (right) {
  556. var p = this.coords.p_pointer;
  557. if (right) {
  558. p += this.options.keyboard_step;
  559. } else {
  560. p -= this.options.keyboard_step;
  561. }
  562. this.coords.x_pointer = this.toFixed(this.coords.w_rs / 100 * p);
  563. this.is_key = true;
  564. this.calc();
  565. },
  566. setMinMax: function () {
  567. if (!this.options) {
  568. return;
  569. }
  570. if (this.options.hide_min_max) {
  571. this.$cache.min[0].style.display = "none";
  572. this.$cache.max[0].style.display = "none";
  573. return;
  574. }
  575. if (this.options.values.length) {
  576. this.$cache.min.html(this.decorate(this.options.p_values[this.options.min]));
  577. this.$cache.max.html(this.decorate(this.options.p_values[this.options.max]));
  578. } else {
  579. this.$cache.min.html(this.decorate(this._prettify(this.options.min), this.options.min));
  580. this.$cache.max.html(this.decorate(this._prettify(this.options.max), this.options.max));
  581. }
  582. this.labels.w_min = this.$cache.min.outerWidth(false);
  583. this.labels.w_max = this.$cache.max.outerWidth(false);
  584. },
  585. // =============================================================================================================
  586. // Calculations
  587. calc: function (update) {
  588. if (!this.options) {
  589. return;
  590. }
  591. this.calc_count++;
  592. if (this.calc_count === 10 || update) {
  593. this.calc_count = 0;
  594. this.coords.w_rs = this.$cache.rs.outerWidth(false);
  595. if (this.options.type === "single") {
  596. this.coords.w_handle = this.$cache.s_single.outerWidth(false);
  597. } else {
  598. this.coords.w_handle = this.$cache.s_from.outerWidth(false);
  599. }
  600. }
  601. if (!this.coords.w_rs) {
  602. return;
  603. }
  604. this.calcPointer();
  605. this.coords.p_handle = this.toFixed(this.coords.w_handle / this.coords.w_rs * 100);
  606. var real_width = 100 - this.coords.p_handle,
  607. real_x = this.toFixed(this.coords.p_pointer - this.coords.p_gap);
  608. if (this.target === "click") {
  609. real_x = this.toFixed(this.coords.p_pointer - (this.coords.p_handle / 2));
  610. this.target = this.chooseHandle(real_x);
  611. }
  612. if (real_x < 0) {
  613. real_x = 0;
  614. } else if (real_x > real_width) {
  615. real_x = real_width;
  616. }
  617. switch (this.target) {
  618. case "base":
  619. var w = (this.options.max - this.options.min) / 100,
  620. f = (this.result.from - this.options.min) / w,
  621. t = (this.result.to - this.options.min) / w;
  622. this.coords.p_single_real = this.toFixed(f);
  623. this.coords.p_from_real = this.toFixed(f);
  624. this.coords.p_to_real = this.toFixed(t);
  625. this.coords.p_single_real = this.checkDiapason(this.coords.p_single_real, this.options.from_min, this.options.from_max);
  626. this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
  627. this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
  628. this.coords.p_single = this.toFixed(f - (this.coords.p_handle / 100 * f));
  629. this.coords.p_from = this.toFixed(f - (this.coords.p_handle / 100 * f));
  630. this.coords.p_to = this.toFixed(t - (this.coords.p_handle / 100 * t));
  631. this.target = null;
  632. break;
  633. case "single":
  634. if (this.options.from_fixed) {
  635. break;
  636. }
  637. this.coords.p_single_real = this.calcWithStep(real_x / real_width * 100);
  638. this.coords.p_single_real = this.checkDiapason(this.coords.p_single_real, this.options.from_min, this.options.from_max);
  639. this.coords.p_single = this.toFixed(this.coords.p_single_real / 100 * real_width);
  640. break;
  641. case "from":
  642. if (this.options.from_fixed) {
  643. break;
  644. }
  645. this.coords.p_from_real = this.calcWithStep(real_x / real_width * 100);
  646. if (this.coords.p_from_real > this.coords.p_to_real) {
  647. this.coords.p_from_real = this.coords.p_to_real;
  648. }
  649. this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
  650. this.coords.p_from_real = this.checkMinInterval(this.coords.p_from_real, this.coords.p_to_real, "from");
  651. this.coords.p_from_real = this.checkMaxInterval(this.coords.p_from_real, this.coords.p_to_real, "from");
  652. this.coords.p_from = this.toFixed(this.coords.p_from_real / 100 * real_width);
  653. break;
  654. case "to":
  655. if (this.options.to_fixed) {
  656. break;
  657. }
  658. this.coords.p_to_real = this.calcWithStep(real_x / real_width * 100);
  659. if (this.coords.p_to_real < this.coords.p_from_real) {
  660. this.coords.p_to_real = this.coords.p_from_real;
  661. }
  662. this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
  663. this.coords.p_to_real = this.checkMinInterval(this.coords.p_to_real, this.coords.p_from_real, "to");
  664. this.coords.p_to_real = this.checkMaxInterval(this.coords.p_to_real, this.coords.p_from_real, "to");
  665. this.coords.p_to = this.toFixed(this.coords.p_to_real / 100 * real_width);
  666. break;
  667. case "both":
  668. real_x = this.toFixed(real_x + (this.coords.p_handle * 0.1));
  669. this.coords.p_from_real = this.calcWithStep((real_x - this.coords.p_gap_left) / real_width * 100);
  670. this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
  671. this.coords.p_from_real = this.checkMinInterval(this.coords.p_from_real, this.coords.p_to_real, "from");
  672. this.coords.p_from = this.toFixed(this.coords.p_from_real / 100 * real_width);
  673. this.coords.p_to_real = this.calcWithStep((real_x + this.coords.p_gap_right) / real_width * 100);
  674. this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
  675. this.coords.p_to_real = this.checkMinInterval(this.coords.p_to_real, this.coords.p_from_real, "to");
  676. this.coords.p_to = this.toFixed(this.coords.p_to_real / 100 * real_width);
  677. break;
  678. }
  679. if (this.options.type === "single") {
  680. this.coords.p_bar_x = (this.coords.p_handle / 2);
  681. this.coords.p_bar_w = this.coords.p_single;
  682. this.result.from_percent = this.coords.p_single_real;
  683. this.result.from = this.calcReal(this.coords.p_single_real);
  684. if (this.options.values.length) {
  685. this.result.from_value = this.options.values[this.result.from];
  686. }
  687. } else {
  688. this.coords.p_bar_x = this.toFixed(this.coords.p_from + (this.coords.p_handle / 2));
  689. this.coords.p_bar_w = this.toFixed(this.coords.p_to - this.coords.p_from);
  690. this.result.from_percent = this.coords.p_from_real;
  691. this.result.from = this.calcReal(this.coords.p_from_real);
  692. this.result.to_percent = this.coords.p_to_real;
  693. this.result.to = this.calcReal(this.coords.p_to_real);
  694. if (this.options.values.length) {
  695. this.result.from_value = this.options.values[this.result.from];
  696. this.result.to_value = this.options.values[this.result.to];
  697. }
  698. }
  699. this.calcMinMax();
  700. this.calcLabels();
  701. },
  702. calcPointer: function () {
  703. if (!this.coords.w_rs) {
  704. this.coords.p_pointer = 0;
  705. return;
  706. }
  707. if (this.coords.x_pointer < 0 || isNaN(this.coords.x_pointer) ) {
  708. this.coords.x_pointer = 0;
  709. } else if (this.coords.x_pointer > this.coords.w_rs) {
  710. this.coords.x_pointer = this.coords.w_rs;
  711. }
  712. this.coords.p_pointer = this.toFixed(this.coords.x_pointer / this.coords.w_rs * 100);
  713. },
  714. chooseHandle: function (real_x) {
  715. if (this.options.type === "single") {
  716. return "single";
  717. } else {
  718. var m_point = this.coords.p_from_real + ((this.coords.p_to_real - this.coords.p_from_real) / 2);
  719. if (real_x >= m_point) {
  720. return "to";
  721. } else {
  722. return "from";
  723. }
  724. }
  725. },
  726. calcMinMax: function () {
  727. if (!this.coords.w_rs) {
  728. return;
  729. }
  730. this.labels.p_min = this.labels.w_min / this.coords.w_rs * 100;
  731. this.labels.p_max = this.labels.w_max / this.coords.w_rs * 100;
  732. },
  733. calcLabels: function () {
  734. if (!this.coords.w_rs || this.options.hide_from_to) {
  735. return;
  736. }
  737. if (this.options.type === "single") {
  738. this.labels.w_single = this.$cache.single.outerWidth(false);
  739. this.labels.p_single = this.labels.w_single / this.coords.w_rs * 100;
  740. this.labels.p_single_left = this.coords.p_single + (this.coords.p_handle / 2) - (this.labels.p_single / 2);
  741. this.labels.p_single_left = this.checkEdges(this.labels.p_single_left, this.labels.p_single);
  742. } else {
  743. this.labels.w_from = this.$cache.from.outerWidth(false);
  744. this.labels.p_from = this.labels.w_from / this.coords.w_rs * 100;
  745. this.labels.p_from_left = this.coords.p_from + (this.coords.p_handle / 2) - (this.labels.p_from / 2);
  746. this.labels.p_from_left = this.toFixed(this.labels.p_from_left);
  747. this.labels.p_from_left = this.checkEdges(this.labels.p_from_left, this.labels.p_from);
  748. this.labels.w_to = this.$cache.to.outerWidth(false);
  749. this.labels.p_to = this.labels.w_to / this.coords.w_rs * 100;
  750. this.labels.p_to_left = this.coords.p_to + (this.coords.p_handle / 2) - (this.labels.p_to / 2);
  751. this.labels.p_to_left = this.toFixed(this.labels.p_to_left);
  752. this.labels.p_to_left = this.checkEdges(this.labels.p_to_left, this.labels.p_to);
  753. this.labels.w_single = this.$cache.single.outerWidth(false);
  754. this.labels.p_single = this.labels.w_single / this.coords.w_rs * 100;
  755. 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);
  756. this.labels.p_single_left = this.toFixed(this.labels.p_single_left);
  757. this.labels.p_single_left = this.checkEdges(this.labels.p_single_left, this.labels.p_single);
  758. }
  759. },
  760. // =============================================================================================================
  761. // Drawings
  762. updateScene: function () {
  763. if (!this.options) {
  764. return;
  765. }
  766. this.drawHandles();
  767. this.raf_id = requestAnimationFrame(this.updateScene.bind(this));
  768. },
  769. drawHandles: function () {
  770. this.coords.w_rs = this.$cache.rs.outerWidth(false);
  771. if (!this.coords.w_rs) {
  772. return;
  773. }
  774. if (this.coords.w_rs !== this.coords.w_rs_old) {
  775. this.target = "base";
  776. this.is_resize = true;
  777. }
  778. if (this.coords.w_rs !== this.coords.w_rs_old || this.force_redraw) {
  779. this.setMinMax();
  780. this.calc(true);
  781. this.drawLabels();
  782. if (this.options.grid) {
  783. this.calcGridMargin();
  784. this.calcGridLabels();
  785. }
  786. this.force_redraw = true;
  787. this.coords.w_rs_old = this.coords.w_rs;
  788. this.drawShadow();
  789. }
  790. if (!this.coords.w_rs) {
  791. return;
  792. }
  793. if (!this.dragging && !this.force_redraw && !this.is_key) {
  794. return;
  795. }
  796. if (this.old_from !== this.result.from || this.old_to !== this.result.to || this.force_redraw || this.is_key) {
  797. this.drawLabels();
  798. this.$cache.bar[0].style.left = this.coords.p_bar_x + "%";
  799. this.$cache.bar[0].style.width = this.coords.p_bar_w + "%";
  800. if (this.options.type === "single") {
  801. this.$cache.s_single[0].style.left = this.coords.p_single + "%";
  802. this.$cache.single[0].style.left = this.labels.p_single_left + "%";
  803. if (this.options.values.length) {
  804. this.$cache.input.prop("value", this.result.from_value);
  805. this.$cache.input.data("from", this.result.from_value);
  806. } else {
  807. this.$cache.input.prop("value", this.result.from);
  808. this.$cache.input.data("from", this.result.from);
  809. }
  810. } else {
  811. this.$cache.s_from[0].style.left = this.coords.p_from + "%";
  812. this.$cache.s_to[0].style.left = this.coords.p_to + "%";
  813. if (this.old_from !== this.result.from || this.force_redraw) {
  814. this.$cache.from[0].style.left = this.labels.p_from_left + "%";
  815. }
  816. if (this.old_to !== this.result.to || this.force_redraw) {
  817. this.$cache.to[0].style.left = this.labels.p_to_left + "%";
  818. }
  819. this.$cache.single[0].style.left = this.labels.p_single_left + "%";
  820. if (this.options.values.length) {
  821. this.$cache.input.prop("value", this.result.from_value + ";" + this.result.to_value);
  822. this.$cache.input.data("from", this.result.from_value);
  823. this.$cache.input.data("to", this.result.to_value);
  824. } else {
  825. this.$cache.input.prop("value", this.result.from + ";" + this.result.to);
  826. this.$cache.input.data("from", this.result.from);
  827. this.$cache.input.data("to", this.result.to);
  828. }
  829. }
  830. if ((this.old_from !== this.result.from || this.old_to !== this.result.to) && !this.is_start) {
  831. this.$cache.input.trigger("change");
  832. }
  833. this.old_from = this.result.from;
  834. this.old_to = this.result.to;
  835. var is_function = this.options.onChange && typeof this.options.onChange === "function" && !this.is_resize;
  836. if (is_function && !this.is_update && !this.is_start) {
  837. this.options.onChange(this.result);
  838. }
  839. var is_finish = this.options.onFinish && typeof this.options.onFinish === "function";
  840. if (is_finish && (this.is_key || this.is_click)) {
  841. this.options.onFinish(this.result);
  842. }
  843. this.is_update = false;
  844. this.is_resize = false;
  845. }
  846. this.is_start = false;
  847. this.is_key = false;
  848. this.is_click = false;
  849. this.force_redraw = false;
  850. },
  851. drawLabels: function () {
  852. if (!this.options) {
  853. return;
  854. }
  855. var values_num = this.options.values.length,
  856. p_values = this.options.p_values,
  857. text_single,
  858. text_from,
  859. text_to;
  860. if (this.options.hide_from_to) {
  861. return;
  862. }
  863. if (this.options.type === "single") {
  864. if (values_num) {
  865. text_single = this.decorate(p_values[this.result.from]);
  866. this.$cache.single.html(text_single);
  867. } else {
  868. text_single = this.decorate(this._prettify(this.result.from), this.result.from);
  869. this.$cache.single.html(text_single);
  870. }
  871. this.calcLabels();
  872. if (this.labels.p_single_left < this.labels.p_min + 1) {
  873. this.$cache.min[0].style.visibility = "hidden";
  874. } else {
  875. this.$cache.min[0].style.visibility = "visible";
  876. }
  877. if (this.labels.p_single_left + this.labels.p_single > 100 - this.labels.p_max - 1) {
  878. this.$cache.max[0].style.visibility = "hidden";
  879. } else {
  880. this.$cache.max[0].style.visibility = "visible";
  881. }
  882. } else {
  883. if (values_num) {
  884. if (this.options.decorate_both) {
  885. text_single = this.decorate(p_values[this.result.from]);
  886. text_single += this.options.values_separator;
  887. text_single += this.decorate(p_values[this.result.to]);
  888. } else {
  889. text_single = this.decorate(p_values[this.result.from] + this.options.values_separator + p_values[this.result.to]);
  890. }
  891. text_from = this.decorate(p_values[this.result.from]);
  892. text_to = this.decorate(p_values[this.result.to]);
  893. this.$cache.single.html(text_single);
  894. this.$cache.from.html(text_from);
  895. this.$cache.to.html(text_to);
  896. } else {
  897. if (this.options.decorate_both) {
  898. text_single = this.decorate(this._prettify(this.result.from));
  899. text_single += this.options.values_separator;
  900. text_single += this.decorate(this._prettify(this.result.to));
  901. } else {
  902. text_single = this.decorate(this._prettify(this.result.from) + this.options.values_separator + this._prettify(this.result.to), this.result.from);
  903. }
  904. text_from = this.decorate(this._prettify(this.result.from), this.result.from);
  905. text_to = this.decorate(this._prettify(this.result.to), this.result.to);
  906. this.$cache.single.html(text_single);
  907. this.$cache.from.html(text_from);
  908. this.$cache.to.html(text_to);
  909. }
  910. this.calcLabels();
  911. var min = Math.min(this.labels.p_single_left, this.labels.p_from_left),
  912. single_left = this.labels.p_single_left + this.labels.p_single,
  913. to_left = this.labels.p_to_left + this.labels.p_to,
  914. max = Math.max(single_left, to_left);
  915. if (this.labels.p_from_left + this.labels.p_from >= this.labels.p_to_left) {
  916. this.$cache.from[0].style.visibility = "hidden";
  917. this.$cache.to[0].style.visibility = "hidden";
  918. this.$cache.single[0].style.visibility = "visible";
  919. if (this.result.from === this.result.to) {
  920. this.$cache.from[0].style.visibility = "visible";
  921. this.$cache.single[0].style.visibility = "hidden";
  922. max = to_left;
  923. } else {
  924. this.$cache.from[0].style.visibility = "hidden";
  925. this.$cache.single[0].style.visibility = "visible";
  926. max = Math.max(single_left, to_left);
  927. }
  928. } else {
  929. this.$cache.from[0].style.visibility = "visible";
  930. this.$cache.to[0].style.visibility = "visible";
  931. this.$cache.single[0].style.visibility = "hidden";
  932. }
  933. if (min < this.labels.p_min + 1) {
  934. this.$cache.min[0].style.visibility = "hidden";
  935. } else {
  936. this.$cache.min[0].style.visibility = "visible";
  937. }
  938. if (max > 100 - this.labels.p_max - 1) {
  939. this.$cache.max[0].style.visibility = "hidden";
  940. } else {
  941. this.$cache.max[0].style.visibility = "visible";
  942. }
  943. }
  944. },
  945. drawShadow: function () {
  946. var o = this.options,
  947. c = this.$cache,
  948. is_from_min = typeof o.from_min === "number" && !isNaN(o.from_min),
  949. is_from_max = typeof o.from_max === "number" && !isNaN(o.from_max),
  950. is_to_min = typeof o.to_min === "number" && !isNaN(o.to_min),
  951. is_to_max = typeof o.to_max === "number" && !isNaN(o.to_max),
  952. from_min,
  953. from_max,
  954. to_min,
  955. to_max;
  956. if (o.type === "single") {
  957. if (o.from_shadow && (is_from_min || is_from_max)) {
  958. from_min = this.calcPercent(o.from_min || o.min);
  959. from_max = this.calcPercent(o.from_max || o.max) - from_min;
  960. from_min = this.toFixed(from_min - (this.coords.p_handle / 100 * from_min));
  961. from_max = this.toFixed(from_max - (this.coords.p_handle / 100 * from_max));
  962. from_min = from_min + (this.coords.p_handle / 2);
  963. c.shad_single[0].style.display = "block";
  964. c.shad_single[0].style.left = from_min + "%";
  965. c.shad_single[0].style.width = from_max + "%";
  966. } else {
  967. c.shad_single[0].style.display = "none";
  968. }
  969. } else {
  970. if (o.from_shadow && (is_from_min || is_from_max)) {
  971. from_min = this.calcPercent(o.from_min || o.min);
  972. from_max = this.calcPercent(o.from_max || o.max) - from_min;
  973. from_min = this.toFixed(from_min - (this.coords.p_handle / 100 * from_min));
  974. from_max = this.toFixed(from_max - (this.coords.p_handle / 100 * from_max));
  975. from_min = from_min + (this.coords.p_handle / 2);
  976. c.shad_from[0].style.display = "block";
  977. c.shad_from[0].style.left = from_min + "%";
  978. c.shad_from[0].style.width = from_max + "%";
  979. } else {
  980. c.shad_from[0].style.display = "none";
  981. }
  982. if (o.to_shadow && (is_to_min || is_to_max)) {
  983. to_min = this.calcPercent(o.to_min || o.min);
  984. to_max = this.calcPercent(o.to_max || o.max) - to_min;
  985. to_min = this.toFixed(to_min - (this.coords.p_handle / 100 * to_min));
  986. to_max = this.toFixed(to_max - (this.coords.p_handle / 100 * to_max));
  987. to_min = to_min + (this.coords.p_handle / 2);
  988. c.shad_to[0].style.display = "block";
  989. c.shad_to[0].style.left = to_min + "%";
  990. c.shad_to[0].style.width = to_max + "%";
  991. } else {
  992. c.shad_to[0].style.display = "none";
  993. }
  994. }
  995. },
  996. // =============================================================================================================
  997. // Service methods
  998. toggleInput: function () {
  999. this.$cache.input.toggleClass("irs-hidden-input");
  1000. },
  1001. calcPercent: function (num) {
  1002. var w = (this.options.max - this.options.min) / 100,
  1003. percent = (num - this.options.min) / w;
  1004. return this.toFixed(percent);
  1005. },
  1006. calcReal: function (percent) {
  1007. var min = this.options.min,
  1008. max = this.options.max,
  1009. abs = 0;
  1010. if (min < 0) {
  1011. abs = Math.abs(min);
  1012. min = min + abs;
  1013. max = max + abs;
  1014. }
  1015. var number = ((max - min) / 100 * percent) + min,
  1016. string = this.options.step.toString().split(".")[1];
  1017. if (string) {
  1018. number = +number.toFixed(string.length);
  1019. } else {
  1020. number = number / this.options.step;
  1021. number = number * this.options.step;
  1022. number = +number.toFixed(0);
  1023. }
  1024. if (abs) {
  1025. number -= abs;
  1026. }
  1027. if (number < this.options.min) {
  1028. number = this.options.min;
  1029. } else if (number > this.options.max) {
  1030. number = this.options.max;
  1031. }
  1032. if (string) {
  1033. return +number.toFixed(string.length);
  1034. } else {
  1035. return this.toFixed(number);
  1036. }
  1037. },
  1038. calcWithStep: function (percent) {
  1039. var rounded = Math.round(percent / this.coords.p_step) * this.coords.p_step;
  1040. if (rounded > 100) {
  1041. rounded = 100;
  1042. }
  1043. if (percent === 100) {
  1044. rounded = 100;
  1045. }
  1046. return this.toFixed(rounded);
  1047. },
  1048. checkMinInterval: function (p_current, p_next, type) {
  1049. var o = this.options,
  1050. current,
  1051. next;
  1052. if (!o.min_interval) {
  1053. return p_current;
  1054. }
  1055. current = this.calcReal(p_current);
  1056. next = this.calcReal(p_next);
  1057. if (type === "from") {
  1058. if (next - current < o.min_interval) {
  1059. current = next - o.min_interval;
  1060. }
  1061. } else {
  1062. if (current - next < o.min_interval) {
  1063. current = next + o.min_interval;
  1064. }
  1065. }
  1066. return this.calcPercent(current);
  1067. },
  1068. checkMaxInterval: function (p_current, p_next, type) {
  1069. var o = this.options,
  1070. current,
  1071. next;
  1072. if (!o.max_interval) {
  1073. return p_current;
  1074. }
  1075. current = this.calcReal(p_current);
  1076. next = this.calcReal(p_next);
  1077. if (type === "from") {
  1078. if (next - current > o.max_interval) {
  1079. current = next - o.max_interval;
  1080. }
  1081. } else {
  1082. if (current - next > o.max_interval) {
  1083. current = next + o.max_interval;
  1084. }
  1085. }
  1086. return this.calcPercent(current);
  1087. },
  1088. checkDiapason: function (p_num, min, max) {
  1089. var num = this.calcReal(p_num),
  1090. o = this.options;
  1091. if (!min || typeof min !== "number") {
  1092. min = o.min;
  1093. }
  1094. if (!max || typeof max !== "number") {
  1095. max = o.max;
  1096. }
  1097. if (num < min) {
  1098. num = min;
  1099. }
  1100. if (num > max) {
  1101. num = max;
  1102. }
  1103. return this.calcPercent(num);
  1104. },
  1105. toFixed: function (num) {
  1106. num = num.toFixed(5);
  1107. return +num;
  1108. },
  1109. _prettify: function (num) {
  1110. if (!this.options.prettify_enabled) {
  1111. return num;
  1112. }
  1113. if (this.options.prettify && typeof this.options.prettify === "function") {
  1114. return this.options.prettify(num);
  1115. } else {
  1116. return this.prettify(num);
  1117. }
  1118. },
  1119. prettify: function (num) {
  1120. var n = num.toString();
  1121. return n.replace(/(\d{1,3}(?=(?:\d\d\d)+(?!\d)))/g, "$1" + this.options.prettify_separator);
  1122. },
  1123. checkEdges: function (left, width) {
  1124. if (!this.options.force_edges) {
  1125. return this.toFixed(left);
  1126. }
  1127. if (left < 0) {
  1128. left = 0;
  1129. } else if (left > 100 - width) {
  1130. left = 100 - width;
  1131. }
  1132. return this.toFixed(left);
  1133. },
  1134. validate: function () {
  1135. var o = this.options,
  1136. r = this.result,
  1137. v = o.values,
  1138. vl = v.length,
  1139. value,
  1140. i;
  1141. if (typeof o.min === "string") o.min = +o.min;
  1142. if (typeof o.max === "string") o.max = +o.max;
  1143. if (typeof o.from === "string") o.from = +o.from;
  1144. if (typeof o.to === "string") o.to = +o.to;
  1145. if (typeof o.step === "string") o.step = +o.step;
  1146. if (typeof o.from_min === "string") o.from_min = +o.from_min;
  1147. if (typeof o.from_max === "string") o.from_max = +o.from_max;
  1148. if (typeof o.to_min === "string") o.to_min = +o.to_min;
  1149. if (typeof o.to_max === "string") o.to_max = +o.to_max;
  1150. if (typeof o.keyboard_step === "string") o.keyboard_step = +o.keyboard_step;
  1151. if (typeof o.grid_num === "string") o.grid_num = +o.grid_num;
  1152. if (o.max <= o.min) {
  1153. if (o.min) {
  1154. o.max = o.min * 2;
  1155. } else {
  1156. o.max = o.min + 1;
  1157. }
  1158. o.step = 1;
  1159. }
  1160. if (vl) {
  1161. o.p_values = [];
  1162. o.min = 0;
  1163. o.max = vl - 1;
  1164. o.step = 1;
  1165. o.grid_num = o.max;
  1166. o.grid_snap = true;
  1167. for (i = 0; i < vl; i++) {
  1168. value = +v[i];
  1169. if (!isNaN(value)) {
  1170. v[i] = value;
  1171. value = this._prettify(value);
  1172. } else {
  1173. value = v[i];
  1174. }
  1175. o.p_values.push(value);
  1176. }
  1177. }
  1178. if (typeof o.from !== "number" || isNaN(o.from)) {
  1179. o.from = o.min;
  1180. }
  1181. if (typeof o.to !== "number" || isNaN(o.from)) {
  1182. o.to = o.max;
  1183. }
  1184. if (o.from < o.min || o.from > o.max) {
  1185. o.from = o.min;
  1186. }
  1187. if (o.to > o.max || o.to < o.min) {
  1188. o.to = o.max;
  1189. }
  1190. if (o.type === "double" && o.from > o.to) {
  1191. o.from = o.to;
  1192. }
  1193. if (typeof o.step !== "number" || isNaN(o.step) || !o.step || o.step < 0) {
  1194. o.step = 1;
  1195. }
  1196. if (typeof o.keyboard_step !== "number" || isNaN(o.keyboard_step) || !o.keyboard_step || o.keyboard_step < 0) {
  1197. o.keyboard_step = 5;
  1198. }
  1199. if (o.from_min && o.from < o.from_min) {
  1200. o.from = o.from_min;
  1201. }
  1202. if (o.from_max && o.from > o.from_max) {
  1203. o.from = o.from_max;
  1204. }
  1205. if (o.to_min && o.to < o.to_min) {
  1206. o.to = o.to_min;
  1207. }
  1208. if (o.to_max && o.from > o.to_max) {
  1209. o.to = o.to_max;
  1210. }
  1211. if (r) {
  1212. if (r.min !== o.min) {
  1213. r.min = o.min;
  1214. }
  1215. if (r.max !== o.max) {
  1216. r.max = o.max;
  1217. }
  1218. if (r.from < r.min || r.from > r.max) {
  1219. r.from = o.from;
  1220. }
  1221. if (r.to < r.min || r.to > r.max) {
  1222. r.to = o.to;
  1223. }
  1224. }
  1225. if (typeof o.min_interval !== "number" || isNaN(o.min_interval) || !o.min_interval || o.min_interval < 0) {
  1226. o.min_interval = 0;
  1227. }
  1228. if (typeof o.max_interval !== "number" || isNaN(o.max_interval) || !o.max_interval || o.max_interval < 0) {
  1229. o.max_interval = 0;
  1230. }
  1231. if (o.min_interval && o.min_interval > o.max - o.min) {
  1232. o.min_interval = o.max - o.min;
  1233. }
  1234. if (o.max_interval && o.max_interval > o.max - o.min) {
  1235. o.max_interval = o.max - o.min;
  1236. }
  1237. },
  1238. decorate: function (num, original) {
  1239. var decorated = "",
  1240. o = this.options;
  1241. if (o.prefix) {
  1242. decorated += o.prefix;
  1243. }
  1244. decorated += num;
  1245. if (o.max_postfix) {
  1246. if (o.values.length && num === o.p_values[o.max]) {
  1247. decorated += o.max_postfix;
  1248. if (o.postfix) {
  1249. decorated += " ";
  1250. }
  1251. } else if (original === o.max) {
  1252. decorated += o.max_postfix;
  1253. if (o.postfix) {
  1254. decorated += " ";
  1255. }
  1256. }
  1257. }
  1258. if (o.postfix) {
  1259. decorated += o.postfix;
  1260. }
  1261. return decorated;
  1262. },
  1263. updateFrom: function () {
  1264. this.result.from = this.options.from;
  1265. this.result.from_percent = this.calcPercent(this.result.from);
  1266. if (this.options.values) {
  1267. this.result.from_value = this.options.values[this.result.from];
  1268. }
  1269. },
  1270. updateTo: function () {
  1271. this.result.to = this.options.to;
  1272. this.result.to_percent = this.calcPercent(this.result.to);
  1273. if (this.options.values) {
  1274. this.result.to_value = this.options.values[this.result.to];
  1275. }
  1276. },
  1277. updateResult: function () {
  1278. this.result.min = this.options.min;
  1279. this.result.max = this.options.max;
  1280. this.updateFrom();
  1281. this.updateTo();
  1282. },
  1283. // =============================================================================================================
  1284. // Grid
  1285. appendGrid: function () {
  1286. if (!this.options.grid) {
  1287. return;
  1288. }
  1289. var o = this.options,
  1290. i, z,
  1291. total = o.max - o.min,
  1292. big_num = o.grid_num,
  1293. big_p = 0,
  1294. big_w = 0,
  1295. small_max = 4,
  1296. local_small_max,
  1297. small_p,
  1298. small_w = 0,
  1299. result,
  1300. html = '';
  1301. this.calcGridMargin();
  1302. if (o.grid_snap) {
  1303. big_num = total / o.step;
  1304. big_p = this.toFixed(o.step / (total / 100));
  1305. } else {
  1306. big_p = this.toFixed(100 / big_num);
  1307. }
  1308. if (big_num > 4) {
  1309. small_max = 3;
  1310. }
  1311. if (big_num > 7) {
  1312. small_max = 2;
  1313. }
  1314. if (big_num > 14) {
  1315. small_max = 1;
  1316. }
  1317. if (big_num > 28) {
  1318. small_max = 0;
  1319. }
  1320. for (i = 0; i < big_num + 1; i++) {
  1321. local_small_max = small_max;
  1322. big_w = this.toFixed(big_p * i);
  1323. if (big_w > 100) {
  1324. big_w = 100;
  1325. local_small_max -= 2;
  1326. if (local_small_max < 0) {
  1327. local_small_max = 0;
  1328. }
  1329. }
  1330. this.coords.big[i] = big_w;
  1331. small_p = (big_w - (big_p * (i - 1))) / (local_small_max + 1);
  1332. for (z = 1; z <= local_small_max; z++) {
  1333. if (big_w === 0) {
  1334. break;
  1335. }
  1336. small_w = this.toFixed(big_w - (small_p * z));
  1337. html += '<span class="irs-grid-pol small" style="left: ' + small_w + '%"></span>';
  1338. }
  1339. html += '<span class="irs-grid-pol" style="left: ' + big_w + '%"></span>';
  1340. result = this.calcReal(big_w);
  1341. if (o.values.length) {
  1342. result = o.p_values[result];
  1343. } else {
  1344. result = this._prettify(result);
  1345. }
  1346. html += '<span class="irs-grid-text js-grid-text-' + i + '" style="left: ' + big_w + '%">' + result + '</span>';
  1347. }
  1348. this.coords.big_num = Math.ceil(big_num + 1);
  1349. this.$cache.cont.addClass("irs-with-grid");
  1350. this.$cache.grid.html(html);
  1351. this.cacheGridLabels();
  1352. },
  1353. cacheGridLabels: function () {
  1354. var $label, i,
  1355. num = this.coords.big_num;
  1356. for (i = 0; i < num; i++) {
  1357. $label = this.$cache.grid.find(".js-grid-text-" + i);
  1358. this.$cache.grid_labels.push($label);
  1359. }
  1360. this.calcGridLabels();
  1361. },
  1362. calcGridLabels: function () {
  1363. var i, label, start = [], finish = [],
  1364. num = this.coords.big_num;
  1365. for (i = 0; i < num; i++) {
  1366. this.coords.big_w[i] = this.$cache.grid_labels[i].outerWidth(false);
  1367. this.coords.big_p[i] = this.toFixed(this.coords.big_w[i] / this.coords.w_rs * 100);
  1368. this.coords.big_x[i] = this.toFixed(this.coords.big_p[i] / 2);
  1369. start[i] = this.toFixed(this.coords.big[i] - this.coords.big_x[i]);
  1370. finish[i] = this.toFixed(start[i] + this.coords.big_p[i]);
  1371. }
  1372. if (this.options.force_edges) {
  1373. if (start[0] < this.coords.grid_gap) {
  1374. start[0] = this.coords.grid_gap;
  1375. finish[0] = this.toFixed(start[0] + this.coords.big_p[0]);
  1376. this.coords.big_x[0] = this.coords.grid_gap;
  1377. }
  1378. if (finish[num - 1] > 100 - this.coords.grid_gap) {
  1379. finish[num - 1] = 100 - this.coords.grid_gap;
  1380. start[num - 1] = this.toFixed(finish[num - 1] - this.coords.big_p[num - 1]);
  1381. this.coords.big_x[num - 1] = this.toFixed(this.coords.big_p[num - 1] - this.coords.grid_gap);
  1382. }
  1383. }
  1384. this.calcGridCollision(2, start, finish);
  1385. this.calcGridCollision(4, start, finish);
  1386. for (i = 0; i < num; i++) {
  1387. label = this.$cache.grid_labels[i][0];
  1388. label.style.marginLeft = -this.coords.big_x[i] + "%";
  1389. }
  1390. },
  1391. // Collisions Calc Beta
  1392. // TODO: Refactor then have plenty of time
  1393. calcGridCollision: function (step, start, finish) {
  1394. var i, next_i, label,
  1395. num = this.coords.big_num;
  1396. for (i = 0; i < num; i += step) {
  1397. next_i = i + (step / 2);
  1398. if (next_i >= num) {
  1399. break;
  1400. }
  1401. label = this.$cache.grid_labels[next_i][0];
  1402. if (finish[i] <= start[next_i]) {
  1403. label.style.visibility = "visible";
  1404. } else {
  1405. label.style.visibility = "hidden";
  1406. }
  1407. }
  1408. },
  1409. calcGridMargin: function () {
  1410. if (!this.options.grid_margin) {
  1411. return;
  1412. }
  1413. this.coords.w_rs = this.$cache.rs.outerWidth(false);
  1414. if (!this.coords.w_rs) {
  1415. return;
  1416. }
  1417. if (this.options.type === "single") {
  1418. this.coords.w_handle = this.$cache.s_single.outerWidth(false);
  1419. } else {
  1420. this.coords.w_handle = this.$cache.s_from.outerWidth(false);
  1421. }
  1422. this.coords.p_handle = this.toFixed(this.coords.w_handle / this.coords.w_rs * 100);
  1423. this.coords.grid_gap = this.toFixed((this.coords.p_handle / 2) - 0.1);
  1424. this.$cache.grid[0].style.width = this.toFixed(100 - this.coords.p_handle) + "%";
  1425. this.$cache.grid[0].style.left = this.coords.grid_gap + "%";
  1426. },
  1427. // =============================================================================================================
  1428. // Public methods
  1429. update: function (options) {
  1430. if (!this.input) {
  1431. return;
  1432. }
  1433. this.is_update = true;
  1434. this.options.from = this.result.from;
  1435. this.options.to = this.result.to;
  1436. this.options = $.extend(this.options, options);
  1437. this.validate();
  1438. this.updateResult(options);
  1439. this.toggleInput();
  1440. this.remove();
  1441. this.init(true);
  1442. },
  1443. reset: function () {
  1444. if (!this.input) {
  1445. return;
  1446. }
  1447. this.updateResult();
  1448. this.update();
  1449. },
  1450. destroy: function () {
  1451. if (!this.input) {
  1452. return;
  1453. }
  1454. this.toggleInput();
  1455. this.$cache.input.prop("readonly", false);
  1456. $.data(this.input, "ionRangeSlider", null);
  1457. this.remove();
  1458. this.input = null;
  1459. this.options = null;
  1460. }
  1461. };
  1462. $.fn.ionRangeSlider = function (options) {
  1463. return this.each(function() {
  1464. if (!$.data(this, "ionRangeSlider")) {
  1465. $.data(this, "ionRangeSlider", new IonRangeSlider(this, options, plugin_count++));
  1466. }
  1467. });
  1468. };
  1469. // =================================================================================================================
  1470. // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
  1471. // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
  1472. // requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
  1473. // MIT license
  1474. (function() {
  1475. var lastTime = 0;
  1476. var vendors = ['ms', 'moz', 'webkit', 'o'];
  1477. for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
  1478. window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
  1479. window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
  1480. || window[vendors[x]+'CancelRequestAnimationFrame'];
  1481. }
  1482. if (!window.requestAnimationFrame)
  1483. window.requestAnimationFrame = function(callback, element) {
  1484. var currTime = new Date().getTime();
  1485. var timeToCall = Math.max(0, 16 - (currTime - lastTime));
  1486. var id = window.setTimeout(function() { callback(currTime + timeToCall); },
  1487. timeToCall);
  1488. lastTime = currTime + timeToCall;
  1489. return id;
  1490. };
  1491. if (!window.cancelAnimationFrame)
  1492. window.cancelAnimationFrame = function(id) {
  1493. clearTimeout(id);
  1494. };
  1495. }());
  1496. } (jQuery, document, window, navigator));