Blame | Letzte Änderung | Log anzeigen | RSS feed
/** jQuery MiniColors: A tiny color picker built on jQuery** Copyright: Cory LaViska for A Beautiful Site, LLC** Contributions and bug reports: https://github.com/claviska/jquery-minicolors** @license: http://opensource.org/licenses/MIT**/if(jQuery) (function($) {// Defaults$.minicolors = {defaults: {animationSpeed: 50,animationEasing: 'swing',change: null,changeDelay: 0,control: 'hue',dataUris: true,defaultValue: '',hide: null,hideSpeed: 100,inline: false,letterCase: 'lowercase',opacity: false,position: 'bottom left',show: null,showSpeed: 100,theme: 'default'}};// Public methods$.extend($.fn, {minicolors: function(method, data) {switch(method) {// Destroy the controlcase 'destroy':$(this).each( function() {destroy($(this));});return $(this);// Hide the color pickercase 'hide':hide();return $(this);// Get/set opacitycase 'opacity':// Getterif( data === undefined ) {// Getterreturn $(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/opacitycase 'rgbObject':return rgbObject($(this), method === 'rgbaObject');// Get an RGB(A) string based on the current color/opacitycase 'rgbString':case 'rgbaString':return rgbString($(this), method === 'rgbaString');// Get/set settings on the flycase '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 pickercase 'show':show( $(this).eq(0) );return $(this);// Get/set the hex color valuecase 'value':if( data === undefined ) {// Getterreturn $(this).val();} else {// Setter$(this).each( function() {updateFromInput($(this).val(data));});}return $(this);// Initializes the controldefault:if( method !== 'create' ) data = method;$(this).each( function() {init($(this), data);});return $(this);}}});// Initialize input elementsfunction init(input, settings) {var minicolors = $('<div class="minicolors" />'),defaults = $.minicolors.defaults;// Do nothing if already initializedif( input.data('minicolors-initialized') ) return;// Handle settingssettings = $.extend(true, {}, defaults, settings);// The wrapperminicolors.addClass('minicolors-theme-' + settings.theme).toggleClass('minicolors-with-opacity', settings.opacity).toggleClass('minicolors-no-data-uris', settings.dataUris !== true);// Custom positioningif( settings.position !== undefined ) {$.each(settings.position.split(' '), function() {minicolors.addClass('minicolors-position-' + this);});}// The inputinput.addClass('minicolors-input').data('minicolors-initialized', false).data('minicolors-settings', settings).prop('size', 7).wrap(minicolors).after('<div class="minicolors-panel minicolors-slider-' + settings.control + '">' +'<div class="minicolors-slider minicolors-sprite">' +'<div class="minicolors-picker"></div>' +'</div>' +'<div class="minicolors-opacity-slider minicolors-sprite">' +'<div class="minicolors-picker"></div>' +'</div>' +'<div class="minicolors-grid minicolors-sprite">' +'<div class="minicolors-grid-inner"></div>' +'<div class="minicolors-picker"><div></div></div>' +'</div>' +'</div>');// The swatchif( !settings.inline ) {input.after('<span class="minicolors-swatch minicolors-sprite"><span class="minicolors-swatch-color"></span></span>');input.next('.minicolors-swatch').on('click', function(event) {event.preventDefault();input.focus();});}// Prevent text selection in IEinput.parent().find('.minicolors-panel').on('selectstart', function() { return false; }).end();// Inline controlsif( settings.inline ) input.parent().addClass('minicolors-inline');updateFromInput(input, false);input.data('minicolors-initialized', true);}// Returns the input back to its original statefunction destroy(input) {var minicolors = input.parent();// Revert the input elementinput.removeData('minicolors-initialized').removeData('minicolors-settings').removeProp('size').removeClass('minicolors-input');// Remove the wrap and destroy whatever remainsminicolors.before(input).remove();}// Shows the specified dropdown panelfunction show(input) {var minicolors = input.parent(),panel = minicolors.find('.minicolors-panel'),settings = input.data('minicolors-settings');// Do nothing if uninitialized, disabled, inline, or already openif( !input.data('minicolors-initialized') ||input.prop('disabled') ||minicolors.hasClass('minicolors-inline') ||minicolors.hasClass('minicolors-focus')) return;hide();minicolors.addClass('minicolors-focus');panel.stop(true, true).fadeIn(settings.showSpeed, function() {if( settings.show ) settings.show.call(input.get(0));});}// Hides all dropdown panelsfunction hide() {$('.minicolors-focus').each( function() {var minicolors = $(this),input = minicolors.find('.minicolors-input'),panel = minicolors.find('.minicolors-panel'),settings = input.data('minicolors-settings');panel.fadeOut(settings.hideSpeed, function() {if( settings.hide ) settings.hide.call(input.get(0));minicolors.removeClass('minicolors-focus');});});}// Moves the selected pickerfunction move(target, event, animate) {var input = target.parents('.minicolors').find('.minicolors-input'),settings = input.data('minicolors-settings'),picker = target.find('[class$=-picker]'),offsetX = target.offset().left,offsetY = target.offset().top,x = Math.round(event.pageX - offsetX),y = Math.round(event.pageY - offsetY),duration = animate ? settings.animationSpeed : 0,wx, wy, r, phi;// Touch supportif( event.originalEvent.changedTouches ) {x = event.originalEvent.changedTouches[0].pageX - offsetX;y = event.originalEvent.changedTouches[0].pageY - offsetY;}// Constrain picker to its containerif( 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 wheelif( 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 pickerif( target.is('.minicolors-grid') ) {picker.stop(true).animate({top: y + 'px',left: x + 'px'}, duration, settings.animationEasing, function() {updateFromControl(input, target);});} else {picker.stop(true).animate({top: y + 'px'}, duration, settings.animationEasing, function() {updateFromControl(input, target);});}}// Sets the input based on the color picker valuesfunction 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,hex = input.val(),opacity = input.attr('data-opacity'),// Helpful referencesminicolors = input.parent(),settings = input.data('minicolors-settings'),swatch = minicolors.find('.minicolors-swatch'),// Panel objectsgrid = minicolors.find('.minicolors-grid'),slider = minicolors.find('.minicolors-slider'),opacitySlider = minicolors.find('.minicolors-opacity-slider'),// Picker objectsgridPicker = grid.find('[class$=-picker]'),sliderPicker = slider.find('[class$=-picker]'),opacityPicker = opacitySlider.find('[class$=-picker]'),// Picker positionsgridPos = getCoords(gridPicker, grid),sliderPos = getCoords(sliderPicker, slider),opacityPos = getCoords(opacityPicker, opacitySlider);// Handle colorsif( target.is('.minicolors-grid, .minicolors-slider') ) {// Determine HSB valuesswitch(settings.control) {case 'wheel':// Calculate hue, saturation, and brightnessx = (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 UIslider.css('backgroundColor', hsb2hex({ h: hue, s: saturation, b: 100 }));break;case 'saturation':// Calculate hue, saturation, and brightnesshue = 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 UIslider.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 brightnesshue = 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 UIslider.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 brightnesshue = 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 UIgrid.css('backgroundColor', hsb2hex({ h: hue, s: 100, b: 100 }));break;}// Adjust caseinput.val( convertCase(hex, settings.letterCase) );}// Handle opacityif( target.is('.minicolors-opacity-slider') ) {if( settings.opacity ) {opacity = parseFloat(1 - (opacityPos.y / opacitySlider.height())).toFixed(2);} else {opacity = 1;}if( settings.opacity ) input.attr('data-opacity', opacity);}// Set swatch colorswatch.find('SPAN').css({backgroundColor: hex,opacity: opacity});// Handle change eventdoChange(input, hex, opacity);}// Sets the color picker values from the inputfunction updateFromInput(input, preserveInputValue) {var hex,hsb,opacity,x, y, r, phi,// Helpful referencesminicolors = input.parent(),settings = input.data('minicolors-settings'),swatch = minicolors.find('.minicolors-swatch'),// Panel objectsgrid = minicolors.find('.minicolors-grid'),slider = minicolors.find('.minicolors-slider'),opacitySlider = minicolors.find('.minicolors-opacity-slider'),// Picker objectsgridPicker = grid.find('[class$=-picker]'),sliderPicker = slider.find('[class$=-picker]'),opacityPicker = opacitySlider.find('[class$=-picker]');// Determine hex/HSB valueshex = convertCase(parseHex(input.val(), true), settings.letterCase);if( !hex ){hex = convertCase(parseHex(settings.defaultValue, true), settings.letterCase);}hsb = hex2hsb(hex);// Update input valueif( !preserveInputValue ) input.val(hex);// Determine opacity valueif( settings.opacity ) {// Get from data-opacity attribute and keep within 0-1 rangeopacity = 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 positiony = keepWithin(opacitySlider.height() - (opacitySlider.height() * opacity), 0, opacitySlider.height());opacityPicker.css('top', y + 'px');}// Update swatchswatch.find('SPAN').css('backgroundColor', hex);// Determine picker locationsswitch(settings.control) {case 'wheel':// Set grid positionr = 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 positiony = 150 - (hsb.b / (100 / grid.height()));if( hex === '' ) y = 0;sliderPicker.css('top', y + 'px');// Update panel colorslider.css('backgroundColor', hsb2hex({ h: hsb.h, s: hsb.s, b: 100 }));break;case 'saturation':// Set grid positionx = 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 positiony = keepWithin(slider.height() - (hsb.s * (slider.height() / 100)), 0, slider.height());sliderPicker.css('top', y + 'px');// Update UIslider.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 positionx = 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 positiony = keepWithin(slider.height() - (hsb.b * (slider.height() / 100)), 0, slider.height());sliderPicker.css('top', y + 'px');// Update UIslider.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 positionx = 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 positiony = keepWithin(slider.height() - (hsb.h / (360 / slider.height())), 0, slider.height());sliderPicker.css('top', y + 'px');// Update panel colorgrid.css('backgroundColor', hsb2hex({ h: hsb.h, s: 100, b: 100 }));break;}// Fire change event, but only if minicolors is fully initializedif( input.data('minicolors-initialized') ) {doChange(input, hex, opacity);}}// Runs the change and changeDelay callbacksfunction doChange(input, hex, opacity) {var settings = input.data('minicolors-settings'),lastChange = input.data('minicolors-lastChange');// Only run if it actually changedif( !lastChange || lastChange.hex !== hex || lastChange.opacity !== opacity ) {// Remember last-changed valueinput.data('minicolors-lastChange', {hex: hex,opacity: opacity});// Fire change eventif( settings.change ) {if( settings.changeDelay ) {// Call after a delayclearTimeout(input.data('minicolors-changeTimeout'));input.data('minicolors-changeTimeout', setTimeout( function() {settings.change.call(input.get(0), hex, opacity);}, settings.changeDelay));} else {// Call immediatelysettings.change.call(input.get(0), hex, opacity);}}input.trigger('change').trigger('input');}}// Generates an RGB(A) object based on the input's valuefunction rgbObject(input) {var hex = parseHex($(input).val(), true),rgb = hex2rgb(hex),opacity = $(input).attr('data-opacity');if( !rgb ) return null;if( opacity !== undefined ) $.extend(rgb, { a: parseFloat(opacity) });return rgb;}// Genearates an RGB(A) string based on the input's valuefunction rgbString(input, alpha) {var hex = parseHex($(input).val(), true),rgb = hex2rgb(hex),opacity = $(input).attr('data-opacity');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 settingsfunction convertCase(string, letterCase) {return letterCase === 'uppercase' ? string.toUpperCase() : string.toLowerCase();}// Parses a string and returns a valid hex string when possiblefunction parseHex(string, expand) {string = string.replace(/[^A-F0-9]/ig, '');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;}// Keeps value within min and maxfunction keepWithin(value, min, max) {if( value < min ) value = min;if( value > max ) value = max;return value;}// Converts an HSB object to an RGB objectfunction 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 object to a hex stringfunction 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 stringfunction hsb2hex(hsb) {return rgb2hex(hsb2rgb(hsb));}// Converts a hex string to an HSB objectfunction hex2hsb(hex) {var hsb = rgb2hsb(hex2rgb(hex));if( hsb.s === 0 ) hsb.h = 360;return hsb;}// Converts an RGB object to an HSB objectfunction 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 objectfunction hex2rgb(hex) {hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16);return {/* jshint ignore:start */r: hex >> 16,g: (hex & 0x00FF00) >> 8,b: (hex & 0x0000FF)/* jshint ignore:end */};}// 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();$(document).data('minicolors-target', target);move(target, event, true);})// Move pickers.on('mousemove.minicolors touchmove.minicolors', function(event) {var target = $(document).data('minicolors-target');if( target ) move(target, event);})// Stop moving.on('mouseup.minicolors touchend.minicolors', function() {$(this).removeData('minicolors-target');})// Show panel when swatch is clicked.on('mousedown.minicolors touchstart.minicolors', '.minicolors-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);})// Fix hex on blur.on('blur.minicolors', '.minicolors-input', function() {var input = $(this),settings = input.data('minicolors-settings');if( !input.data('minicolors-initialized') ) return;// Parse Hexinput.val(parseHex(input.val(), true));// Is it blank?if( input.val() === '' ) input.val(parseHex(settings.defaultValue, true));// Adjust caseinput.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.keyCode) {case 9: // tabhide();break;case 13: // entercase 27: // eschide();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);});})(jQuery);