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