1(function (factory) { 2 'use strict'; 3 4 if (typeof define === 'function' && define.amd) { 5 // AMD. Register as an anonymous module. 6 define([], factory); 7 } 8 else if (typeof module === 'object' && module !== null && module.exports) { 9 // CommonJS 10 module.exports = factory(); 11 } else { 12 // Browser globals 13 /* jshint ignore:start */ 14 window['rangeSlider'] = factory(); 15 /* jshint ignore:end */ 16 } 17}(function () { 18 'use strict'; 19 20 var EVENT_LISTENER_LIST = 'eventListenerList'; 21 var newLineAndTabRegexp = new RegExp('/[\\n\\t]/', 'g'); 22 var MAX_SET_BY_DEFAULT = 100; 23 var HANDLE_RESIZE_DELAY = 300; 24 var HANDLE_RESIZE_DEBOUNCE = 50; 25 26 /** 27 * Range feature detection 28 * @return {Boolean} 29 */ 30 function supportsRange() { 31 var input = document.createElement('input'); 32 input.setAttribute('type', 'range'); 33 return input.type !== 'text'; 34 } 35 36 var pluginName = 'rangeSlider', 37 pluginIdentifier = 0, 38 inputrange = supportsRange(), 39 defaults = { 40 polyfill: true, 41 rangeClass: 'rangeSlider', 42 disabledClass: 'rangeSlider--disabled', 43 fillClass: 'rangeSlider__fill', 44 bufferClass: 'rangeSlider__buffer', 45 handleClass: 'rangeSlider__handle', 46 startEvent: ['mousedown', 'touchstart', 'pointerdown'], 47 moveEvent: ['mousemove', 'touchmove', 'pointermove'], 48 endEvent: ['mouseup', 'touchend', 'pointerup'], 49 min: null, 50 max: null, 51 step: null, 52 value: null, 53 buffer: null, 54 borderRadius: 10 55 }; 56 57 /** 58 * Delays a function for the given number of milliseconds, and then calls 59 * it with the arguments supplied. 60 * 61 * @param {Function} fn [description] 62 * @param {Number} wait [description] 63 * @return {Function} 64 */ 65 function delay(fn, wait) { 66 var args = Array.prototype.slice.call(arguments, 2); 67 return setTimeout(function () { 68 return fn.apply(null, args); 69 }, wait); 70 } 71 72 /** 73 * Returns a debounced function that will make sure the given 74 * function is not triggered too much. 75 * 76 * @param {Function} fn Function to debounce. 77 * @param {Number} debounceDuration OPTIONAL. The amount of time in milliseconds for which we will debounce the function. (defaults to 100ms) 78 * @return {Function} 79 */ 80 function debounce(fn, debounceDuration) { 81 debounceDuration = debounceDuration || 100; 82 return function () { 83 if (!fn.debouncing) { 84 var args = Array.prototype.slice.apply(arguments); 85 fn.lastReturnVal = fn.apply(window, args); 86 fn.debouncing = true; 87 } 88 clearTimeout(fn.debounceTimeout); 89 fn.debounceTimeout = setTimeout(function () { 90 fn.debouncing = false; 91 }, debounceDuration); 92 return fn.lastReturnVal; 93 }; 94 } 95 96 /** 97 * Check if a `element` is visible in the DOM 98 * 99 * @param {Element} element 100 * @return {Boolean} 101 */ 102 function isHidden(element) { 103 return !!(element.offsetWidth === 0 || element.offsetHeight === 0 || element.open === false); 104 105 } 106 107 /** 108 * Get hidden parentNodes of an `element` 109 * 110 * @param {Element} element 111 * @return {[type]} 112 */ 113 function getHiddenParentNodes(element) { 114 var parents = [], 115 node = element.parentNode; 116 117 while (isHidden(node)) { 118 parents.push(node); 119 node = node.parentNode; 120 } 121 return parents; 122 } 123 124 /** 125 * Returns dimensions for an element even if it is not visible in the DOM. 126 * 127 * @param {Element} element 128 * @param {string} key (e.g. offsetWidth ââ¬Â¦) 129 * @return {Number} 130 */ 131 function getDimension(element, key) { 132 var hiddenParentNodes = getHiddenParentNodes(element), 133 hiddenParentNodesLength = hiddenParentNodes.length, 134 displayProperty = [], 135 dimension = element[key]; 136 137 // Used for native `<details>` elements 138 function toggleOpenProperty(element) { 139 if (typeof element.open !== 'undefined') { 140 element.open = (element.open) ? false : true; 141 } 142 } 143 144 if (hiddenParentNodesLength) { 145 for (var i = 0; i < hiddenParentNodesLength; i++) { 146 // Cache the display property to restore it later. 147 displayProperty[i] = hiddenParentNodes[i].style.display; 148 149 hiddenParentNodes[i].style.display = 'block'; 150 hiddenParentNodes[i].style.height = '0'; 151 hiddenParentNodes[i].style.overflow = 'hidden'; 152 hiddenParentNodes[i].style.visibility = 'hidden'; 153 toggleOpenProperty(hiddenParentNodes[i]); 154 } 155 156 dimension = element[key]; 157 158 for (var j = 0; j < hiddenParentNodesLength; j++) { 159 toggleOpenProperty(hiddenParentNodes[j]); 160 hiddenParentNodes[j].style.display = displayProperty[j]; 161 hiddenParentNodes[j].style.height = ''; 162 hiddenParentNodes[j].style.overflow = ''; 163 hiddenParentNodes[j].style.visibility = ''; 164 } 165 } 166 return dimension; 167 } 168 169 function isString(obj) { 170 return obj === '' + obj; 171 } 172 173 function isNumberLike(obj) { 174 return (obj !== null && obj !== undefined && (isString(obj) && isFinite(parseFloat(obj)) || (isFinite(obj)))); 175 } 176 177 function getFirsNumberLike() { 178 if (!arguments.length) { 179 return null; 180 } 181 for (var i = 0, len = arguments.length; i < len; i++) { 182 if (isNumberLike(arguments[i])) { 183 return arguments[i]; 184 } 185 } 186 } 187 188 function isObject(obj) { 189 return Object.prototype.toString.call(obj) === '[object Object]'; 190 } 191 192 function simpleExtend(defaultOpt, options) { 193 var opt = {}, key; 194 for (key in defaultOpt) { 195 opt[key] = defaultOpt[key]; 196 } 197 for (key in options) { 198 opt[key] = options[key]; 199 } 200 201 return opt; 202 } 203 204 /** 205 * 206 * @param {HTMLElement} el 207 * @param {Object} cssObj 208 * @returns {*} 209 */ 210 function setCss(el, cssObj) { 211 for (var key in cssObj) { 212 el.style[key] = cssObj[key]; 213 } 214 return el.style; 215 } 216 217 /** 218 * 219 * @param {HTMLElement} elem 220 * @param {string} className 221 */ 222 function addClass(elem, className) { 223 if (!hasClass(elem, className)) { 224 elem.className += ' ' + className; 225 } 226 } 227 228 /** 229 * 230 * @param {HTMLElement} elem 231 * @param {string} className 232 */ 233 function removeClass(elem, className) { 234 var newClass = ' ' + elem.className.replace(/[\t\r\n]/g, ' ') + ' '; 235 if (hasClass(elem, className)) { 236 while (newClass.indexOf(' ' + className + ' ') >= 0) { 237 newClass = newClass.replace(' ' + className + ' ', ' '); 238 } 239 elem.className = newClass.replace(/^\s+|\s+$/g, ''); 240 } 241 } 242 243 244 /** 245 * 246 * @param {HTMLElement} el 247 * @callback callback 248 * @param {boolean} andForElement - apply callback for el 249 * @returns {HTMLElement} 250 */ 251 function forEachAncestors(el, callback, andForElement) { 252 if (andForElement) { 253 callback(el); 254 } 255 256 while (el.parentNode && !callback(el)) { 257 el = el.parentNode; 258 } 259 260 return el; 261 } 262 263 /** 264 * 265 * @param {HTMLElement} el 266 * @param {string} name event name 267 * @param {Object} data 268 */ 269 function triggerEvent(el, name, data) { 270 if (!isString(name)) { 271 throw new TypeError('event name must be String'); 272 } 273 if (!(el instanceof HTMLElement)) { 274 throw new TypeError('element must be HTMLElement'); 275 } 276 name = name.trim(); 277 var event = document.createEvent('CustomEvent'); 278 event.initCustomEvent(name, false, false, data); 279 el.dispatchEvent(event); 280 } 281 282 /** 283 * 284 * @param {HTMLElement} elem 285 * @param {string} className 286 */ 287 function hasClass(elem, className) { 288 return new RegExp(' ' + className + ' ').test(' ' + elem.className + ' '); 289 } 290 291 /** 292 * @param {Object} referenceNode after this 293 * @param {Object} newNode insert this 294 */ 295 function insertAfter(referenceNode, newNode) { 296 referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling); 297 } 298 299 /** 300 * Add event listeners and push them to el[EVENT_LISTENER_LIST] 301 * @param {HTMLElement} el DOM element 302 * @param {Array} events 303 * @callback listener 304 */ 305 function addEventListeners(el, events, listener) {
306 events.forEach(function (eventName) { 307 if (!el[EVENT_LISTENER_LIST]) { 308 el[EVENT_LISTENER_LIST] = {}; 309 } 310 if (!el[EVENT_LISTENER_LIST][eventName]) { 311 el[EVENT_LISTENER_LIST][eventName] = []; 312 } 313 314 el.addEventListener( 315 eventName, 316 listener, 317 false 318 ); 319 if (el[EVENT_LISTENER_LIST][eventName].indexOf(listener) < 0) { 320 el[EVENT_LISTENER_LIST][eventName].push(listener); 321 } 322 }); 323 } 324 325 /** 326 * Remove event listeners and remove them from el[EVENT_LISTENER_LIST] 327 * @param {HTMLElement} el DOM element 328 * @param {Array} events 329 * @callback listener 330 */ 331 function removeEventListeners(el, events, listener) { 332 events.forEach(function (eventName) { 333 el.removeEventListener( 334 eventName, 335 listener, 336 false 337 ); 338 339 var index; 340 if (el[EVENT_LISTENER_LIST] && el[EVENT_LISTENER_LIST][eventName] && 341 (index = el[EVENT_LISTENER_LIST][eventName].indexOf(listener)) > -1 342 ) { 343 el[EVENT_LISTENER_LIST][eventName].splice(index, 1); 344 } 345 }); 346 } 347 348 /** 349 * Remove ALL event listeners which exists in el[EVENT_LISTENER_LIST] 350 * @param {HTMLElement} el DOM element 351 */ 352 function removeAllListenersFromEl(el) { 353 if (!el[EVENT_LISTENER_LIST]) { 354 return; 355 } 356 /* jshint ignore:start */ 357 var instance = this; 358 359 /** 360 * 361 * @callback listener 362 * @this {Object} event name 363 */ 364 function rm(listener) { 365 if (listener === instance._startEventListener) { 366 this.el.removeEventListener(this.eventName, listener, false); 367 } 368 } 369 370 for (var eventName in el[EVENT_LISTENER_LIST]) { 371 el[EVENT_LISTENER_LIST][eventName].forEach(rm, {eventName: eventName, el: el}); 372 } 373 374 el[EVENT_LISTENER_LIST] = {}; 375 /* jshint ignore:end */ 376 } 377 378 379 /** 380 * Plugin 381 * @param {HTMLElement} element 382 * @param {this} options 383 */ 384 function Plugin(element, options) { 385 var minSetByDefault, maxSetByDefault, stepSetByDefault; 386 this.element = element; 387 this.options = simpleExtend(defaults, options); 388 this.polyfill = this.options.polyfill; 389 this.onInit = this.options.onInit; 390 this.onSlide = this.options.onSlide; 391 this.onSlideStart = this.options.onSlideStart; 392 this.onSlideEnd = this.options.onSlideEnd; 393 this.onSlideEventsCount = -1; 394 this.isInteractsNow = false; 395 this.needTriggerEvents = false; 396 397 // Plugin should only be used as a polyfill 398 if (!this.polyfill) { 399 // Input range support? 400 if (inputrange) { 401 return false; 402 } 403 } 404 405 this.options.buffer = this.options.buffer || parseFloat(this.element.getAttribute('data-buffer')); 406 407 this.identifier = 'js-' + pluginName + '-' + (pluginIdentifier++); 408 this.min = getFirsNumberLike(this.options.min, parseFloat(this.element.getAttribute('min')), (minSetByDefault = 0)); 409 this.max = getFirsNumberLike(this.options.max, parseFloat(this.element.getAttribute('max')), (maxSetByDefault = MAX_SET_BY_DEFAULT)); 410 this.value = getFirsNumberLike(this.options.value, this.element.value, 411 parseFloat(this.element.value || this.min + (this.max - this.min) / 2)); 412 this.step = getFirsNumberLike(this.options.step, 413 parseFloat(this.element.getAttribute('step')) || (stepSetByDefault = 1)); 414 this.percent = null; 415 this._updatePercentFromValue(); 416 417 this.toFixed = this._toFixed(this.step); 418 419 420 this.fill = document.createElement('div'); 421 this.fill.className = this.options.fillClass; 422 423 this.handle = document.createElement('div'); 424 this.handle.className = this.options.handleClass; 425 426 this.handle_icon1 = document.createElement('i'); 427 this.handle_icon2 = document.createElement('i'); 428 this.handle_icon1.className = 'icon-layout'; 429 this.handle_icon2.className = 'icon-layout'; 430 431 this.range = document.createElement('div'); 432 this.range.className = this.options.rangeClass; 433 this.range.id = this.identifier; 434 this.range.appendChild(this.handle); 435 this.range.appendChild(this.fill); 436 this.handle.appendChild(this.handle_icon1); 437 this.handle.appendChild(this.handle_icon2); 438 439 if (this.options.bufferClass) { 440 this.buffer = document.createElement('div'); 441 this.buffer.className = this.options.bufferClass; 442 this.range.appendChild(this.buffer); 443 } 444 445 if (isNumberLike(this.options.value)) { 446 this._setValue(this.options.value, true); 447 this.element.value = this.options.value; 448 } 449 450 if (isNumberLike(this.options.buffer)) { 451 this.element.setAttribute('data-buffer', this.options.buffer); 452 } 453 454 if (isNumberLike(this.options.min) || minSetByDefault) { 455 this.element.setAttribute('min', '' + this.min); 456 } 457 458 if (isNumberLike(this.options.max) || maxSetByDefault) { 459 this.element.setAttribute('max', '' + this.max); 460 } 461 462 if (isNumberLike(this.options.step) || stepSetByDefault) { 463 this.element.setAttribute('step', '' + this.step); 464 } 465 466 insertAfter(this.element, this.range); 467 468 // visually hide the input 469 setCss(this.element, { 470 'position': 'absolute', 471 'width': '1px', 472 'height': '1px', 473 'overflow': 'hidden', 474 'opacity': '0' 475 }); 476 477 // Store context 478 this._handleDown = this._handleDown.bind(this); 479 this._handleMove = this._handleMove.bind(this); 480 this._handleEnd = this._handleEnd.bind(this); 481 this._startEventListener = this._startEventListener.bind(this); 482 this._changeEventListener = this._changeEventListener.bind(this); 483 this._handleResize = this._handleResize.bind(this); 484 485 this._init(); 486 487 //// Attach Events 488 window.addEventListener('resize', this._handleResize, false); 489 490 addEventListeners(document, this.options.startEvent, this._startEventListener); 491 492 // Listen to programmatic value changes 493 this.element.addEventListener('change', this._changeEventListener, false); 494 } 495 496 Plugin.prototype.constructor = Plugin; 497 498 Plugin.prototype._toFixed = function (step) { 499 return (step + '').replace('.', '').length - 1; 500 }; 501 502 503 Plugin.prototype._init = function () { 504 if (this.onInit && typeof this.onInit === 'function') { 505 this.onInit(); 506 } 507 this._update(); 508 }; 509 510 Plugin.prototype._updatePercentFromValue = function () { 511 this.percent = (this.value - this.min) / (this.max - this.min); 512 }; 513 514 /** 515 * This method check if this.identifier exists in ev.target's ancestors 516 * @param ev 517 * @param data 518 */ 519 Plugin.prototype._startEventListener = function (ev, data) { 520 var _this = this; 521 var el = ev.target; 522 var isEventOnSlider = false;
523 forEachAncestors(el, function (el) { 524 return (isEventOnSlider = el.id === _this.identifier && !hasClass(el, _this.options.disabledClass)); 525 }, true); 526 if (isEventOnSlider) { 527 this._handleDown(ev, data); 528 } 529 }; 530 531 Plugin.prototype._changeEventListener = function (ev, data) { 532 if (data && data.origin === this.identifier) { 533 return; 534 } 535 536 var value = ev.target.value, 537 pos = this._getPositionFromValue(value); 538 this._setPosition(pos); 539 }; 540 541 Plugin.prototype._update = function () { 542 this.handleWidth = getDimension(this.handle, 'offsetWidth'); 543 this.rangeWidth = getDimension(this.range, 'offsetWidth'); 544 this.maxHandleX = this.rangeWidth - this.handleWidth; 545 this.grabX = this.handleWidth / 2; 546 this.position = this._getPositionFromValue(this.value); 547 548 // Consider disabled state 549 if (this.element.disabled) { 550 addClass(this.range, this.options.disabledClass); 551 } else { 552 removeClass(this.range, this.options.disabledClass); 553 } 554 555 this._setPosition(this.position); 556 if (this.options.bufferClass && this.options.buffer) { 557 this._setBufferPosition(this.options.buffer); 558 } 559 this._updatePercentFromValue(); 560 triggerEvent(this.element, 'change', {origin: this.identifier}); 561 }; 562 563 564 Plugin.prototype._handleResize = function () { 565 var _this = this; 566 return debounce(function () { 567 // Simulate resizeEnd event. 568 delay(function () { 569 _this._update(); 570 }, HANDLE_RESIZE_DELAY); 571 }, HANDLE_RESIZE_DEBOUNCE)(); 572 }; 573 574 Plugin.prototype._handleDown = function (e) { 575 this.isInteractsNow = true; 576 e.preventDefault(); 577 addEventListeners(document, this.options.moveEvent, this._handleMove); 578 addEventListeners(document, this.options.endEvent, this._handleEnd); 579 580 // If we click on the handle don't set the new position 581 if ((' ' + e.target.className + ' ').replace(newLineAndTabRegexp, ' ').indexOf(this.options.handleClass) > -1) { 582 return; 583 } 584 585 var posX = this._getRelativePosition(e), 586 rangeX = this.range.getBoundingClientRect().left, 587 handleX = this._getPositionFromNode(this.handle) - rangeX; 588 589 this._setPosition(posX - this.grabX); 590 591 if (posX >
591= handleX && posX < handleX + this.handleWidth) { 592 this.grabX = posX - handleX; 593 } 594 this._updatePercentFromValue(); 595 }; 596 597 Plugin.prototype._handleMove = function (e) { 598 this.isInteractsNow = true; 599 e.preventDefault(); 600 var posX = this._getRelativePosition(e); 601 this._setPosition(posX - this.grabX); 602 //this.isInteractsNow = false; 603 }; 604 605 Plugin.prototype._handleEnd = function (e) { 606 e.preventDefault(); 607 removeEventListeners(document, this.options.moveEvent, this._handleMove); 608 removeEventListeners(document, this.options.endEvent, this._handleEnd); 609 610 // Ok we're done fire the change event 611 triggerEvent(this.element, 'change', {origin: this.identifier}); 612 613 if (this.isInteractsNow || this.needTriggerEvents) { 614 if (this.onSlideEnd && typeof this.onSlideEnd === 'function') { 615 this.onSlideEnd(this.value, this.percent, this.position); 616 } 617 } 618 this.onSlideEventsCount = 0; 619 this.isInteractsNow = false; 620 }; 621 622 Plugin.prototype._cap = function (pos, min, max) { 623 if (pos < min) { 624 return min; 625 } 626 if (pos > max) { 627 return max; 628 } 629 return pos; 630 }; 631 632 Plugin.prototype._setPosition = function (pos) { 633 var value, left; 634 635 // Snapping steps 636 value = this._getValueFromPosition(this._cap(pos, 0, this.maxHandleX)); 637 left = this._getPositionFromValue(value); 638 639 // Update ui 640 this.fill.style.width = (left + this.grabX) + 'px'; 641 this.handle.style.left = left + 'px'; 642 this._setValue(value); 643 644 // Update globals 645 this.position = left; 646 this.value = value; 647 this._updatePercentFromValue(); 648 649 if (this.isInteractsNow || this.needTriggerEventss) { 650 if (this.onSlideStart && typeof this.onSlideStart === 'function' && this.onSlideEventsCount === 0) { 651 this.onSlideStart(this.value, this.percent, this.position); 652 } 653 654 if (this.onSlide && typeof this.onSlide === 'function') { 655 this.onSlide(this.value, this.percent, this.position); 656 } 657 } 658 659 this.onSlideEventsCount++; 660 }; 661 662 Plugin.prototype._setBufferPosition = function (pos) { 663 var isPercent = true, 664 bufferWidth, 665 paddingWidth, 666 bufferWidthWithPadding; 667 if (isFinite(pos)) { 668 pos = parseFloat(pos); 669 } else if (isString(pos)) { 670 if (pos.indexOf('px') > 0) { 671 isPercent = false; 672 } 673 pos = parseFloat(pos); 674 } else { 675 console.warn('New position must be XXpx or XX%'); 676 return; 677 } 678 679 if (isNaN(pos)) { 680 console.warn('New position is NaN'); 681 return; 682 } 683 if (!this.options.bufferClass) { 684 console.warn('You disabled buffer, it\'s className is empty'); 685 return; 686 } 687 bufferWidth = isPercent ? pos : (pos / this.rangeWidth * 100); 688 if (bufferWidth < 0) { 689 bufferWidth = 0; 690 } 691 if (bufferWidth > 100) { 692 bufferWidth = 100; 693 } 694 this.options.buffer = bufferWidth; 695 696 paddingWidth = this.options.borderRadius / this.rangeWidth * 100; 697 bufferWidthWithPadding = bufferWidth - paddingWidth; 698 if (bufferWidthWithPadding < 0) { 699 bufferWidthWithPadding = 0; 700 } 701 702 this.buffer.style.width = bufferWidthWithPadding + '%'; 703 this.buffer.style.left = paddingWidth * 0.5 + '%'; 704 this.element.setAttribute('data-buffer', bufferWidth); 705 }; 706 707 // Returns element position relative to the parent 708 Plugin.prototype._getPositionFromNode = function (node) { 709 var i = 0; 710 while (node !== null) { 711 i += node.offsetLeft; 712 node = node.offsetParent; 713 } 714 return i; 715 }; 716 717 /** 718 * 719 * @param {(MouseEvent|TouchEvent)}e 720 * @returns {number} 721 */ 722 Plugin.prototype._getRelativePosition = function (e) { 723 // Get the offset left relative to the viewport 724 var rangeX = this.range.getBoundingClientRect().left, 725 pageX = 0; 726 727 if (typeof e.pageX !== 'undefined') { 728 pageX = (e.touches && e.touches.length) ? e.touches[0].pageX : e.pageX; 729 } 730 else if (typeof e.originalEvent !== 'undefined') { 731 if (typeof e.originalEvent.clientX !== 'undefined') { 732 pageX = e.originalEvent.clientX; 733 } 734 else if (e.originalEvent.touches && e.originalEvent.touches[0] && typeof e.originalEvent.touches[0].clientX !== 'undefined') { 735 pageX = e.originalEvent.touches[0].clientX; 736 } 737 } 738 else if (e.touches && e.touches[0] && typeof e.touches[0].clientX !== 'undefined') { 739 pageX = e.touches[0].clientX; 740 } 741 else if (e.currentPoint && typeof e.currentPoint.x !== 'undefined') { 742 pageX = e.currentPoint.x; 743 } 744 745 return pageX - rangeX; 746 }; 747 748 Plugin.prototype._getPositionFromValue = function (value) { 749 var percentage, pos; 750 percentage = (value - this.min) / (this.max - this.min); 751 pos = percentage * this.maxHandleX; 752 return pos; 753 }; 754 755 Plugin.prototype._getValueFromPosition = function (pos) { 756 var percentage, value;
757 percentage = ((pos) / (this.maxHandleX || 1)); 758 value = this.step * Math.round(percentage * (this.max - this.min) / this.step) + this.min; 759 return Number((value).toFixed(this.toFixed)); 760 }; 761 762 Plugin.prototype._setValue = function (value, force) { 763 if (value === this.value && !force) { 764 return; 765 } 766 767 // Set the new value and fire the `input` event 768 this.element.value = value; 769 this.value = value; 770 triggerEvent(this.element, 'input', {origin: this.identifier}); 771 }; 772 773 774 /** 775 * 776 * @param {Object} obj like {min : Number, max : Number, value : Number, step : Number, buffer : [String|Number]} 777 * @param {Boolean} triggerEvents 778 * @returns {Plugin} 779 */ 780 Plugin.prototype.update = function (obj, triggerEvents) { 781 if (triggerEvents) { 782 this.needTriggerEvents = true; 783 } 784 if (isObject(obj)) { 785 if (isNumberLike(obj.min)) { 786 this.element.setAttribute('min', '' + obj.min); 787 this.min = obj.min; 788 } 789 790 if (isNumberLike(obj.max)) { 791 this.element.setAttribute('max', '' + obj.max); 792 this.max = obj.max; 793 } 794 795 if (isNumberLike(obj.step)) { 796 this.element.setAttribute('step', '' + obj.step); 797 this.step = obj.step; 798 this.toFixed = this._toFixed(obj.step); 799 } 800 801 if (isNumberLike(obj.buffer)) { 802 this._setBufferPosition(obj.buffer); 803 } 804 805 if (isNumberLike(obj.value)) { 806 this._setValue(obj.value); 807 } 808 } 809 this._update(); 810 this.onSlideEventsCount = 0; 811 this.needTriggerEvents = false; 812 return this; 813 }; 814 815 Plugin.prototype.destroy = function () { 816 removeAllListenersFromEl.call(this, document); 817 window.removeEventListener('resize', this._handleResize, false); 818 this.element.removeEventListener('change', this._changeEventListener, false); 819 820 this.element.style.cssText = ''; 821 delete this.element[pluginName]; 822 823 // Remove the generated markup 824 if (this.range) { 825 this.range.parentNode.removeChild(this.range); 826 } 827 }; 828 829 // A really lightweight plugin wrapper around the constructor, 830 // preventing against multiple instantiations 831 832 Plugin.create = function (el, options) { 833 function createInstance(el) { 834 var data = el[pluginName]; 835 836 // Create a new instance. 837 if (!data) { 838 data = new Plugin(el, options); 839 el[pluginName] = data; 840 } 841 } 842 843 if (el.length) { 844 Array.prototype.slice.call(el).forEach(function (el) { 845 createInstance(el); 846 }); 847 } else { 848 createInstance(el); 849 } 850 }; 851 852 return Plugin; 853 854 } 855));
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.