UNPKG

wcolpick

Version:

Photoshop-style Full featured Color Picker for jQuery - Wcolpick

920 lines (914 loc) 54.4 kB
/* Wcolpick - A Web Color Picker Copyright (C) 2017-2020 devpelux (Salvatore Peluso) Licensed under MIT license. Download from npm: npm i wcolpick Last Edit: 2020/12/06 18:53 */ (function ($) { var wcolpick = function () { var tpl = '<div class="wcolpick"><div class="wcolpick_color"><div class="wcolpick_color_overlay1"><div class="wcolpick_color_overlay2"><div class="wcolpick_selector_outer"><div class="wcolpick_selector_inner"></div></div></div></div></div><div class="wcolpick_hue"><div class="wcolpick_hue_underlay"></div><div class="wcolpick_hue_overlay"></div><div class="wcolpick_hue_arrs"><div class="wcolpick_hue_larr"></div><div class="wcolpick_hue_rarr"></div></div></div><div class="wcolpick_alpha"><div class="wcolpick_alpha_underlay wcolpick_checkerboards"></div><div class="wcolpick_alpha_overlay"></div><div class="wcolpick_alpha_arrs"><div class="wcolpick_alpha_darr"></div><div class="wcolpick_alpha_uarr"></div></div></div><div class="wcolpick_hex_field"><div class="wcolpick_field_letter">#</div><input type="text" maxlength="8" size="6" /></div><div class="wcolpick_rgb_r wcolpick_field"><div class="wcolpick_field_letter">R</div><input type="text" maxlength="3" size="3" /><div class="wcolpick_field_arrs"><div class="wcolpick_field_uarr"></div><div class="wcolpick_field_darr"></div></div></div><div class="wcolpick_rgb_g wcolpick_field"><div class="wcolpick_field_letter">G</div><input type="text" maxlength="3" size="3" /><div class="wcolpick_field_arrs"><div class="wcolpick_field_uarr"></div><div class="wcolpick_field_darr"></div></div></div><div class="wcolpick_rgb_b wcolpick_field"><div class="wcolpick_field_letter">B</div><input type="text" maxlength="3" size="3" /><div class="wcolpick_field_arrs"><div class="wcolpick_field_uarr"></div><div class="wcolpick_field_darr"></div></div></div><div class="wcolpick_hsb_h wcolpick_field"><div class="wcolpick_field_letter">H</div><input type="text" maxlength="3" size="3" /><div class="wcolpick_field_arrs"><div class="wcolpick_field_uarr"></div><div class="wcolpick_field_darr"></div></div></div><div class="wcolpick_hsb_s wcolpick_field"><div class="wcolpick_field_letter">S</div><input type="text" maxlength="3" size="3" /><div class="wcolpick_field_arrs"><div class="wcolpick_field_uarr"></div><div class="wcolpick_field_darr"></div></div></div><div class="wcolpick_hsb_b wcolpick_field"><div class="wcolpick_field_letter">B</div><input type="text" maxlength="3" size="3" /><div class="wcolpick_field_arrs"><div class="wcolpick_field_uarr"></div><div class="wcolpick_field_darr"></div></div></div><div class="wcolpick_alpha_field wcolpick_field"><div class="wcolpick_field_letter">A</div><input type="text" maxlength="3" size="3" /><div class="wcolpick_field_arrs"><div class="wcolpick_field_uarr"></div><div class="wcolpick_field_darr"></div></div></div><div class="wcolpick_colors"><div class="wcolpick_colors_underlay wcolpick_checkerboards"></div><div class="wcolpick_new_color"></div><div class="wcolpick_current_color"></div></div><div class="wcolpick_submit"><div class="wcolpick_tear"></div></div></div>', defaults = { alphaOutline: true, appendToBody: false, arrowsColor: 'default', backgroundColor: 'default', border: 1, borderColor: 'default', checkersColor: 'default', color: {h:0, s:0, b:20, a:1}, colorOutline: true, colorScheme: 'light-full', colorSelOutline: true, compactLayout: false, enableAlpha: true, enableSubmit: true, enableUpDown: true, fieldsBackground: 'default', flat: true, hueOutline: true, layout: 'full', livePreview: true, polyfill: false, position: 'auto', readonlyFields: false, readonlyHexField: false, showEvent: 'click', submitBackground: 'default', submitColor: 'default', variant: 'standard', onBeforeShow: function () {}, onChange: function () {}, onDestroy: function () {}, onHide: function () {}, onLoaded: function () {}, onShow: function () {}, onSubmit: function () {} }, //Fill the inputs of the plugin fillRGBFields = function (rgba, cal) { $(cal).data('wcolpick').fields .eq(1).val(rgba.r).end() .eq(2).val(rgba.g).end() .eq(3).val(rgba.b).end(); }, fillHSBFields = function (hsba, cal) { $(cal).data('wcolpick').fields .eq(4).val(Math.round(hsba.h)).end() .eq(5).val(Math.round(hsba.s)).end() .eq(6).val(Math.round(hsba.b)).end(); }, fillAlphaField = function (hsba, cal) { $(cal).data('wcolpick').fields.eq(7).val(Math.round(hsba.a*100)).end(); }, fillHexField = function (hex, cal) { if ($(cal).data('wcolpick').enableAlpha) $(cal).data('wcolpick').fields.eq(0).val(hex); else $(cal).data('wcolpick').fields.eq(0).val(hex.substring(0,6)); }, //Set selector's color and selector's indicator position setSelectorPos = function (hsba, cal) { $(cal).data('wcolpick').selectorIndic.css({ left: Math.round($(cal).data('wcolpick').size * hsba.s/100), top: Math.round($(cal).data('wcolpick').size * (100-hsba.b)/100) }); }, setSelectorColor = function (hsba, cal) { if (isInternetExplorer()) { //Compatibility with IE 6-9 var rgba = hsbaToRgba({h: Math.round(hsba.h), s: 100, b: 100, a: 255}); $(cal).data('wcolpick').selector.css('backgroundColor', 'rgb('+rgba.r+','+rgba.g+','+rgba.b+')'); } else $(cal).data('wcolpick').selector.css('backgroundColor', 'hsl('+Math.round(hsba.h)+','+100+'%,'+50+'%)'); }, //Set hue's arrows position setHuePos = function (hsba, cal) { $(cal).data('wcolpick').hue.css('top', Math.round($(cal).data('wcolpick').size - $(cal).data('wcolpick').size * hsba.h/360)); }, //Set alpha bar color and alpha's arrows position setAlphaPos = function (hsba, cal) { if ($(cal).data('wcolpick').enableAlpha) $(cal).data('wcolpick').alpha.css('left', Math.round($(cal).data('wcolpick').size * hsba.a)); }, setAlphaColor = function (rgba, cal) { if ($(cal).data('wcolpick').enableAlpha) { if (isInternetExplorer()) { //Compatibility with IE 6-9 var end = rgbaToHex(rgba).substring(0,6); $(cal).data('wcolpick').alphaBar.attr('style','filter:progid:DXImageTransform.Microsoft.gradient(GradientType=1,startColorstr=0,endColorstr=#'+end+'); -ms-filter:"progid:DXImageTransform.Microsoft.gradient(GradientType=1,startColorstr=0,endColorstr=#'+end+')";'); } else { var begin = 'rgba('+rgba.r+','+rgba.g+','+rgba.b+',0)', end = 'rgba('+rgba.r+','+rgba.g+','+rgba.b+',1)'; } $(cal).data('wcolpick').alphaBar.attr('style','background:-webkit-linear-gradient(left,'+begin+' 0%,'+end+' 100%); background:-moz-linear-gradient(left,'+begin+' 0%,'+end+' 100%); background:-ms-linear-gradient(left,'+begin+' 0%,'+end+' 100%); background:-o-linear-gradient(left,'+begin+' 0%,'+end+' 100%); background:linear-gradient(to right,'+begin+' 0%,'+end+' 100%);'); } }, //Set current and new colors setCurrentColor = function (rgba, cal) { $(cal).data('wcolpick').currentColor.css('backgroundColor', 'rgba('+rgba.r+','+rgba.g+','+rgba.b+','+rgba.a+')'); }, setNewColor = function (rgba, cal) { $(cal).data('wcolpick').newColor.css('backgroundColor', 'rgba('+rgba.r+','+rgba.g+','+rgba.b+','+rgba.a+')'); }, //Called when the new color is changed change = function () { var cal = $(this).parent().parent(), hsba, rgba, hex; if (this.parentNode.className.indexOf('_alpha') > 0) { hsba = { h: cal.data('wcolpick').color.h, s: cal.data('wcolpick').color.s, b: cal.data('wcolpick').color.b, a: fixAlpha(cal.data('wcolpick').fields.eq(7).val()/100) }; rgba = hsbaToRgba(hsba); hex = rgbaToHex(rgba); } else if (this.parentNode.className.indexOf('_hex') > 0) { rgba = hexToRgba(adaptHex(cal.data('wcolpick').fields.eq(0).val(), cal)); hsba = rgbaToHsba(rgba); hex = rgbaToHex(rgba); } else if (this.parentNode.className.indexOf('_hsb') > 0) { hsba = fixHSBA({ h: Math.round(cal.data('wcolpick').fields.eq(4).val()), s: Math.round(cal.data('wcolpick').fields.eq(5).val()), b: Math.round(cal.data('wcolpick').fields.eq(6).val()), a: cal.data('wcolpick').color.a }); rgba = hsbaToRgba(hsba); hex = rgbaToHex(rgba); } else { rgba = fixRGBA({ r: Math.round(cal.data('wcolpick').fields.eq(1).val()), g: Math.round(cal.data('wcolpick').fields.eq(2).val()), b: Math.round(cal.data('wcolpick').fields.eq(3).val()), a: cal.data('wcolpick').color.a }); hsba = rgbaToHsba(rgba); hex = rgbaToHex(rgba); } //Store new color cal.data('wcolpick').color = cloneHSBA(hsba, true); //Show new color setNewColor(rgba, cal.get(0)); //Fill fields with new color fillHSBFields(hsba, cal.get(0)); fillAlphaField(hsba, cal.get(0)); fillRGBFields(rgba, cal.get(0)); fillHexField(hex, cal.get(0)); //Setup other elements with new color setSelectorPos(hsba, cal.get(0)); setSelectorColor(hsba, cal.get(0)); setHuePos(hsba, cal.get(0)); setAlphaPos(hsba, cal.get(0)); setAlphaColor(rgba, cal.get(0)); //Fires onChange (bySetColor = false) var hsla = hsbaToHsla(hsba); cal.data('wcolpick').onChange.apply(cal.parent(), [{bySetColor:false, colorDiv:cal.get(0), el:cal.data('wcolpick').el, hex:hex.substring(0,6), hexa:hex, hsb:cloneHSBA(hsba, false), hsba:hsba, hsl:cloneHSLA(hsla, false), hsla:hsla, rgb:cloneRGBA(rgba, false), rgba:rgba}]); }, //Change style on blur and on focus of inputs blur = function () { $(this).parent().removeClass('wcolpick_focus'); }, focus = function () { $(this).parent().parent().data('wcolpick').fields.parent().removeClass('wcolpick_focus'); $(this).parent().addClass('wcolpick_focus'); }, //Increment/decrement arrows functions downIncrement = function (ev) { ev.preventDefault ? ev.preventDefault() : ev.returnValue = false; var field = $(this).parent().find('input').focus(); var current = { el: $(this).parent().addClass('wcolpick_changing'), max: this.parentNode.className.indexOf('_hsb_h') > 0 ? 360 : (this.parentNode.className.indexOf('_hsb') > 0 ? 100 : (this.parentNode.className.indexOf('_alpha') > 0 ? 100 : 255)), y: ev.pageY, field: field, val: Math.round(field.val()), preview: $(this).parent().parent().data('wcolpick').livePreview }; $(document).mouseup(current, upIncrement); $(document).mousemove(current, moveIncrement); }, moveIncrement = function (ev) { //livePreview = true: update colors | livePreview = false: update only field's value ev.data.field.val(fixVal(Math.round(ev.data.val - ev.pageY + ev.data.y), 0, ev.data.max)); if (ev.data.preview) change.apply(ev.data.field.get(0)); return false; }, upIncrement = function (ev) { //livePreview = true: do nothing | livePreview = false: update colors if (!ev.data.preview) change.apply(ev.data.field.get(0)); ev.data.el.removeClass('wcolpick_changing').find('input').focus(); $(document).off('mouseup', upIncrement); $(document).off('mousemove', moveIncrement); return false; }, //Alpha slider functions downAlpha = function (ev) { ev.preventDefault ? ev.preventDefault() : ev.returnValue = false; var current = { cal: $(this).parent(), x: $(this).offset().left, preview: $(this).parent().data('wcolpick').livePreview }; $(document).on('mouseup touchend',current,upAlpha); $(document).on('mousemove touchmove',current,moveAlpha); //Update alpha value with selected value var pageX = ((ev.type == 'touchstart') ? ev.originalEvent.changedTouches[0].pageX : ev.pageX); change.apply( current.cal.data('wcolpick').fields .eq(7).val(Math.round(100 * fixVal(pageX - current.x, 0, current.cal.data('wcolpick').size) / current.cal.data('wcolpick').size)) .get(0) ); return false; }, moveAlpha = function (ev) { var pageX = ((ev.type == 'touchmove') ? ev.originalEvent.changedTouches[0].pageX : ev.pageX); var alpha = Math.round(100 * fixVal(pageX - ev.data.x, 0, ev.data.cal.data('wcolpick').size) / ev.data.cal.data('wcolpick').size); //livePreview = true: update colors | livePreview = false: update only position if (ev.data.preview) change.apply(ev.data.cal.data('wcolpick').fields.eq(7).val(alpha).get(0)); else setAlphaPos({a:alpha/100}, ev.data.cal.get(0)); return false; }, upAlpha = function (ev) { //livePreview = true: do nothing | livePreview = false: update colors if (!ev.data.preview) { var pageX = ((ev.type == 'touchend') ? ev.originalEvent.changedTouches[0].pageX : ev.pageX); change.apply( ev.data.cal.data('wcolpick').fields .eq(7).val(Math.round(100 * fixVal(pageX - ev.data.x, 0, ev.data.cal.data('wcolpick').size) / ev.data.cal.data('wcolpick').size)) .get(0) ); } $(document).off('mouseup touchend',upAlpha); $(document).off('mousemove touchmove',moveAlpha); return false; }, //Hue slider functions downHue = function (ev) { ev.preventDefault ? ev.preventDefault() : ev.returnValue = false; var current = { cal: $(this).parent(), y: $(this).offset().top, preview: $(this).parent().data('wcolpick').livePreview }; $(document).on('mouseup touchend',current,upHue); $(document).on('mousemove touchmove',current,moveHue); //Update hue value with selected value var pageY = ((ev.type == 'touchstart') ? ev.originalEvent.changedTouches[0].pageY : ev.pageY); change.apply( current.cal.data('wcolpick').fields .eq(4).val(Math.round(360 * (current.cal.data('wcolpick').size - fixVal(pageY - current.y, 0, current.cal.data('wcolpick').size)) / current.cal.data('wcolpick').size)) .get(0) ); return false; }, moveHue = function (ev) { var pageY = ((ev.type == 'touchmove') ? ev.originalEvent.changedTouches[0].pageY : ev.pageY); var hue = Math.round(360 * (ev.data.cal.data('wcolpick').size - fixVal(pageY - ev.data.y, 0, ev.data.cal.data('wcolpick').size)) / ev.data.cal.data('wcolpick').size); //livePreview = true: update colors | livePreview = false: update only position if (ev.data.preview) change.apply(ev.data.cal.data('wcolpick').fields.eq(4).val(hue).get(0)); else setHuePos({h:hue}, ev.data.cal.get(0)); return false; }, upHue = function (ev) { //livePreview = true: do nothing | livePreview = false: update colors if (!ev.data.preview) { var pageY = ((ev.type == 'touchend') ? ev.originalEvent.changedTouches[0].pageY : ev.pageY); change.apply( ev.data.cal.data('wcolpick').fields .eq(4).val(Math.round(360 * (ev.data.cal.data('wcolpick').size - fixVal(pageY - ev.data.y, 0, ev.data.cal.data('wcolpick').size)) / ev.data.cal.data('wcolpick').size)) .get(0) ); } $(document).off('mouseup touchend',upHue); $(document).off('mousemove touchmove',moveHue); return false; }, //Color selector functions downSelector = function (ev) { ev.preventDefault ? ev.preventDefault() : ev.returnValue = false; var current = { cal: $(this).parent(), pos: $(this).offset(), preview: $(this).parent().data('wcolpick').livePreview }; $(document).on('mouseup touchend',current,upSelector); $(document).on('mousemove touchmove',current,moveSelector); //Update saturation and brightness with selected values var pageX, pageY; if(ev.type == 'touchstart') {pageX = ev.originalEvent.changedTouches[0].pageX; pageY = ev.originalEvent.changedTouches[0].pageY;} else {pageX = ev.pageX; pageY = ev.pageY;} change.apply( current.cal.data('wcolpick').fields .eq(6).val(Math.round(100 * (current.cal.data('wcolpick').size - fixVal(pageY - current.pos.top, 0, current.cal.data('wcolpick').size)) / current.cal.data('wcolpick').size)).end() .eq(5).val(Math.round(100 * fixVal(pageX - current.pos.left, 0, current.cal.data('wcolpick').size) / current.cal.data('wcolpick').size)) .get(0) ); return false; }, moveSelector = function (ev) { var pageX, pageY; if(ev.type == 'touchmove') {pageX = ev.originalEvent.changedTouches[0].pageX; pageY = ev.originalEvent.changedTouches[0].pageY;} else {pageX = ev.pageX; pageY = ev.pageY;} var saturation = Math.round(100 * fixVal(pageX - ev.data.pos.left, 0, ev.data.cal.data('wcolpick').size) / ev.data.cal.data('wcolpick').size); var brightness = Math.round(100 * (ev.data.cal.data('wcolpick').size - fixVal(pageY - ev.data.pos.top, 0, ev.data.cal.data('wcolpick').size)) / ev.data.cal.data('wcolpick').size); //livePreview = true: update colors | livePreview = false: update only position if (ev.data.preview) change.apply(ev.data.cal.data('wcolpick').fields.eq(6).val(brightness).end().eq(5).val(saturation).get(0)); else setSelectorPos({s:saturation, b:brightness}, ev.data.cal.get(0)); return false; }, upSelector = function (ev) { //livePreview = true: do nothing | livePreview = false: update colors if (!ev.data.preview) { var pageX, pageY; if(ev.type == 'touchend') {pageX = ev.originalEvent.changedTouches[0].pageX; pageY = ev.originalEvent.changedTouches[0].pageY; } else { pageX = ev.pageX; pageY = ev.pageY;} change.apply( ev.data.cal.data('wcolpick').fields .eq(6).val(Math.round(100 * (ev.data.cal.data('wcolpick').size - fixVal(pageY - ev.data.pos.top, 0, ev.data.cal.data('wcolpick').size)) / ev.data.cal.data('wcolpick').size)).end() .eq(5).val(Math.round(100 * fixVal(pageX - ev.data.pos.left, 0, ev.data.cal.data('wcolpick').size) / ev.data.cal.data('wcolpick').size)) .get(0) ); } $(document).off('mouseup touchend',upSelector); $(document).off('mousemove touchmove',moveSelector); return false; }, //Change values of the fields with up/down keys keyDownFields = function(ev) { if ($(this).parent().parent().data('wcolpick').enableUpDown) { //Not triggered for hexadecimal field (there is no standard to define an order among the colors) if (this.parentNode.className.indexOf('_hex_field') == -1) { if (ev.which == 38 || ev.which == 40) { ev.preventDefault(); //Get the value from the selected element var value = $(this).val(); if (ev.which == 38) value++; //Up else value--; //Down //Set the new value and apply changes change.apply($(this).val(value).get(0)); } } } }, //Submit button clickSubmit = function () { var cal = $(this).parent(); var hsba = cloneHSBA(cal.data('wcolpick').color, true); var rgba = hsbaToRgba(hsba); var hex = rgbaToHex(rgba); cal.data('wcolpick').origColor = cloneHSBA(hsba, true); setCurrentColor(rgba, cal.get(0)); //Fires onSubmit var hsla = hsbaToHsla(hsba); cal.data('wcolpick').onSubmit({colorDiv:cal.get(0), el:cal.data('wcolpick').el, hex:hex.substring(0,6), hexa:hex, hsb:cloneHSBA(hsba, false), hsba:hsba, hsl:cloneHSLA(hsla, false), hsla:hsla, rgb:cloneRGBA(rgba, false), rgba:rgba}); }, //Restore original color by clicking on current color restoreOriginal = function () { var cal = $(this).parent().parent(); var hsba = cloneHSBA(cal.data('wcolpick').origColor, true); var rgba = hsbaToRgba(hsba); var hex = rgbaToHex(rgba); cal.data('wcolpick').color = cloneHSBA(hsba, true); //Reapplies current color to all elements fillHexField(hex, cal.get(0)); fillRGBFields(rgba, cal.get(0)); fillHSBFields(hsba, cal.get(0)); fillAlphaField(hsba, cal.get(0)); setSelectorPos(hsba, cal.get(0)); setSelectorColor(hsba, cal.get(0)); setHuePos(hsba, cal.get(0)); setAlphaPos(hsba, cal.get(0)); setAlphaColor(rgba, cal.get(0)); setNewColor(rgba, cal.get(0)); //Fires onChange (bySetColor = false) var hsla = hsbaToHsla(hsba); cal.data('wcolpick').onChange.apply(cal.parent(), [{bySetColor:false, colorDiv:cal.get(0), el:cal.data('wcolpick').el, hex:hex.substring(0,6), hexa:hex, hsb:cloneHSBA(hsba, false), hsba:hsba, hsl:cloneHSLA(hsla, false), hsla:hsla, rgb:cloneRGBA(rgba, false), rgba:rgba}]); }, //Fix alpha value, if the user enters a wrong value fixAlpha = function (alpha) { return fixVal(isNaN(alpha) ? 1 : alpha, 0, 1); }, //Remove alpha from hexadecimal, if alpha channel is disabled adaptHex = function (hex, cal) { if (hex === undefined) hex = '000000ff'; if (!cal.data('wcolpick').enableAlpha) { hex = removeAlpha(hex); } return hex; }, //Remove alpha value from hexadecimals/objects removeAlpha = function (col) { if (col !== undefined) { if (typeof col === 'string') { if (col.indexOf('#') != 0) { if (col.length == 4) col = col.substring(0,3); if (col.length == 8) col = col.substring(0,6); } else { if (col.length == 5) col = col.substring(0,4); if (col.length == 9) col = col.substring(0,7); } } else if (col.a !== undefined) col.a = 1; } return col; }, //Clone color objects cloneRGBA = function (rgba, withAlpha) { if (rgba === undefined) return {r:0, g:0, b:0, a:1}; if (withAlpha) { if (rgba.a === undefined) return {r:rgba.r, g:rgba.g, b:rgba.b, a:1}; else return {r:rgba.r, g:rgba.g, b:rgba.b, a:rgba.a}; } else return {r:rgba.r, g:rgba.g, b:rgba.b}; }, cloneHSBA = function (hsba, withAlpha) { if (hsba === undefined) return {h:0, s:0, b:0, a:1}; if (withAlpha) { if (hsba.a === undefined) return {h:hsba.h, s:hsba.s, b:hsba.b, a:1}; else return {h:hsba.h, s:hsba.s, b:hsba.b, a:hsba.a}; } else return {h:hsba.h, s:hsba.s, b:hsba.b}; }, cloneHSLA = function (hsla, withAlpha) { if (hsla === undefined) return {h:0, s:0, l:0, a:1}; if (withAlpha) { if (hsla.a === undefined) return {h:hsla.h, s:hsla.s, l:hsla.l, a:1}; else return {h:hsla.h, s:hsla.s, l:hsla.l, a:hsla.a}; } else return {h:hsla.h, s:hsla.s, l:hsla.l}; }, //Compare color objects compareHSBA = function (hsba1, hsba2) { if (hsba1 === undefined || hsba2 === undefined) return false; return (hsba1.h == hsba2.h && hsba1.s == hsba2.s && hsba1.b == hsba2.b && hsba1.a == hsba2.a); }, //Shows/hides the color picker show = function (ev) { //Prevent the trigger of any direct parent if (ev) ev.stopPropagation(); //cal is the color picker (dom object) var cal = $('#' + $(this).data('wcolpickId')), overridePos = {}; //Trying to access to a property (e.g. color) and, if is generated an error, abort! try {var temp = cal.data('wcolpick').color;} catch (e) {return this;} //Polyfill fixes if (ev && !cal.data('wcolpick').polyfill) ev.preventDefault(); //Fires onBeforeShow cal.data('wcolpick').onBeforeShow.apply(this, [{colorDiv:cal.get(0), el:cal.data('wcolpick').el, overridePos:overridePos}]); //If flat is true, simply shows the color picker! if (cal.data('wcolpick').flat) { //Fires onShow if (!(cal.data('wcolpick').onShow.apply(this, [{colorDiv:cal.get(0), el:cal.data('wcolpick').el}]) != false)) return this; //Shows the picker and terminates cal.show(); return; } //Positions the color picker... if (overridePos.left === undefined || isNaN(overridePos.left) || overridePos.top === undefined || isNaN(overridePos.top)) { //Calculates the correctly position var finalPos = {top:0, left:0}, pos = cal.data('wcolpick').appendedToBody ? $(this).offset() : $(this).position(); if (cal.data('wcolpick').position == 'center') { //... on center of viewport //Positions the color picker on top-left corner of viewport finalPos.top = pos.top - ($(this).offset().top - $(window).scrollTop()); finalPos.left = pos.left - ($(this).offset().left - $(window).scrollLeft()); //Positions the color picker on center of viewport by adding coordinates var centerViewport = {top:$(window).height()/2, left:$(window).width()/2}; finalPos.top += centerViewport.top - cal.outerHeight()/2; finalPos.left += centerViewport.left - cal.outerWidth()/2; } else { //... automatically (default) //Positions the color picker under his related html object finalPos.top = pos.top + this.offsetHeight; finalPos.left = pos.left; //Fixes, if the color picker is showing outside of viewport if (outOfViewportHeight(cal, $(this), this) && $(this).offset().top - $(window).scrollTop() >= cal.outerHeight()) { finalPos.top -= (cal.outerHeight() + this.offsetHeight); } if (outOfViewportWidth(cal, $(this))) { if ($(this).offset().left - $(window).scrollLeft() + this.offsetWidth >= cal.outerWidth()) { finalPos.left -= (cal.outerWidth() - this.offsetWidth); } else { var leftMargin = $(this).offset().left - $(window).scrollLeft(); var outWidth = leftMargin + cal.outerWidth() - $(window).width(); if (leftMargin > outWidth) { finalPos.left -= outWidth; } else { finalPos.left -= leftMargin; } } } } //Applies the result cal.css({top: finalPos.top + 'px', left: finalPos.left + 'px'}); } else { //Applies the user-defined position cal.css({top: overridePos.top + 'px', left: overridePos.left + 'px'}); } //Fires onShow if (!(cal.data('wcolpick').onShow.apply(this, [{colorDiv:cal.get(0), el:cal.data('wcolpick').el}]) != false)) return this; //Shows the picker cal.show(); //Hides when user clicks outside $('html').mousedown({cal:cal}, hide); cal.mousedown(function(ev){ev.stopPropagation();}) }, hide = function (ev) { var cal = $('#' + $(this).data('wcolpickId')); if (ev) cal = ev.data.cal; //Trying to access to a property (e.g. color) and, if is generated an error, abort! try {var temp = cal.data('wcolpick').color;} catch (e) {return this;} //Fires onHide if (!(cal.data('wcolpick').onHide.apply(this, [{colorDiv:cal.get(0), el:cal.data('wcolpick').el}]) != false)) return this; //Hides the picker cal.hide(); $('html').off('mousedown', hide); }, //Detect if the color picker is out of viewport outOfViewportHeight = function (cal, wrapEl, domEl) { var calViewTop = wrapEl.offset().top - $(window).scrollTop() + domEl.offsetHeight; //Top of the color picker in viewport var calHeight = cal.outerHeight(); //Height of the color picker var viewHeight = $(window).height(); //Viewport height return (calViewTop + calHeight > viewHeight); }, outOfViewportWidth = function (cal, wrapEl) { var calViewLeft = wrapEl.offset().left - $(window).scrollLeft(); //Left of the color picker in viewport var calWidth = cal.outerWidth(); //Width of the color picker var viewWidth = $(window).width(); //Viewport width return (calViewLeft + calWidth > viewWidth); }, //Destroys the color picker destroy = function (ev) { var cal = $('#' + $(this).data('wcolpickId')); if (ev) cal = ev.data.cal; //Fires onDestroy if (!(cal.data('wcolpick').onDestroy.apply(this, [{colorDiv:cal.get(0), el:cal.data('wcolpick').el}]) != false)) return this; //Destroys the picker cal.remove(); //Prevent firing of hide event on a destroyed object! //bySetColor $('html').off('mousedown', hide); }, //Generate a random unique id getUniqueID = (function () { var cnt = Math.round(Math.random() * 10000); return function () { cnt += 1; return cnt; }; })(), //Used to detect if the browser in use is Microsoft Internet Explorer isInternetExplorer = function () { var isIE = (navigator.appName === 'Microsoft Internet Explorer'); if (!isIE) return false; var UA = navigator.userAgent.toLowerCase(); var IEver = parseFloat(UA.match( /msie ([0-9]{1,}[\.0-9]{0,})/ )[1]); var ngIE = (isIE && IEver < 10); return ngIE; }; return { init: function (opt) { opt = $.extend({}, defaults, opt||{}); //Set color if (typeof opt.color === 'string') opt.color = hexToHsba(opt.color); else if (opt.color.r !== undefined && opt.color.g !== undefined && opt.color.b !== undefined) opt.color = rgbaToHsba(fixRGBA(opt.color)); else if (opt.color.h !== undefined && opt.color.s !== undefined && opt.color.b !== undefined) opt.color = fixHSBA(opt.color); else if (opt.color.h !== undefined && opt.color.s !== undefined && opt.color.l !== undefined) opt.color = hslaToHsba(fixHSLA(opt.color)); else opt.color = {h:0, s:0, b:0, a:1}; //Black = Error color //Normalizes string options opt.arrowsColor = opt.arrowsColor.toLowerCase(); opt.checkersColor = opt.checkersColor.toLowerCase(); opt.colorScheme = opt.colorScheme.toLowerCase(); opt.layout = opt.layout.toLowerCase(); opt.position = opt.position.toLowerCase(); opt.showEvent = opt.showEvent.toLowerCase(); opt.submitColor = opt.submitColor.toLowerCase(); opt.variant = opt.variant.toLowerCase(); if (typeof opt.fieldsBackground === 'string') opt.fieldsBackground = opt.fieldsBackground.toLowerCase(); if (typeof opt.submitBackground === 'string') opt.submitBackground = opt.submitBackground.toLowerCase(); //For each selected DOM element return this.each(function () { //If the element does not have an ID if (!$(this).data('wcolpickId')) { var options = $.extend({}, opt); //Fixes color if alpha is disabled if (!opt.enableAlpha) opt.color = removeAlpha(opt.color); //Setup current color options.origColor = cloneHSBA(opt.color, true); // Set polyfill if (typeof opt.polyfill == 'function') options.polyfill = opt.polyfill(this); //Input field operations options.input = $(this).is('input'); //Polyfill fixes if (options.polyfill && options.input && this.type === 'color') return; //Generate and assign a random ID var id = 'colorpicker_' + getUniqueID(); $(this).data('wcolpickId', id); //Set the tpl's ID and get the HTML var cal = $(tpl).attr('id', id); //Setup size of the selected variant (Add other "else-if" for other future variants) if (options.variant == 'small') options.size = 160; //Small Version! else if (options.variant == 'extra-large') options.size = 300; //Extra Large Version! else options.size = 225; //Standard Version (default)! //Loading the choosen layout if (options.variant == 'small') { //Add class according to layout (small) cal.addClass('wcolpickS wcolpickS_'+options.layout+(options.enableSubmit?'':' wcolpickS_'+options.layout+'_ns')); if(!options.enableAlpha) cal.addClass('wcolpickS_noalpha wcolpickS_'+options.layout+'_noalpha'+(options.enableSubmit?'':' wcolpickS_'+options.layout+'_noalpha_ns')); //Disable alpha channel, if requested } else if (options.variant == 'extra-large') { //Add class according to layout (extra-large) cal.addClass('wcolpickXL wcolpickXL_'+options.layout+(options.enableSubmit?'':' wcolpickXL_'+options.layout+'_ns')); if(!options.enableAlpha) cal.addClass('wcolpickXL_noalpha wcolpickXL_'+options.layout+'_noalpha'+(options.enableSubmit?'':' wcolpickXL_'+options.layout+'_noalpha_ns')); //Disable alpha channel, if requested } else { //Add class according to layout (default -> standard) cal.addClass('wcolpick_'+options.layout+(options.enableSubmit?'':' wcolpick_'+options.layout+'_ns')); if(!options.enableAlpha) cal.addClass('wcolpick_noalpha wcolpick_'+options.layout+'_noalpha'+(options.enableSubmit?'':' wcolpick_'+options.layout+'_noalpha_ns')); //Disable alpha channel, if requested } //Loading Compact layout, if requested if (options.compactLayout) { if (options.variant == 'small') { //Add class according to layout (small) cal.addClass('wcolpickS_compact wcolpickS_compact_'+options.layout+(options.enableSubmit?'':' wcolpickS_compact_'+options.layout+'_ns')); if(!options.enableAlpha) cal.addClass('wcolpickS_compact_noalpha wcolpickS_compact_'+options.layout+'_noalpha'+(options.enableSubmit?'':' wcolpickS_compact_'+options.layout+'_noalpha_ns')); //Disable alpha channel, if requested } else if (options.variant == 'extra-large') { //Add class according to layout (extra-large) cal.addClass('wcolpickXL_compact wcolpickXL_compact_'+options.layout+(options.enableSubmit?'':' wcolpickXL_compact_'+options.layout+'_ns')); if(!options.enableAlpha) cal.addClass('wcolpickXL_compact_noalpha wcolpickXL_compact_'+options.layout+'_noalpha'+(options.enableSubmit?'':' wcolpickXL_compact_'+options.layout+'_noalpha_ns')); //Disable alpha channel, if requested } else { //Add class according to layout (default -> standard) cal.addClass('wcolpick_compact wcolpick_compact_'+options.layout+(options.enableSubmit?'':' wcolpick_compact_'+options.layout+'_ns')); if(!options.enableAlpha) cal.addClass('wcolpick_compact_noalpha wcolpick_compact_'+options.layout+'_noalpha'+(options.enableSubmit?'':' wcolpick_compact_'+options.layout+'_noalpha_ns')); //Disable alpha channel, if requested } } //Loading the choosen color scheme if (options.colorScheme.indexOf('light') == 0) { //All light color schemes start with "light" cal.addClass('wcolpick_light'); //Loading default light color scheme if(options.colorScheme != 'light') cal.addClass('wcolpick_'+options.colorScheme); //Loading light-based color scheme //INFO: You can implement light-based color schemes, in css, naming them: light-[name] (IMPORTANT: Use only lowercase names!) } else if (options.colorScheme.indexOf('dark') == 0) { //All dark color schemes start with "dark" cal.addClass('wcolpick_dark'); //Loading default dark color scheme if(options.colorScheme != 'dark') cal.addClass('wcolpick_'+options.colorScheme); //Loading dark-based color scheme //INFO: You can implement dark-based color schemes, in css, naming them: dark-[name] (IMPORTANT: Use only lowercase names!) } else { //If the scheme does not starts with "light" or "dark" cal.addClass('wcolpick_light'); //Loading default color scheme for all (light) cal.addClass('wcolpick_'+options.colorScheme); //Loading the "strange" color scheme } //Change color scheme for arrows, if requested if (options.arrowsColor == 'light') cal.addClass('wcolpick_lightArrs'); else if (options.arrowsColor == 'dark') cal.addClass('wcolpick_darkArrs'); //Change color scheme for checkerboards, if requested if (options.checkersColor == 'light') cal.addClass('wcolpick_lightCheckerboards'); else if (options.checkersColor == 'dark') cal.addClass('wcolpick_darkCheckerboards'); //Change color scheme for submit button, if requested if (options.submitColor == 'light') cal.addClass('wcolpick_lightSubmit'); else if (options.submitColor == 'dark') cal.addClass('wcolpick_darkSubmit'); //Hide outlines, if requested if (!options.colorSelOutline) cal.addClass('wcolpick_noCSOutline'); if (!options.hueOutline) cal.addClass('wcolpick_noHOutline'); if (!options.alphaOutline) cal.addClass('wcolpick_noAOutline'); if (!options.colorOutline) cal.addClass('wcolpick_noNCOutline'); //Set border width cal.css('border-width', options.border + 'px'); //Setup submit button options.submit = cal.find('div.wcolpick_submit').click(clickSubmit); //Setup input fields options.fields = cal.find('input').change(change).keydown(keyDownFields).blur(blur).focus(focus); //If alpha channel is disabled, set hex field maxlength to 6 if (!options.enableAlpha) options.fields.eq(0).prop('maxlength', 6); //Setup readonly attribute to fields for (var i = 0; i < 8; i++) options.fields.eq(i).prop('readonly', options.readonlyFields); if (options.readonlyHexField) options.fields.eq(0).prop('readonly', options.readonlyHexField); //Setup color of fields, submit button, external border, and background (if a color is different than default, it will override the default color) if (options.fieldsBackground != 'default') { var colstr = encodeToCSS(options.fieldsBackground); for (var i = 0; i < 8; i++) options.fields.eq(i).parent().css('background',colstr); } if (options.submitBackground != 'default') options.submit.css('background',encodeToCSS(options.submitBackground)); if (options.backgroundColor != 'default') cal.css('background',encodeToCSS(options.backgroundColor)); if (options.borderColor != 'default') cal.css('borderColor',encodeToCSS(options.borderColor)); //Setup restoreOriginal to current color's click event cal.find('div.wcolpick_field_arrs').mousedown(downIncrement).end().find('div.wcolpick_current_color').click(restoreOriginal); //Setup color selector options.selector = cal.find('div.wcolpick_color').on('mousedown touchstart',downSelector); options.selectorIndic = options.selector.find('div.wcolpick_selector_outer'); //Setup hue bar and alpha bar options.el = this; options.hue = cal.find('div.wcolpick_hue_arrs'); options.hueBar = cal.find('div.wcolpick_hue_overlay'); options.alpha = cal.find('div.wcolpick_alpha_arrs'); options.alphaBar = cal.find('div.wcolpick_alpha_overlay'); //Painting hue bar var stops = ['#ff0000','#ff0080','#ff00ff','#8000ff','#0000ff','#0080ff','#00ffff','#00ff80','#00ff00','#80ff00','#ffff00','#ff8000','#ff0000']; if (isInternetExplorer()) { //Compatibility with IE 6-9 var i, div; for (i=0; i<=11; i++) { div = $('<div></div>').attr('style','height:8.333333%; filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='+stops[i]+',endColorstr='+stops[i+1]+'); -ms-filter:"progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='+stops[i]+',endColorstr='+stops[i+1]+')";'); options.hueBar.append(div); } } else { var stopList = stops.join(','); options.hueBar.attr('style','background:-webkit-linear-gradient(top,'+stopList+'); background:-moz-linear-gradient(top,'+stopList+'); background:-ms-linear-gradient(top,'+stopList+'); background:-o-linear-gradient(top,'+stopList+'); background:linear-gradient(to bottom,'+stopList+');'); } //Setup remaining events, new, and current color cal.find('div.wcolpick_hue').on('mousedown touchstart',downHue); cal.find('div.wcolpick_alpha').on('mousedown touchstart',downAlpha); options.newColor = cal.find('div.wcolpick_new_color'); options.currentColor = cal.find('div.wcolpick_current_color'); //Store options cal.data('wcolpick', options); //Fill with default color var rgba = hsbaToRgba(options.color); fillHSBFields(options.color, cal.get(0)); fillAlphaField(options.color, cal.get(0)); fillRGBFields(rgba, cal.get(0)); fillHexField(rgbaToHex(rgba), cal.get(0)); setSelectorPos(options.color, cal.get(0)); setSelectorColor(options.color, cal.get(0)); setHuePos(options.color, cal.get(0)); setAlphaPos(options.color, cal.get(0)); setAlphaColor(rgba, cal.get(0)); setCurrentColor(rgba, cal.get(0)); setNewColor(rgba, cal.get(0)); //Append to parent if flat=false, else show in place if (options.flat) { cal.appendTo(this).show(); cal.css({position: 'relative', display: 'block'}); } else { cal.data('wcolpick').appendedToBody = options.appendToBody; if (!options.appendToBody) cal.appendTo($(this).parent()); else cal.appendTo(document.body); $(this).on(options.showEvent, show); cal.css({position: 'absolute'}); } //Loading completed cal.data('wcolpick').onLoaded.apply(cal.parent(), [{colorDiv:cal.get(0), el:cal.data('wcolpick').el}]); } }); }, //Shows the picker showColpick: function() { return this.each( function () { if ($(this).data('wcolpickId')) { show.apply(this); } }); }, //Hides the picker hideColpick: function() { return this.each( function () { if ($(this).data('wcolpickId')) { hide.apply(this); } }); }, //Destroys the picker destroyColpick: function() { return this.each( function () { if ($(this).data('wcolpickId')) { destroy.apply(this); } }); }, //Sets a color as new and current (Default: Set only as new color) setColpickColor: function(col, setCurrent) { if (col !== undefined) { //If color is undefined, do nothing! if (typeof col === 'string') col = hexToHsba(col); else if (col.r !== undefined && col.g !== undefined && col.b !== undefined) col = rgbaToHsba(fixRGBA(col)); else if (col.h !== undefined && col.s !== undefined && col.b !== undefined) col = fixHSBA(col); else if (col.h !== undefined && col.s !== undefined && col.l !== undefined) col = hslaToHsba(fixHSLA(col)); else return this; //If color is not recognized, do nothing! if (setCurrent === undefined) setCurrent = false; //Default: Set only as new color return this.each(function(){ if ($(this).data('wcolpickId')) { var cal = $('#' + $(this).data('wcolpickId')); //Fixes color if alpha is disabled if (!cal.data('wcolpick').enableAlpha) col = removeAlpha(col); //Check if the color is actually changed and, if is true, do nothing! if (setCurrent) { if (compareHSBA(col, cal.data('wcolpick').color) && compareHSBA(col, cal.data('wcolpick').origColor)) return this; } else { if (compareHSBA(col, cal.data('wcolpick').color)) return this; } //Setup new color cal.data('wcolpick').color = cloneHSBA(col, true); var rgba = hsbaToRgba(col); var hex = rgbaToHex(rgba); //Applies color to all elements fillHSBFields(col, cal.get(0)); fillAlphaField(col, cal.get(0)); fillRGBFields(rgba, cal.get(0)); fillHexField(hex, cal.get(0)); setSelectorPos(col, cal.get(0)); setSelectorColor(col, cal.get(0)); setHuePos(col, cal.get(0)); setAlphaPos(col, cal.get(0)); setAlphaColor(rgba, cal.get(0)); setNewColor(rgba, cal.get(0)); //If setCurrent is "true", sets the color as current if (setCurrent) { cal.data('wcolpick').origColor = cloneHSBA(col, true); setCurrentColor(rgba, cal.get(0)); } //Fires onChange (bySetColor = true) var hsla = hsbaToHsla(col); cal.data('wcolpick').onChange.apply(cal.parent(), [{bySetColor:true, colorDiv:cal.get(0), el:cal.data('wcolpick').el, hex:hex.substring(0,6), hexa:hex, hsb:cloneHSBA(col, false), hsba:col, hsl:cloneHSLA(hsla, false), hsla:hsla, rgb:cloneRGBA(rgba, false), rgba:rgba}]); } }); } }, //Returns the selected color (Default: Hsb color with alpha value, and get new color (not current)) getColpickColor: function(type, getCurrent) { var cal = $('#' + $(this).data('wcolpickId')); if (getCurrent === undefined) getCurrent = false; //Default: Get new color (not current) if (type === undefined) type = 'hsba'; //Default: Hsb color with alpha value var withAlpha = (type.indexOf('a') != -1); //Getting the color var col = getCurrent ? cloneHSBA(cal.data('wcolpick').origColor, true) : cloneHSBA(cal.data('wcolpick').color, true); if (type.indexOf('rgb') != -1) { var rgba = hsbaToRgba(col); return withAlpha ? {r:rgba.r, g:rgba.g, b:rgba.b, a:rgba.a} : {r:rgba.r, g:rgba.g, b:rgba.b}; } else if (type.indexOf('hsl') != -1) { var hsla = hsbaToHsla(col); return withAlpha ? {h:hsla.h, s:hsla.s, l:hsla.l, a:hsla.a} : {h:hsla.h, s:hsla.s, l:hsla.l}; } else if (type.indexOf('hex') != -1) return withAlpha ? hsbaToHex(col) : hsbaToHex(col).substring(0,6); else return withAlpha ? {h:col.h, s:col.s, b:col.b, a:col.a} : {h:col.h, s:col.s, b:col.b}; } }; }(); //Color space convertions var hexToRgba = function (hex) { if (hex === undefined) return {r:0, g:0, b:0, a:1}; if (hex.indexOf('#') == 0) hex = hex.substring(1); if (isValidHex(hex)) { if (hex.length == 3) hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2] + 'ff'; else if (hex.length == 4) hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3]; else if (hex.length == 6) hex = hex + 'ff'; else if (hex.length != 8) return {r:0, g:0, b:0, a:1}; } else { return {r:0, g:0, b:0, a:1}; } var hexI = parseInt(hex,16); var rgba = {r: hexI >>> 24, g: (hexI & 0x00FF0000) >>> 16, b: (hexI & 0x0000FF00) >>> 8, a: (hexI & 0x000000FF) / 255}; return rgba; }; var hexToHsba = function (hex) { return rgbaToHsba(hexToRgba(hex)); }; var hexToHsla = function (hex) { return rgbaToHsla(hexToRgba(hex)); }; var rgbaToHex = function (rgba) { if (rgba === undefined) return '000000ff'; if (rgba.a === undefined) rgba.a = 1; var a = Math.round(rgba.a * 255); var hex = [ rgba.r.toString(16), rgba.g.toString(16), rgba.b.toString(16), a.toString(16) ]; $.each(hex, function (nr, val) { if (val.length == 1) hex[nr] = '0' + val; }); return hex.join(''); }; var rgbaToHsba = function (rgba) { if (rgba === undefined) return {h:0, s:0, b:0, a:1}; if (rgba.a === undefined) rgba.a = 1; var r = rgba.r / 255, g = rgba.g / 255, b = rgba.b / 255; var min = Math.min(r, Math.min(g, b)); var max = Math.max(r, Math.max(g, b)); var delta = max - min; var brightness = max; var saturation = max != 0 ? delta / max : 0; var hue = delta != 0 ? (r == max ? (g - b) / delta : g == max ? ((b - r) / delta) + 2 : ((r - g) / delta) + 4) * 60 : 0; if (hue < 0) hue += 360; return fixHSBA({h: hue, s: saturation * 100, b: brightness * 100, a: rgba.a}); }; var rgbaToHsla = function (rgba) { if (rgba === undefined) return {h:0, s:0, l:0, a:1}; if (rgba.a === undefined) rgba.a = 1; var r = rgba.r / 255, g = rgba.g / 255, b = rgba.b / 255; var min = Math.min(r, Math.min(g, b)); var max = Math.max(r, Math.max(g, b)); var delta = max - min; var lightness = (max + min) / 2; var saturation = delta != 0 ? delta / (1 - Math.abs(max + min - 1)) : 0; var hue = delta != 0 ? (r == max ? (g - b) / delta : g == max ? ((b - r) / delta) + 2 : ((r - g) / delta) + 4) * 60 : 0; if (hue < 0) hue += 360; return fixHSLA({h: hue, s: saturation * 100, l: lightness * 100, a: rgba.a}); }; var hsbaToHex = function (hsba) { return rgbaToHex(hsbaToRgba(hsba)); }; var hsbaToRgba = function (hsba) { if (hsba === undefined) return {r:0, g:0, b:0, a:1}; if (hsba.a === undefined) hsba.a = 1; var hsbaL = {h: hsba.h, s: hsba.s / 100, b: hsba.b / 100, a: hsba.a}; var red, green, blue; if (hsbaL.s == 0) red = green = blue = hsbaL.b; else { var t1 = hsbaL.b; var t2 = (1 - hsbaL.s) * hsbaL.b; var t3 = (t1 - t2) * (hsbaL.h % 60) / 60; if (hsbaL.h < 60 || hsbaL.h == 360) { red = t1; blue = t2; green = t2 + t3; } else if (hsbaL.h < 120) { green = t1; blue = t2; red = t1 - t3; } else if (hsbaL.h < 180) { green = t1; red = t2; blue = t2 + t3; } else if (hsbaL.h < 240) { blue = t1; red = t2; green = t1 - t3; } else if (hsbaL.h < 300) { blue = t1; green = t2; red = t2 + t3; } else { red = t1; green = t2; blue = t1 - t3; } } return fixRGBA({r: Math.round(red * 255), g: Math.round(green * 255), b: Math.round(blue * 255), a: hsbaL.a}); }; var hsbaToHsla = function (hsba) { if (hsba === undefined) return {h:0, s:0, l:0, a:1}; if (hsba.a === undefined) hsba.a = 1; var hsbaL = {h: hsba.h, s: hsba.s / 100, b: hsba.b / 100, a: hsba.a}; var lightness = hsbaL.b * (2 - hsbaL.s) / 2; var saturation = lightness != 0 && lightness != 1 ? hsba.b * hsba.s / (1 - Math.abs((2 * lightness) - 1)) : 0; return fixHSLA({h: hsbaL.h, s: saturation * 100, l: lightness * 100, a: hsbaL.a}); }; var hslaToHex = function (hsla) { return rgbaToHex(hslaToRgba(hsla)); }; var hslaToRgba = function (hsla) { if (hsla === undefined) return {r:0, g:0, b:0, a:1}; if (hsla.a === undefined) hsla.a = 1; var hslaL = {h: hsla.h, s: hsla.s / 100, l: hsla.l / 100, a: hsla.a}; var red, green, blue; var c = (1 - Math.abs(2 * hslaL.l - 1)) * hslaL.s; var x = c * (1 - Math.abs((hslaL.h / 60 % 2) - 1)); var m = hslaL.l - (c / 2); if (hslaL.h < 60 || hslaL.h == 360) { red = c + m; green = x + m; blue = m; } else if (hslaL.h < 120) { red = x + m; green = c + m; blue = m; } else if (hslaL.h < 180) { red = m; green = c + m; blue = x + m; } else if (hslaL.h < 240) { red = m; green = x + m; blue = c + m; } else if (hslaL.h < 300) { red = x + m; green = m; blue = c + m; } else { red = c + m; green = m; blue = x + m; } return fixRGBA({r: Math.round(red * 255), g: Math.round(green * 255