// // jQuery MiniColors: A tiny color picker built on jQuery // // Developed by Cory LaViska for A Beautiful Site, LLC // // Licensed under the MIT license: http://opensource.org/licenses/MIT // (function (factory) { if(typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['jquery'], factory); } else if(typeof exports === 'object') { // Node/CommonJS module.exports = factory(require('jquery')); } else { // Browser globals factory(jQuery); } }(function ($) { 'use strict'; // Defaults $.minicolors = { defaults: { animationSpeed: 50, animationEasing: 'swing', change: null, changeDelay: 0, control: 'hue', defaultValue: '', format: 'hex', hide: null, hideSpeed: 100, inline: false, keywords: '', letterCase: 'lowercase', opacity: false, position: 'bottom', show: null, showSpeed: 100, theme: 'default', swatches: [] } }; // Public methods $.extend($.fn, { minicolors: function(method, data) { switch(method) { // Destroy the control case 'destroy': $(this).each(function() { destroy($(this)); }); return $(this); // Hide the color picker case 'hide': hide(); return $(this); // Get/set opacity case 'opacity': // Getter if(data === undefined) { // Getter return $(this).attr('data-opacity'); } else { // Setter $(this).each(function() { updateFromInput($(this).attr('data-opacity', data)); }); } return $(this); // Get an RGB(A) object based on the current color/opacity case 'rgbObject': return rgbObject($(this), method === 'rgbaObject'); // Get an RGB(A) string based on the current color/opacity case 'rgbString': case 'rgbaString': return rgbString($(this), method === 'rgbaString'); // Get/set settings on the fly case 'settings': if(data === undefined) { return $(this).data('minicolors-settings'); } else { // Setter $(this).each(function() { var settings = $(this).data('minicolors-settings') || {}; destroy($(this)); $(this).minicolors($.extend(true, settings, data)); }); } return $(this); // Show the color picker case 'show': show($(this).eq(0)); return $(this); // Get/set the hex color value case 'value': if(data === undefined) { // Getter return $(this).val(); } else { // Setter $(this).each(function() { if(typeof(data) === 'object' && data !== null) { if(data.opacity !== undefined) { $(this).attr('data-opacity', keepWithin(data.opacity, 0, 1)); } if(data.color) { $(this).val(data.color); } } else { $(this).val(data); } updateFromInput($(this)); }); } return $(this); // Initializes the control default: if(method !== 'create') data = method; $(this).each(function() { init($(this), data); }); return $(this); } } }); // Initialize input elements function init(input, settings) { var minicolors = $('
'); var defaults = $.minicolors.defaults; var name; var size; var swatches; var swatch; var swatchString; var panel; var i; // Do nothing if already initialized if(input.data('minicolors-initialized')) return; // Handle settings settings = $.extend(true, {}, defaults, settings); // The wrapper minicolors .addClass('minicolors-theme-' + settings.theme) .toggleClass('minicolors-with-opacity', settings.opacity); // Custom positioning if(settings.position !== undefined) { $.each(settings.position.split(' '), function() { minicolors.addClass('minicolors-position-' + this); }); } // Input size if(settings.format === 'rgb') { size = settings.opacity ? '25' : '20'; } else { size = settings.keywords ? '11' : '7'; } // The input input .addClass('minicolors-input') .data('minicolors-initialized', false) .data('minicolors-settings', settings) .prop('size', size) .wrap(minicolors) .after( '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' ); // The swatch if(!settings.inline) { input.after(''); input.next('.minicolors-input-swatch').on('click', function(event) { event.preventDefault(); input.focus(); }); } // Prevent text selection in IE panel = input.parent().find('.minicolors-panel'); panel.on('selectstart', function() { return false; }).end(); // Swatches if(settings.swatches && settings.swatches.length !== 0) { panel.addClass('minicolors-with-swatches'); swatches = $('') .appendTo(panel); for(i = 0; i < settings.swatches.length; ++i) { // allow for custom objects as swatches if($.type(settings.swatches[i]) === 'object') { name = settings.swatches[i].name; swatch = settings.swatches[i].color; } else { name = ''; swatch = settings.swatches[i]; } swatchString = swatch; swatch = isRgb(swatch) ? parseRgb(swatch, true) : hex2rgb(parseHex(swatch, true)); $('
  • ') .appendTo(swatches) .data('swatch-color', swatchString) .find('.minicolors-swatch-color') .css({ backgroundColor: rgb2hex(swatch), opacity: swatch.a }); settings.swatches[i] = swatch; } } // Inline controls if(settings.inline) input.parent().addClass('minicolors-inline'); updateFromInput(input, false); input.data('minicolors-initialized', true); } // Returns the input back to its original state function destroy(input) { var minicolors = input.parent(); // Revert the input element input .removeData('minicolors-initialized') .removeData('minicolors-settings') .removeProp('size') .removeClass('minicolors-input'); // Remove the wrap and destroy whatever remains minicolors.before(input).remove(); } // Shows the specified dropdown panel function show(input) { var minicolors = input.parent(); var panel = minicolors.find('.minicolors-panel'); var settings = input.data('minicolors-settings'); // Do nothing if uninitialized, disabled, inline, or already open if( !input.data('minicolors-initialized') || input.prop('disabled') || minicolors.hasClass('minicolors-inline') || minicolors.hasClass('minicolors-focus') ) return; hide(); minicolors.addClass('minicolors-focus'); if (panel.animate) { panel .stop(true, true) .fadeIn(settings.showSpeed, function () { if (settings.show) settings.show.call(input.get(0)); }); } else { panel.show(); if (settings.show) settings.show.call(input.get(0)); } } // Hides all dropdown panels function hide() { $('.minicolors-focus').each(function() { var minicolors = $(this); var input = minicolors.find('.minicolors-input'); var panel = minicolors.find('.minicolors-panel'); var settings = input.data('minicolors-settings'); if (panel.animate) { panel.fadeOut(settings.hideSpeed, function () { if (settings.hide) settings.hide.call(input.get(0)); minicolors.removeClass('minicolors-focus'); }); } else { panel.hide(); if (settings.hide) settings.hide.call(input.get(0)); minicolors.removeClass('minicolors-focus'); } }); } // Moves the selected picker function move(target, event, animate) { var input = target.parents('.minicolors').find('.minicolors-input'); var settings = input.data('minicolors-settings'); var picker = target.find('[class$=-picker]'); var offsetX = target.offset().left; var offsetY = target.offset().top; var x = Math.round(event.pageX - offsetX); var y = Math.round(event.pageY - offsetY); var duration = animate ? settings.animationSpeed : 0; var wx, wy, r, phi, styles; // Touch support if(event.originalEvent.changedTouches) { x = event.originalEvent.changedTouches[0].pageX - offsetX; y = event.originalEvent.changedTouches[0].pageY - offsetY; } // Constrain picker to its container if(x < 0) x = 0; if(y < 0) y = 0; if(x > target.width()) x = target.width(); if(y > target.height()) y = target.height(); // Constrain color wheel values to the wheel if(target.parent().is('.minicolors-slider-wheel') && picker.parent().is('.minicolors-grid')) { wx = 75 - x; wy = 75 - y; r = Math.sqrt(wx * wx + wy * wy); phi = Math.atan2(wy, wx); if(phi < 0) phi += Math.PI * 2; if(r > 75) { r = 75; x = 75 - (75 * Math.cos(phi)); y = 75 - (75 * Math.sin(phi)); } x = Math.round(x); y = Math.round(y); } // Move the picker styles = { top: y + 'px' }; if(target.is('.minicolors-grid')) { styles.left = x + 'px'; } if (picker.animate) { picker .stop(true) .animate(styles, duration, settings.animationEasing, function() { updateFromControl(input, target); }); } else { picker .css(styles); updateFromControl(input, target); } } // Sets the input based on the color picker values function updateFromControl(input, target) { function getCoords(picker, container) { var left, top; if(!picker.length || !container) return null; left = picker.offset().left; top = picker.offset().top; return { x: left - container.offset().left + (picker.outerWidth() / 2), y: top - container.offset().top + (picker.outerHeight() / 2) }; } var hue, saturation, brightness, x, y, r, phi; var hex = input.val(); var opacity = input.attr('data-opacity'); // Helpful references var minicolors = input.parent(); var settings = input.data('minicolors-settings'); var swatch = minicolors.find('.minicolors-input-swatch'); // Panel objects var grid = minicolors.find('.minicolors-grid'); var slider = minicolors.find('.minicolors-slider'); var opacitySlider = minicolors.find('.minicolors-opacity-slider'); // Picker objects var gridPicker = grid.find('[class$=-picker]'); var sliderPicker = slider.find('[class$=-picker]'); var opacityPicker = opacitySlider.find('[class$=-picker]'); // Picker positions var gridPos = getCoords(gridPicker, grid); var sliderPos = getCoords(sliderPicker, slider); var opacityPos = getCoords(opacityPicker, opacitySlider); // Handle colors if(target.is('.minicolors-grid, .minicolors-slider, .minicolors-opacity-slider')) { // Determine HSB values switch(settings.control) { case 'wheel': // Calculate hue, saturation, and brightness x = (grid.width() / 2) - gridPos.x; y = (grid.height() / 2) - gridPos.y; r = Math.sqrt(x * x + y * y); phi = Math.atan2(y, x); if(phi < 0) phi += Math.PI * 2; if(r > 75) { r = 75; gridPos.x = 69 - (75 * Math.cos(phi)); gridPos.y = 69 - (75 * Math.sin(phi)); } saturation = keepWithin(r / 0.75, 0, 100); hue = keepWithin(phi * 180 / Math.PI, 0, 360); brightness = keepWithin(100 - Math.floor(sliderPos.y * (100 / slider.height())), 0, 100); hex = hsb2hex({ h: hue, s: saturation, b: brightness }); // Update UI slider.css('backgroundColor', hsb2hex({ h: hue, s: saturation, b: 100 })); break; case 'saturation': // Calculate hue, saturation, and brightness hue = keepWithin(parseInt(gridPos.x * (360 / grid.width()), 10), 0, 360); saturation = keepWithin(100 - Math.floor(sliderPos.y * (100 / slider.height())), 0, 100); brightness = keepWithin(100 - Math.floor(gridPos.y * (100 / grid.height())), 0, 100); hex = hsb2hex({ h: hue, s: saturation, b: brightness }); // Update UI slider.css('backgroundColor', hsb2hex({ h: hue, s: 100, b: brightness })); minicolors.find('.minicolors-grid-inner').css('opacity', saturation / 100); break; case 'brightness': // Calculate hue, saturation, and brightness hue = keepWithin(parseInt(gridPos.x * (360 / grid.width()), 10), 0, 360); saturation = keepWithin(100 - Math.floor(gridPos.y * (100 / grid.height())), 0, 100); brightness = keepWithin(100 - Math.floor(sliderPos.y * (100 / slider.height())), 0, 100); hex = hsb2hex({ h: hue, s: saturation, b: brightness }); // Update UI slider.css('backgroundColor', hsb2hex({ h: hue, s: saturation, b: 100 })); minicolors.find('.minicolors-grid-inner').css('opacity', 1 - (brightness / 100)); break; default: // Calculate hue, saturation, and brightness hue = keepWithin(360 - parseInt(sliderPos.y * (360 / slider.height()), 10), 0, 360); saturation = keepWithin(Math.floor(gridPos.x * (100 / grid.width())), 0, 100); brightness = keepWithin(100 - Math.floor(gridPos.y * (100 / grid.height())), 0, 100); hex = hsb2hex({ h: hue, s: saturation, b: brightness }); // Update UI grid.css('backgroundColor', hsb2hex({ h: hue, s: 100, b: 100 })); break; } // Handle opacity if(settings.opacity) { opacity = parseFloat(1 - (opacityPos.y / opacitySlider.height())).toFixed(2); } else { opacity = 1; } updateInput(input, hex, opacity); } else { // Set swatch color swatch.find('span').css({ backgroundColor: hex, opacity: opacity }); // Handle change event doChange(input, hex, opacity); } } // Sets the value of the input and does the appropriate conversions // to respect settings, also updates the swatch function updateInput(input, value, opacity) { var rgb; // Helpful references var minicolors = input.parent(); var settings = input.data('minicolors-settings'); var swatch = minicolors.find('.minicolors-input-swatch'); if(settings.opacity) input.attr('data-opacity', opacity); // Set color string if(settings.format === 'rgb') { // Returns RGB(A) string // Checks for input format and does the conversion if(isRgb(value)) { rgb = parseRgb(value, true); } else { rgb = hex2rgb(parseHex(value, true)); } opacity = input.attr('data-opacity') === '' ? 1 : keepWithin(parseFloat(input.attr('data-opacity')).toFixed(2), 0, 1); if(isNaN(opacity) || !settings.opacity) opacity = 1; if(input.minicolors('rgbObject').a <= 1 && rgb && settings.opacity) { // Set RGBA string if alpha value = 'rgba(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ', ' + parseFloat(opacity) + ')'; } else { // Set RGB string (alpha = 1) value = 'rgb(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ')'; } } else { // Returns hex color // Checks for input format and does the conversion if(isRgb(value)) { value = rgbString2hex(value); } value = convertCase(value, settings.letterCase); } // Update value from picker input.val(value); // Set swatch color swatch.find('span').css({ backgroundColor: value, opacity: opacity }); // Handle change event doChange(input, value, opacity); } // Sets the color picker values from the input function updateFromInput(input, preserveInputValue) { var hex, hsb, opacity, keywords, alpha, value, x, y, r, phi; // Helpful references var minicolors = input.parent(); var settings = input.data('minicolors-settings'); var swatch = minicolors.find('.minicolors-input-swatch'); // Panel objects var grid = minicolors.find('.minicolors-grid'); var slider = minicolors.find('.minicolors-slider'); var opacitySlider = minicolors.find('.minicolors-opacity-slider'); // Picker objects var gridPicker = grid.find('[class$=-picker]'); var sliderPicker = slider.find('[class$=-picker]'); var opacityPicker = opacitySlider.find('[class$=-picker]'); // Determine hex/HSB values if(isRgb(input.val())) { // If input value is a rgb(a) string, convert it to hex color and update opacity hex = rgbString2hex(input.val()); alpha = keepWithin(parseFloat(getAlpha(input.val())).toFixed(2), 0, 1); if(alpha) { input.attr('data-opacity', alpha); } } else { hex = convertCase(parseHex(input.val(), true), settings.letterCase); } if(!hex){ hex = convertCase(parseInput(settings.defaultValue, true), settings.letterCase); } hsb = hex2hsb(hex); // Get array of lowercase keywords keywords = !settings.keywords ? [] : $.map(settings.keywords.split(','), function(a) { return $.trim(a.toLowerCase()); }); // Set color string if(input.val() !== '' && $.inArray(input.val().toLowerCase(), keywords) > -1) { value = convertCase(input.val()); } else { value = isRgb(input.val()) ? parseRgb(input.val()) : hex; } // Update input value if(!preserveInputValue) input.val(value); // Determine opacity value if(settings.opacity) { // Get from data-opacity attribute and keep within 0-1 range opacity = input.attr('data-opacity') === '' ? 1 : keepWithin(parseFloat(input.attr('data-opacity')).toFixed(2), 0, 1); if(isNaN(opacity)) opacity = 1; input.attr('data-opacity', opacity); swatch.find('span').css('opacity', opacity); // Set opacity picker position y = keepWithin(opacitySlider.height() - (opacitySlider.height() * opacity), 0, opacitySlider.height()); opacityPicker.css('top', y + 'px'); } // Set opacity to zero if input value is transparent if(input.val().toLowerCase() === 'transparent') { swatch.find('span').css('opacity', 0); } // Update swatch swatch.find('span').css('backgroundColor', hex); // Determine picker locations switch(settings.control) { case 'wheel': // Set grid position r = keepWithin(Math.ceil(hsb.s * 0.75), 0, grid.height() / 2); phi = hsb.h * Math.PI / 180; x = keepWithin(75 - Math.cos(phi) * r, 0, grid.width()); y = keepWithin(75 - Math.sin(phi) * r, 0, grid.height()); gridPicker.css({ top: y + 'px', left: x + 'px' }); // Set slider position y = 150 - (hsb.b / (100 / grid.height())); if(hex === '') y = 0; sliderPicker.css('top', y + 'px'); // Update panel color slider.css('backgroundColor', hsb2hex({ h: hsb.h, s: hsb.s, b: 100 })); break; case 'saturation': // Set grid position x = keepWithin((5 * hsb.h) / 12, 0, 150); y = keepWithin(grid.height() - Math.ceil(hsb.b / (100 / grid.height())), 0, grid.height()); gridPicker.css({ top: y + 'px', left: x + 'px' }); // Set slider position y = keepWithin(slider.height() - (hsb.s * (slider.height() / 100)), 0, slider.height()); sliderPicker.css('top', y + 'px'); // Update UI slider.css('backgroundColor', hsb2hex({ h: hsb.h, s: 100, b: hsb.b })); minicolors.find('.minicolors-grid-inner').css('opacity', hsb.s / 100); break; case 'brightness': // Set grid position x = keepWithin((5 * hsb.h) / 12, 0, 150); y = keepWithin(grid.height() - Math.ceil(hsb.s / (100 / grid.height())), 0, grid.height()); gridPicker.css({ top: y + 'px', left: x + 'px' }); // Set slider position y = keepWithin(slider.height() - (hsb.b * (slider.height() / 100)), 0, slider.height()); sliderPicker.css('top', y + 'px'); // Update UI slider.css('backgroundColor', hsb2hex({ h: hsb.h, s: hsb.s, b: 100 })); minicolors.find('.minicolors-grid-inner').css('opacity', 1 - (hsb.b / 100)); break; default: // Set grid position x = keepWithin(Math.ceil(hsb.s / (100 / grid.width())), 0, grid.width()); y = keepWithin(grid.height() - Math.ceil(hsb.b / (100 / grid.height())), 0, grid.height()); gridPicker.css({ top: y + 'px', left: x + 'px' }); // Set slider position y = keepWithin(slider.height() - (hsb.h / (360 / slider.height())), 0, slider.height()); sliderPicker.css('top', y + 'px'); // Update panel color grid.css('backgroundColor', hsb2hex({ h: hsb.h, s: 100, b: 100 })); break; } // Fire change event, but only if minicolors is fully initialized if(input.data('minicolors-initialized')) { doChange(input, value, opacity); } } // Runs the change and changeDelay callbacks function doChange(input, value, opacity) { var settings = input.data('minicolors-settings'); var lastChange = input.data('minicolors-lastChange'); var obj, sel, i; // Only run if it actually changed if(!lastChange || lastChange.value !== value || lastChange.opacity !== opacity) { // Remember last-changed value input.data('minicolors-lastChange', { value: value, opacity: opacity }); // Check and select applicable swatch if(settings.swatches && settings.swatches.length !== 0) { if(!isRgb(value)) { obj = hex2rgb(value); } else { obj = parseRgb(value, true); } sel = -1; for(i = 0; i < settings.swatches.length; ++i) { if(obj.r === settings.swatches[i].r && obj.g === settings.swatches[i].g && obj.b === settings.swatches[i].b && obj.a === settings.swatches[i].a) { sel = i; break; } } input.parent().find('.minicolors-swatches .minicolors-swatch').removeClass('selected'); if(sel !== -1) { input.parent().find('.minicolors-swatches .minicolors-swatch').eq(i).addClass('selected'); } } // Fire change event if(settings.change) { if(settings.changeDelay) { // Call after a delay clearTimeout(input.data('minicolors-changeTimeout')); input.data('minicolors-changeTimeout', setTimeout(function() { settings.change.call(input.get(0), value, opacity); }, settings.changeDelay)); } else { // Call immediately settings.change.call(input.get(0), value, opacity); } } input.trigger('change').trigger('input'); } } // Generates an RGB(A) object based on the input's value function rgbObject(input) { var rgb, opacity = $(input).attr('data-opacity'); if( isRgb($(input).val()) ) { rgb = parseRgb($(input).val(), true); } else { var hex = parseHex($(input).val(), true); rgb = hex2rgb(hex); } if( !rgb ) return null; if( opacity !== undefined ) $.extend(rgb, { a: parseFloat(opacity) }); return rgb; } // Generates an RGB(A) string based on the input's value function rgbString(input, alpha) { var rgb, opacity = $(input).attr('data-opacity'); if( isRgb($(input).val()) ) { rgb = parseRgb($(input).val(), true); } else { var hex = parseHex($(input).val(), true); rgb = hex2rgb(hex); } if( !rgb ) return null; if( opacity === undefined ) opacity = 1; if( alpha ) { return 'rgba(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ', ' + parseFloat(opacity) + ')'; } else { return 'rgb(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ')'; } } // Converts to the letter case specified in settings function convertCase(string, letterCase) { return letterCase === 'uppercase' ? string.toUpperCase() : string.toLowerCase(); } // Parses a string and returns a valid hex string when possible function parseHex(string, expand) { string = string.replace(/^#/g, ''); if(!string.match(/^[A-F0-9]{3,6}/ig)) return ''; if(string.length !== 3 && string.length !== 6) return ''; if(string.length === 3 && expand) { string = string[0] + string[0] + string[1] + string[1] + string[2] + string[2]; } return '#' + string; } // Parses a string and returns a valid RGB(A) string when possible function parseRgb(string, obj) { var values = string.replace(/[^\d,.]/g, ''); var rgba = values.split(','); rgba[0] = keepWithin(parseInt(rgba[0], 10), 0, 255); rgba[1] = keepWithin(parseInt(rgba[1], 10), 0, 255); rgba[2] = keepWithin(parseInt(rgba[2], 10), 0, 255); if(rgba[3] !== undefined) { rgba[3] = keepWithin(parseFloat(rgba[3], 10), 0, 1); } // Return RGBA object if( obj ) { if (rgba[3] !== undefined) { return { r: rgba[0], g: rgba[1], b: rgba[2], a: rgba[3] }; } else { return { r: rgba[0], g: rgba[1], b: rgba[2] }; } } // Return RGBA string if(typeof(rgba[3]) !== 'undefined' && rgba[3] <= 1) { return 'rgba(' + rgba[0] + ', ' + rgba[1] + ', ' + rgba[2] + ', ' + rgba[3] + ')'; } else { return 'rgb(' + rgba[0] + ', ' + rgba[1] + ', ' + rgba[2] + ')'; } } // Parses a string and returns a valid color string when possible function parseInput(string, expand) { if(isRgb(string)) { // Returns a valid rgb(a) string return parseRgb(string); } else { return parseHex(string, expand); } } // Keeps value within min and max function keepWithin(value, min, max) { if(value < min) value = min; if(value > max) value = max; return value; } // Checks if a string is a valid RGB(A) string function isRgb(string) { var rgb = string.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i); return (rgb && rgb.length === 4) ? true : false; } // Function to get alpha from a RGB(A) string function getAlpha(rgba) { rgba = rgba.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+(\.\d{1,2})?|\.\d{1,2})[\s+]?/i); return (rgba && rgba.length === 6) ? rgba[4] : '1'; } // Converts an HSB object to an RGB object function hsb2rgb(hsb) { var rgb = {}; var h = Math.round(hsb.h); var s = Math.round(hsb.s * 255 / 100); var v = Math.round(hsb.b * 255 / 100); if(s === 0) { rgb.r = rgb.g = rgb.b = v; } else { var t1 = v; var t2 = (255 - s) * v / 255; var t3 = (t1 - t2) * (h % 60) / 60; if(h === 360) h = 0; if(h < 60) { rgb.r = t1; rgb.b = t2; rgb.g = t2 + t3; } else if(h < 120) {rgb.g = t1; rgb.b = t2; rgb.r = t1 - t3; } else if(h < 180) {rgb.g = t1; rgb.r = t2; rgb.b = t2 + t3; } else if(h < 240) {rgb.b = t1; rgb.r = t2; rgb.g = t1 - t3; } else if(h < 300) {rgb.b = t1; rgb.g = t2; rgb.r = t2 + t3; } else if(h < 360) {rgb.r = t1; rgb.g = t2; rgb.b = t1 - t3; } else { rgb.r = 0; rgb.g = 0; rgb.b = 0; } } return { r: Math.round(rgb.r), g: Math.round(rgb.g), b: Math.round(rgb.b) }; } // Converts an RGB string to a hex string function rgbString2hex(rgb){ rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i); return (rgb && rgb.length === 4) ? '#' + ('0' + parseInt(rgb[1],10).toString(16)).slice(-2) + ('0' + parseInt(rgb[2],10).toString(16)).slice(-2) + ('0' + parseInt(rgb[3],10).toString(16)).slice(-2) : ''; } // Converts an RGB object to a hex string function rgb2hex(rgb) { var hex = [ rgb.r.toString(16), rgb.g.toString(16), rgb.b.toString(16) ]; $.each(hex, function(nr, val) { if(val.length === 1) hex[nr] = '0' + val; }); return '#' + hex.join(''); } // Converts an HSB object to a hex string function hsb2hex(hsb) { return rgb2hex(hsb2rgb(hsb)); } // Converts a hex string to an HSB object function hex2hsb(hex) { var hsb = rgb2hsb(hex2rgb(hex)); if(hsb.s === 0) hsb.h = 360; return hsb; } // Converts an RGB object to an HSB object function rgb2hsb(rgb) { var hsb = { h: 0, s: 0, b: 0 }; var min = Math.min(rgb.r, rgb.g, rgb.b); var max = Math.max(rgb.r, rgb.g, rgb.b); var delta = max - min; hsb.b = max; hsb.s = max !== 0 ? 255 * delta / max : 0; if(hsb.s !== 0) { if(rgb.r === max) { hsb.h = (rgb.g - rgb.b) / delta; } else if(rgb.g === max) { hsb.h = 2 + (rgb.b - rgb.r) / delta; } else { hsb.h = 4 + (rgb.r - rgb.g) / delta; } } else { hsb.h = -1; } hsb.h *= 60; if(hsb.h < 0) { hsb.h += 360; } hsb.s *= 100/255; hsb.b *= 100/255; return hsb; } // Converts a hex string to an RGB object function hex2rgb(hex) { hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16); return { r: hex >> 16, g: (hex & 0x00FF00) >> 8, b: (hex & 0x0000FF) }; } // Handle events $([document]) // Hide on clicks outside of the control .on('mousedown.minicolors touchstart.minicolors', function(event) { if(!$(event.target).parents().add(event.target).hasClass('minicolors')) { hide(); } }) // Start moving .on('mousedown.minicolors touchstart.minicolors', '.minicolors-grid, .minicolors-slider, .minicolors-opacity-slider', function(event) { var target = $(this); event.preventDefault(); $(event.delegateTarget).data('minicolors-target', target); move(target, event, true); }) // Move pickers .on('mousemove.minicolors touchmove.minicolors', function(event) { var target = $(event.delegateTarget).data('minicolors-target'); if(target) move(target, event); }) // Stop moving .on('mouseup.minicolors touchend.minicolors', function() { $(this).removeData('minicolors-target'); }) // Selected a swatch .on('click.minicolors', '.minicolors-swatches li', function(event) { event.preventDefault(); var target = $(this), input = target.parents('.minicolors').find('.minicolors-input'), color = target.data('swatch-color'); updateInput(input, color, getAlpha(color)); updateFromInput(input); }) // Show panel when swatch is clicked .on('mousedown.minicolors touchstart.minicolors', '.minicolors-input-swatch', function(event) { var input = $(this).parent().find('.minicolors-input'); event.preventDefault(); show(input); }) // Show on focus .on('focus.minicolors', '.minicolors-input', function() { var input = $(this); if(!input.data('minicolors-initialized')) return; show(input); }) // Update value on blur .on('blur.minicolors', '.minicolors-input', function() { var input = $(this); var settings = input.data('minicolors-settings'); var keywords; var hex; var rgba; var swatchOpacity; var value; if(!input.data('minicolors-initialized')) return; // Get array of lowercase keywords keywords = !settings.keywords ? [] : $.map(settings.keywords.split(','), function(a) { return $.trim(a.toLowerCase()); }); // Set color string if(input.val() !== '' && $.inArray(input.val().toLowerCase(), keywords) > -1) { value = input.val(); } else { // Get RGBA values for easy conversion if(isRgb(input.val())) { rgba = parseRgb(input.val(), true); } else { hex = parseHex(input.val(), true); rgba = hex ? hex2rgb(hex) : null; } // Convert to format if(rgba === null) { value = settings.defaultValue; } else if(settings.format === 'rgb') { value = settings.opacity ? parseRgb('rgba(' + rgba.r + ',' + rgba.g + ',' + rgba.b + ',' + input.attr('data-opacity') + ')') : parseRgb('rgb(' + rgba.r + ',' + rgba.g + ',' + rgba.b + ')'); } else { value = rgb2hex(rgba); } } // Update swatch opacity swatchOpacity = settings.opacity ? input.attr('data-opacity') : 1; if(value.toLowerCase() === 'transparent') swatchOpacity = 0; input .closest('.minicolors') .find('.minicolors-input-swatch > span') .css('opacity', swatchOpacity); // Set input value input.val(value); // Is it blank? if(input.val() === '') input.val(parseInput(settings.defaultValue, true)); // Adjust case input.val(convertCase(input.val(), settings.letterCase)); }) // Handle keypresses .on('keydown.minicolors', '.minicolors-input', function(event) { var input = $(this); if(!input.data('minicolors-initialized')) return; switch(event.which) { case 9: // tab hide(); break; case 13: // enter case 27: // esc hide(); input.blur(); break; } }) // Update on keyup .on('keyup.minicolors', '.minicolors-input', function() { var input = $(this); if(!input.data('minicolors-initialized')) return; updateFromInput(input, true); }) // Update on paste .on('paste.minicolors', '.minicolors-input', function() { var input = $(this); if(!input.data('minicolors-initialized')) return; setTimeout(function() { updateFromInput(input, true); }, 1); }); }));