UNPKG

bootstrap-colorpicker

Version:

Bootstrap Colorpicker is a modular color picker plugin for Bootstrap 4.

247 lines (208 loc) 6.44 kB
'use strict'; import $ from 'jquery'; /** * Class that handles all configured sliders on mouse or touch events. * @ignore */ class SliderHandler { /** * @param {Colorpicker} colorpicker */ constructor(colorpicker) { /** * @type {Colorpicker} */ this.colorpicker = colorpicker; /** * @type {*|String} * @private */ this.currentSlider = null; /** * @type {{left: number, top: number}} * @private */ this.mousePointer = { left: 0, top: 0 }; /** * @type {Function} */ this.onMove = $.proxy(this.defaultOnMove, this); } /** * This function is called every time a slider guide is moved * The scope of "this" is the SliderHandler object. * * @param {int} top * @param {int} left */ defaultOnMove(top, left) { if (!this.currentSlider) { return; } let slider = this.currentSlider, cp = this.colorpicker, ch = cp.colorHandler; // Create a color object let color = !ch.hasColor() ? ch.getFallbackColor() : ch.color.getClone(); // Adjust the guide position slider.guideStyle.left = left + 'px'; slider.guideStyle.top = top + 'px'; // Adjust the color if (slider.callLeft) { color[slider.callLeft].call(color, left / slider.maxLeft); } if (slider.callTop) { color[slider.callTop].call(color, top / slider.maxTop); } // Set the new color cp.setValue(color); cp.popupHandler.focus(); } /** * Binds the colorpicker sliders to the mouse/touch events */ bind() { let sliders = this.colorpicker.options.horizontal ? this.colorpicker .options.slidersHorz : this.colorpicker.options.sliders; let sliderClasses = []; for (let sliderName in sliders) { if (!sliders.hasOwnProperty(sliderName)) { continue; } sliderClasses.push(sliders[sliderName].selector); } this.colorpicker.picker.find(sliderClasses.join(', ')) .on('mousedown.colorpicker touchstart.colorpicker', $.proxy(this.pressed, this)); } /** * Unbinds any event bound by this handler */ unbind() { $(this.colorpicker.picker).off({ 'mousemove.colorpicker': $.proxy(this.moved, this), 'touchmove.colorpicker': $.proxy(this.moved, this), 'mouseup.colorpicker': $.proxy(this.released, this), 'touchend.colorpicker': $.proxy(this.released, this) }); } /** * Function triggered when clicking in one of the color adjustment bars * * @private * @fires Colorpicker#mousemove * @param {Event} e */ pressed(e) { if (this.colorpicker.isDisabled()) { return; } this.colorpicker.lastEvent.alias = 'pressed'; this.colorpicker.lastEvent.e = e; if (!e.pageX && !e.pageY && e.originalEvent && e.originalEvent.touches) { e.pageX = e.originalEvent.touches[0].pageX; e.pageY = e.originalEvent.touches[0].pageY; } // e.stopPropagation(); // e.preventDefault(); let target = $(e.target); // detect the slider and set the limits and callbacks let zone = target.closest('div'); let sliders = this.colorpicker.options.horizontal ? this.colorpicker .options.slidersHorz : this.colorpicker.options.sliders; if (zone.is('.colorpicker')) { return; } this.currentSlider = null; for (let sliderName in sliders) { if (!sliders.hasOwnProperty(sliderName)) { continue; } let slider = sliders[sliderName]; if (zone.is(slider.selector)) { this.currentSlider = $.extend({}, slider, {name: sliderName}); break; } else if (slider.childSelector !== undefined && zone.is(slider.childSelector)) { this.currentSlider = $.extend({}, slider, {name: sliderName}); zone = zone.parent(); // zone.parents(slider.selector).first() ? break; } } let guide = zone.find('.colorpicker-guide').get(0); if (this.currentSlider === null || guide === null) { return; } let offset = zone.offset(); // reference to guide's style this.currentSlider.guideStyle = guide.style; this.currentSlider.left = e.pageX - offset.left; this.currentSlider.top = e.pageY - offset.top; this.mousePointer = { left: e.pageX, top: e.pageY }; // TODO: fix moving outside the picker makes the guides to keep moving. The event needs to be bound to the window. /** * (window.document) Triggered on mousedown for the document object, * so the color adjustment guide is moved to the clicked position. * * @event Colorpicker#mousemove */ $(this.colorpicker.picker).on({ 'mousemove.colorpicker': $.proxy(this.moved, this), 'touchmove.colorpicker': $.proxy(this.moved, this), 'mouseup.colorpicker': $.proxy(this.released, this), 'touchend.colorpicker': $.proxy(this.released, this) }).trigger('mousemove'); } /** * Function triggered when dragging a guide inside one of the color adjustment bars. * * @private * @param {Event} e */ moved(e) { this.colorpicker.lastEvent.alias = 'moved'; this.colorpicker.lastEvent.e = e; if (!e.pageX && !e.pageY && e.originalEvent && e.originalEvent.touches) { e.pageX = e.originalEvent.touches[0].pageX; e.pageY = e.originalEvent.touches[0].pageY; } // e.stopPropagation(); e.preventDefault(); // prevents scrolling on mobile let left = Math.max( 0, Math.min( this.currentSlider.maxLeft, this.currentSlider.left + ((e.pageX || this.mousePointer.left) - this.mousePointer.left) ) ); let top = Math.max( 0, Math.min( this.currentSlider.maxTop, this.currentSlider.top + ((e.pageY || this.mousePointer.top) - this.mousePointer.top) ) ); this.onMove(top, left); } /** * Function triggered when releasing the click in one of the color adjustment bars. * * @private * @param {Event} e */ released(e) { this.colorpicker.lastEvent.alias = 'released'; this.colorpicker.lastEvent.e = e; // e.stopPropagation(); // e.preventDefault(); $(this.colorpicker.picker).off({ 'mousemove.colorpicker': this.moved, 'touchmove.colorpicker': this.moved, 'mouseup.colorpicker': this.released, 'touchend.colorpicker': this.released }); } } export default SliderHandler;