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