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