(function($, anim) { 'use strict'; let _defaults = {}; /** * @class * */ class Range extends Component { /** * Construct Range instance * @constructor * @param {Element} el * @param {Object} options */ constructor(el, options) { super(Range, el, options); this.el.M_Range = this; /** * Options for the range * @member Range#options */ this.options = $.extend({}, Range.defaults, options); this._mousedown = false; // Setup this._setupThumb(); this._setupEventHandlers(); } static get defaults() { return _defaults; } static init(els, options) { return super.init(this, els, options); } /** * Get Instance */ static getInstance(el) { let domElem = !!el.jquery ? el[0] : el; return domElem.M_Range; } /** * Teardown component */ destroy() { this._removeEventHandlers(); this._removeThumb(); this.el.M_Range = undefined; } /** * Setup Event Handlers */ _setupEventHandlers() { this._handleRangeChangeBound = this._handleRangeChange.bind(this); this._handleRangeMousedownTouchstartBound = this._handleRangeMousedownTouchstart.bind(this); this._handleRangeInputMousemoveTouchmoveBound = this._handleRangeInputMousemoveTouchmove.bind( this ); this._handleRangeMouseupTouchendBound = this._handleRangeMouseupTouchend.bind(this); this._handleRangeBlurMouseoutTouchleaveBound = this._handleRangeBlurMouseoutTouchleave.bind( this ); this.el.addEventListener('change', this._handleRangeChangeBound); this.el.addEventListener('mousedown', this._handleRangeMousedownTouchstartBound); this.el.addEventListener('touchstart', this._handleRangeMousedownTouchstartBound); this.el.addEventListener('input', this._handleRangeInputMousemoveTouchmoveBound); this.el.addEventListener('mousemove', this._handleRangeInputMousemoveTouchmoveBound); this.el.addEventListener('touchmove', this._handleRangeInputMousemoveTouchmoveBound); this.el.addEventListener('mouseup', this._handleRangeMouseupTouchendBound); this.el.addEventListener('touchend', this._handleRangeMouseupTouchendBound); this.el.addEventListener('blur', this._handleRangeBlurMouseoutTouchleaveBound); this.el.addEventListener('mouseout', this._handleRangeBlurMouseoutTouchleaveBound); this.el.addEventListener('touchleave', this._handleRangeBlurMouseoutTouchleaveBound); } /** * Remove Event Handlers */ _removeEventHandlers() { this.el.removeEventListener('change', this._handleRangeChangeBound); this.el.removeEventListener('mousedown', this._handleRangeMousedownTouchstartBound); this.el.removeEventListener('touchstart', this._handleRangeMousedownTouchstartBound); this.el.removeEventListener('input', this._handleRangeInputMousemoveTouchmoveBound); this.el.removeEventListener('mousemove', this._handleRangeInputMousemoveTouchmoveBound); this.el.removeEventListener('touchmove', this._handleRangeInputMousemoveTouchmoveBound); this.el.removeEventListener('mouseup', this._handleRangeMouseupTouchendBound); this.el.removeEventListener('touchend', this._handleRangeMouseupTouchendBound); this.el.removeEventListener('blur', this._handleRangeBlurMouseoutTouchleaveBound); this.el.removeEventListener('mouseout', this._handleRangeBlurMouseoutTouchleaveBound); this.el.removeEventListener('touchleave', this._handleRangeBlurMouseoutTouchleaveBound); } /** * Handle Range Change * @param {Event} e */ _handleRangeChange() { $(this.value).html(this.$el.val()); if (!$(this.thumb).hasClass('active')) { this._showRangeBubble(); } let offsetLeft = this._calcRangeOffset(); $(this.thumb) .addClass('active') .css('left', offsetLeft + 'px'); } /** * Handle Range Mousedown and Touchstart * @param {Event} e */ _handleRangeMousedownTouchstart(e) { // Set indicator value $(this.value).html(this.$el.val()); this._mousedown = true; this.$el.addClass('active'); if (!$(this.thumb).hasClass('active')) { this._showRangeBubble(); } if (e.type !== 'input') { let offsetLeft = this._calcRangeOffset(); $(this.thumb) .addClass('active') .css('left', offsetLeft + 'px'); } } /** * Handle Range Input, Mousemove and Touchmove */ _handleRangeInputMousemoveTouchmove() { if (this._mousedown) { if (!$(this.thumb).hasClass('active')) { this._showRangeBubble(); } let offsetLeft = this._calcRangeOffset(); $(this.thumb) .addClass('active') .css('left', offsetLeft + 'px'); $(this.value).html(this.$el.val()); } } /** * Handle Range Mouseup and Touchend */ _handleRangeMouseupTouchend() { this._mousedown = false; this.$el.removeClass('active'); } /** * Handle Range Blur, Mouseout and Touchleave */ _handleRangeBlurMouseoutTouchleave() { if (!this._mousedown) { let paddingLeft = parseInt(this.$el.css('padding-left')); let marginLeft = 7 + paddingLeft + 'px'; if ($(this.thumb).hasClass('active')) { anim.remove(this.thumb); anim({ targets: this.thumb, height: 0, width: 0, top: 10, easing: 'easeOutQuad', marginLeft: marginLeft, duration: 100 }); } $(this.thumb).removeClass('active'); } } /** * Setup dropdown */ _setupThumb() { this.thumb = document.createElement('span'); this.value = document.createElement('span'); $(this.thumb).addClass('thumb'); $(this.value).addClass('value'); $(this.thumb).append(this.value); this.$el.after(this.thumb); } /** * Remove dropdown */ _removeThumb() { $(this.thumb).remove(); } /** * morph thumb into bubble */ _showRangeBubble() { let paddingLeft = parseInt( $(this.thumb) .parent() .css('padding-left') ); let marginLeft = -7 + paddingLeft + 'px'; // TODO: fix magic number? anim.remove(this.thumb); anim({ targets: this.thumb, height: 30, width: 30, top: -30, marginLeft: marginLeft, duration: 300, easing: 'easeOutQuint' }); } /** * Calculate the offset of the thumb * @return {Number} offset in pixels */ _calcRangeOffset() { let width = this.$el.width() - 15; let max = parseFloat(this.$el.attr('max')) || 100; // Range default max let min = parseFloat(this.$el.attr('min')) || 0; // Range default min let percent = (parseFloat(this.$el.val()) - min) / (max - min); return percent * width; } } M.Range = Range; if (M.jQueryLoaded) { M.initializeJqueryWrapper(Range, 'range', 'M_Range'); } Range.init($('input[type=range]')); })(cash, M.anime);