From 21252c83c57451647e9b51e76695d127d75d4079 Mon Sep 17 00:00:00 2001 From: Triangle717 Date: Fri, 17 Oct 2014 12:52:49 -0400 Subject: [PATCH 1/3] Add upper/lowercase colors option in Inline Color Editor(adobe/brackets#9519) --- src/editor/Editor.js | 6 +- .../default/InlineColorEditor/ColorEditor.js | 133 ++++++++++-------- .../thirdparty/tinycolor-min.js | 25 +--- .../default/InlineColorEditor/unittests.js | 115 +++++++++++---- 4 files changed, 168 insertions(+), 111 deletions(-) diff --git a/src/editor/Editor.js b/src/editor/Editor.js index c426ed7b450..6f65f113803 100644 --- a/src/editor/Editor.js +++ b/src/editor/Editor.js @@ -91,8 +91,9 @@ define(function (require, exports, module) { SPACE_UNITS = "spaceUnits", STYLE_ACTIVE_LINE = "styleActiveLine", TAB_SIZE = "tabSize", - WORD_WRAP = "wordWrap", - USE_TAB_CHAR = "useTabChar"; + UPPERCASE_COLORS = "uppercaseColors", + USE_TAB_CHAR = "useTabChar", + WORD_WRAP = "wordWrap"; var cmOptions = {}; @@ -136,6 +137,7 @@ define(function (require, exports, module) { PreferencesManager.definePreference(TAB_SIZE, "number", DEFAULT_TAB_SIZE, { validator: _.partialRight(ValidationUtils.isIntegerInRange, MIN_TAB_SIZE, MAX_TAB_SIZE) }); + PreferencesManager.definePreference(UPPERCASE_COLORS, "boolean", false); PreferencesManager.definePreference(USE_TAB_CHAR, "boolean", false); PreferencesManager.definePreference(WORD_WRAP, "boolean", true); diff --git a/src/extensions/default/InlineColorEditor/ColorEditor.js b/src/extensions/default/InlineColorEditor/ColorEditor.js index ac0849a6082..3995a02465a 100644 --- a/src/extensions/default/InlineColorEditor/ColorEditor.js +++ b/src/extensions/default/InlineColorEditor/ColorEditor.js @@ -22,20 +22,23 @@ */ /*jslint vars: true, plusplus: true, nomen: true, regexp: true, maxerr: 50 */ -/*global define, brackets, $, window, tinycolor, Mustache */ +/*global define, brackets, $, window, Mustache */ define(function (require, exports, module) { "use strict"; - require("thirdparty/tinycolor-min"); - var KeyEvent = brackets.getModule("utils/KeyEvent"), - StringUtils = brackets.getModule("utils/StringUtils"), - Strings = brackets.getModule("strings"); + var KeyEvent = brackets.getModule("utils/KeyEvent"), + PreferencesManager = brackets.getModule("preferences/PreferencesManager"), + StringUtils = brackets.getModule("utils/StringUtils"), + Strings = brackets.getModule("strings"), + tinycolor = require("thirdparty/tinycolor-min"); /** Mustache template that forms the bare DOM structure of the UI */ var ColorEditorTemplate = require("text!ColorEditorTemplate.html"); - /** @const @type {number} */ + /** + * @const @type {number} + */ var STEP_MULTIPLIER = 5; /** @@ -64,6 +67,10 @@ define(function (require, exports, module) { this._color = tinycolor(color); this._originalColor = color; this._redoColor = null; + this._isUpperCase = PreferencesManager.get("uppercaseColors"); + PreferencesManager.on("change", "uppercaseColors", function () { + this._isUpperCase = PreferencesManager.get("uppercaseColors"); + }.bind(this)); this.$colorValue = this.$element.find(".color-value"); this.$buttonList = this.$element.find("ul.button-bar"); @@ -152,11 +159,11 @@ define(function (require, exports, module) { * incorrect to call this directly; use _commitColor() or setColorAsHsv() instead. */ ColorEditor.prototype._synchronize = function () { - var colorValue = this.getColor().toString(), + var colorValue = this.getColor().getOriginalInput(), colorObject = tinycolor(colorValue), - hueColor = "hsl(" + this._hsv.h + ", 100%, 50%)"; + hueColor = "hsl(" + this._hsv.h + ", 100%, 50%)"; - this._updateColorTypeRadioButtons(colorObject.format); + this._updateColorTypeRadioButtons(colorObject.getFormat()); this.$colorValue.val(colorValue); this.$currentColor.css("background-color", colorValue); this.$selection.css("background-color", hueColor); @@ -181,7 +188,10 @@ define(function (require, exports, module) { }); }; - /** Focus the main color square's thumb */ + /** + * Focus the main color square's thumb. + * @return {boolean} True if we focused the square, false otherwise. + */ ColorEditor.prototype.focus = function () { if (!this.$selectionBase.is(":focus")) { this.$selectionBase.focus(); @@ -190,7 +200,9 @@ define(function (require, exports, module) { return false; }; - /** @return {tinycolor|string} The currently selected color (TODO (#2201): type is unpredictable) */ + /** + * @return {tinycolor|string} The currently selected color (TODO (#2201): type is unpredictable). + */ ColorEditor.prototype.getColor = function () { return this._color; }; @@ -215,12 +227,12 @@ define(function (require, exports, module) { /** Add event listeners to the format button bar */ ColorEditor.prototype._bindColorFormatToRadioButton = function (buttonClass, propertyName, value) { var handler, - _this = this; + self = this; handler = function (event) { - var colorObject, newColor, newFormat; - newFormat = $(event.currentTarget).html().toLowerCase().replace("%", "p"); - newColor = _this.getColor(); - colorObject = tinycolor(newColor); + var newFormat = $(event.currentTarget).html().toLowerCase().replace("%", "p"), + newColor = self.getColor().toString(), + colorObject = tinycolor(newColor); + switch (newFormat) { case "hsla": newColor = colorObject.toHslString(); @@ -233,19 +245,23 @@ define(function (require, exports, module) { break; case "hex": newColor = colorObject.toHexString(); - _this._hsv.a = 1; + self._hsv.a = 1; break; } - _this._commitColor(newColor, false); + + // We need to run this again whenever RGB/HSL/Hex conversions + // are performed to preserve the case + newColor = self._isUpperCase ? newColor.toUpperCase() : newColor; + self._commitColor(newColor, false); }; this.$element.find("." + buttonClass).click(handler); }; /** Add event listener to the "original color value" swatch */ ColorEditor.prototype._bindOriginalColorButton = function () { - var _this = this; + var self = this; this.$originalColor.click(function (event) { - _this._commitColor(_this._originalColor, true); + self._commitColor(self._originalColor, true); }); }; @@ -256,7 +272,7 @@ define(function (require, exports, module) { * @return {string} an RGB color string in the normal format using non-percentage values */ ColorEditor.prototype._convertToNormalRGB = function (color) { - var matches = color.match(/^rgb.*?([0-9]+)\%.*?([0-9]+)\%.*?([0-9]+)\%/); + var matches = color.match(/^rgb.*?([0-9]+)\%.*?([0-9]+)\%.*?([0-9]+)\%/i); if (matches) { var i, percentStr, value; for (i = 0; i < 3; i++) { @@ -279,30 +295,30 @@ define(function (require, exports, module) { ColorEditor.prototype._normalizeColorString = function (color) { var normalizedColor = color; - // Convert 6-digit hex to 3-digit hex as tinycolor (#ffaacc -> #fac) + // Convert 6-digit hex to 3-digit hex as TinyColor (#ffaacc -> #fac) if (color.match(/^#[0-9a-fA-F]{6}/)) { return tinycolor(color).toString(); } - if (color.match(/^(rgb|hsl)/)) { + if (color.match(/^(rgb|hsl)/i)) { normalizedColor = normalizedColor.replace(/,\s*/g, ", "); normalizedColor = normalizedColor.replace(/\(\s+/, "("); normalizedColor = normalizedColor.replace(/\s+\)/, ")"); } - return normalizedColor.toLowerCase(); + return normalizedColor; }; /** Handle changes in text field */ ColorEditor.prototype._handleTextFieldInput = function (losingFocus) { - var newColor = $.trim(this.$colorValue.val()), + var newColor = $.trim(this.$colorValue.val()), newColorObj = tinycolor(newColor), - newColorOk = newColorObj.ok; + newColorOk = newColorObj.isValid(); - // tinycolor will auto correct an incomplete rgb or hsl value into a valid color value. + // TinyColor will auto correct an incomplete rgb or hsl value into a valid color value. // eg. rgb(0,0,0 -> rgb(0, 0, 0) - // We want to avoid having tinycolor do this, because we don't want to sync the color + // We want to avoid having TinyColor do this, because we don't want to sync the color // to the UI if it's incomplete. To accomplish this, we first normalize the original - // color string into the format tinycolor would generate, and then compare it to what - // tinycolor actually generates to see if it's different. If so, then we assume the color + // color string into the format TinyColor would generate, and then compare it to what + // TinyColor actually generates to see if it's different. If so, then we assume the color // was incomplete to begin with. if (newColorOk) { newColorOk = (newColorObj.toString() === this._normalizeColorString(newColor)); @@ -320,14 +336,14 @@ define(function (require, exports, module) { }; ColorEditor.prototype._bindInputHandlers = function () { - var _this = this; + var self = this; this.$colorValue.bind("input", function (event) { - _this._handleTextFieldInput(false); + self._handleTextFieldInput(false); }); this.$colorValue.bind("change", function (event) { - _this._handleTextFieldInput(true); + self._handleTextFieldInput(true); }); }; @@ -336,13 +352,13 @@ define(function (require, exports, module) { * @param {!Array.<{value:string, count:number}>} swatches */ ColorEditor.prototype._addSwatches = function (swatches) { - var _this = this; + var self = this; // Create swatches swatches.forEach(function (swatch) { var stringFormat = (swatch.count > 1) ? Strings.COLOR_EDITOR_USED_COLOR_TIP_PLURAL : Strings.COLOR_EDITOR_USED_COLOR_TIP_SINGULAR, usedColorTip = StringUtils.format(stringFormat, swatch.value, swatch.count); - _this.$swatches.append("
  • " + swatch.value + "
  • "); }); @@ -353,18 +369,18 @@ define(function (require, exports, module) { event.keyCode === KeyEvent.DOM_VK_ENTER || event.keyCode === KeyEvent.DOM_VK_SPACE) { // Enter/Space is same as clicking on swatch - _this._commitColor($(event.currentTarget).find(".value").html()); + self._commitColor($(event.currentTarget).find(".value").html()); } else if (event.keyCode === KeyEvent.DOM_VK_TAB) { // Tab on last swatch loops back to color square if (!event.shiftKey && $(this).next("li").length === 0) { - _this.$selectionBase.focus(); + self.$selectionBase.focus(); return false; } } }); this.$swatches.find("li").click(function (event) { - _this._commitColor($(event.currentTarget).find(".value").html()); + self._commitColor($(event.currentTarget).find(".value").html()); }); }; @@ -374,8 +390,8 @@ define(function (require, exports, module) { * @param {!{h:number=, s:number=, v:number=}} hsv Any missing values use the previous color's values. */ ColorEditor.prototype.setColorAsHsv = function (hsv) { - var colorVal, newColor, oldFormat; - oldFormat = tinycolor(this.getColor()).format; + var colorVal, newColor, + oldFormat = tinycolor(this.getColor()).getFormat(); // Set our state to the new color $.extend(this._hsv, hsv); @@ -396,6 +412,7 @@ define(function (require, exports, module) { colorVal = this._hsv.a < 1 ? newColor.toRgbString() : newColor.toHexString(); break; } + colorVal = this._isUpperCase ? colorVal.toUpperCase() : colorVal; this._commitColor(colorVal, false); }; @@ -406,17 +423,16 @@ define(function (require, exports, module) { * @param {boolean=} resetHsv Pass false ONLY if hsv set already been modified to match colorVal. Default: true. */ ColorEditor.prototype._commitColor = function (colorVal, resetHsv) { - var colorObj; if (resetHsv === undefined) { resetHsv = true; } this._callback(colorVal); - this._color = colorVal; + this._color = tinycolor(colorVal); + if (resetHsv) { - colorObj = tinycolor(colorVal); - this._hsv = colorObj.toHsv(); - this._color = colorObj; + this._hsv = this._color.toHsv(); } + this._redoColor = null; // if we had undone, this new value blows away the redo history this._synchronize(); }; @@ -439,12 +455,11 @@ define(function (require, exports, module) { /** Dragging color square's thumb */ ColorEditor.prototype._handleSelectionFieldDrag = function (event) { - var height, hsv, width, xOffset, yOffset; - height = this.$selection.height(); - width = this.$selection.width(); - xOffset = _getNewOffset(event.clientX, this.$selection.offset().left, width); - yOffset = _getNewOffset(event.clientY, this.$selection.offset().top, height); - hsv = {}; + var height = this.$selection.height(), + width = this.$selection.width(), + xOffset = _getNewOffset(event.clientX, this.$selection.offset().left, width), + yOffset = _getNewOffset(event.clientY, this.$selection.offset().top, height), + hsv = {}; hsv.s = xOffset / width; hsv.v = 1 - yOffset / height; this.setColorAsHsv(hsv, false); @@ -455,10 +470,9 @@ define(function (require, exports, module) { /** Dragging hue slider thumb */ ColorEditor.prototype._handleHueDrag = function (event) { - var height, hsv, offset; - height = this.$hueSlider.height(); - offset = _getNewOffset(event.clientY, this.$hueSlider.offset().top, height); - hsv = {}; + var height = this.$hueSlider.height(), + offset = _getNewOffset(event.clientY, this.$hueSlider.offset().top, height), + hsv = {}; hsv.h = (1 - offset / height) * 360; this.setColorAsHsv(hsv, false); if (!this.$hueSlider.find(".selector-base").is(":focus")) { @@ -468,11 +482,10 @@ define(function (require, exports, module) { /** Dragging opacity slider thumb */ ColorEditor.prototype._handleOpacityDrag = function (event) { - var height, hsv, offset; - height = this.$opacitySlider.height(); - offset = _getNewOffset(event.clientY, this.$opacitySlider.offset().top, height); - hsv = {}; - hsv.a = 1 - offset / height; + var height = this.$opacitySlider.height(), + offset = _getNewOffset(event.clientY, this.$opacitySlider.offset().top, height), + hsv = {}; + hsv.a = 1 - (offset / height); this.setColorAsHsv(hsv, false); if (!this.$opacitySlider.find(".selector-base").is(":focus")) { this.$opacitySlider.find(".selector-base").focus(); diff --git a/src/extensions/default/InlineColorEditor/thirdparty/tinycolor-min.js b/src/extensions/default/InlineColorEditor/thirdparty/tinycolor-min.js index 9f8df8dc290..89325118c40 100644 --- a/src/extensions/default/InlineColorEditor/thirdparty/tinycolor-min.js +++ b/src/extensions/default/InlineColorEditor/thirdparty/tinycolor-min.js @@ -1,21 +1,4 @@ -// TinyColor.js - - 2012 Brian Grinstead - v0.9.10 -(function(G){function e(b,d){var a,c,n,i,h,b=b?b:"";if("object"==typeof b&&b.hasOwnProperty("_tc_id"))return b;c=b;h=i=n=255;var C=1,o=a=!1;if("string"==typeof c)a:{c=c.replace(H,"").replace(I,"").toLowerCase();var u=!1;if(z[c])c=z[c],u=!0;else if("transparent"==c){c={r:0,g:0,b:0,a:0};break a}var f;c=(f=t.rgb.exec(c))?{r:f[1],g:f[2],b:f[3]}:(f=t.rgba.exec(c))?{r:f[1],g:f[2],b:f[3],a:f[4]}:(f=t.hsl.exec(c))?{h:f[1],s:f[2],l:f[3]}:(f=t.hsla.exec(c))?{h:f[1],s:f[2],l:f[3],a:f[4]}:(f=t.hsv.exec(c))?{h:f[1], -s:f[2],v:f[3]}:(f=t.hex6.exec(c))?{r:parseInt(f[1],16),g:parseInt(f[2],16),b:parseInt(f[3],16),format:u?"name":"hex"}:(f=t.hex3.exec(c))?{r:parseInt(f[1]+""+f[1],16),g:parseInt(f[2]+""+f[2],16),b:parseInt(f[3]+""+f[3],16),format:u?"name":"hex"}:!1}if("object"==typeof c&&(c.hasOwnProperty("r")&&c.hasOwnProperty("g")&&c.hasOwnProperty("b")?(n=255*j(c.r,255),i=255*j(c.g,255),h=255*j(c.b,255),a=!0,o="%"===String(c.r).substr(-1)?"prgb":"rgb"):c.hasOwnProperty("h")&&c.hasOwnProperty("s")&&c.hasOwnProperty("v")? -(c.s=w(c.s),c.v=w(c.v),a=c.h,i=c.s,h=c.v,a=6*j(a,360),i=j(i,100),h=j(h,100),n=v.floor(a),f=a-n,a=h*(1-i),o=h*(1-f*i),f=h*(1-(1-f)*i),u=n%6,n=255*[h,o,a,a,f,h][u],i=255*[f,h,h,o,a,a][u],h=255*[a,a,f,h,h,o][u],a=!0,o="hsv"):c.hasOwnProperty("h")&&(c.hasOwnProperty("s")&&c.hasOwnProperty("l"))&&(c.s=w(c.s),c.l=w(c.l),n=c.h,a=c.s,h=c.l,i=function(a,b,c){0>c&&(c+=1);1c?b:c<2/3?a+6*(b-a)*(2/3-c):a},n=j(n,360),a=j(a,100),h=j(h,100),0==a?a=h=o=h:(o=0.5>h?h*(1+a):h+ -a-h*a,f=2*h-o,a=i(f,o,n+1/3),h=i(f,o,n),o=i(f,o,n-1/3)),n=255*a,i=255*h,h=255*o,a=!0,o="hsl"),c.hasOwnProperty("a")))C=c.a;c=c.format||o;n=q(255,r(n,0));i=q(255,r(i,0));h=q(255,r(h,0));var k=n,l=i,m=h,p=parseFloat(C),s=g(100*p)/100;1>k&&(k=g(k));1>l&&(l=g(l));1>m&&(m=g(m));return{ok:a,format:c,_tc_id:J++,alpha:p,toHsv:function(){var a=D(k,l,m);return{h:360*a.h,s:a.s,v:a.v,a:p}},toHsvString:function(){var a=D(k,l,m),b=g(360*a.h),c=g(100*a.s),a=g(100*a.v);return 1==p?"hsv("+b+", "+c+"%, "+a+"%)":"hsva("+ -b+", "+c+"%, "+a+"%, "+s+")"},toHsl:function(){var a=E(k,l,m);return{h:360*a.h,s:a.s,l:a.l,a:p}},toHslString:function(){var a=E(k,l,m),b=g(360*a.h),c=g(100*a.s),a=g(100*a.l);return 1==p?"hsl("+b+", "+c+"%, "+a+"%)":"hsla("+b+", "+c+"%, "+a+"%, "+s+")"},toHex:function(){return y(k,l,m)},toHexString:function(){return"#"+y(k,l,m)},toRgb:function(){return{r:g(k),g:g(l),b:g(m),a:p}},toRgbString:function(){return 1==p?"rgb("+g(k)+", "+g(l)+", "+g(m)+")":"rgba("+g(k)+", "+g(l)+", "+g(m)+", "+s+")"},toPercentageRgb:function(){return{r:g(100* -j(k,255))+"%",g:g(100*j(l,255))+"%",b:g(100*j(m,255))+"%",a:p}},toPercentageRgbString:function(){return 1==p?"rgb("+g(100*j(k,255))+"%, "+g(100*j(l,255))+"%, "+g(100*j(m,255))+"%)":"rgba("+g(100*j(k,255))+"%, "+g(100*j(l,255))+"%, "+g(100*j(m,255))+"%, "+s+")"},toName:function(){return K[y(k,l,m)]||!1},toFilter:function(){var a=secondHex=y(k,l,m),b=secondAlphaHex=Math.round(255*parseFloat(p)).toString(16),c=d&&d.gradientType?"GradientType = 1, ":"";if(secondColor){var f=e(secondColor);secondHex=f.toHex(); -secondAlphaHex=Math.round(255*parseFloat(f.alpha)).toString(16)}return"progid:DXImageTransform.Microsoft.gradient("+c+"startColorstr=#"+x(b)+a+",endColorstr=#"+x(secondAlphaHex)+secondHex+")"},toString:function(a){var a=a||this.format,b=!1;"rgb"===a&&(b=this.toRgbString());"prgb"===a&&(b=this.toPercentageRgbString());"hex"===a&&(b=this.toHexString());"name"===a&&(b=this.toName());"hsl"===a&&(b=this.toHslString());"hsv"===a&&(b=this.toHsvString());return b||this.toHexString()}}}function E(b,d,a){var b= -j(b,255),d=j(d,255),a=j(a,255),c=r(b,d,a),e=q(b,d,a),i,h=(c+e)/2;if(c==e)i=e=0;else{var g=c-e,e=0.5v.abs(b-d)?1:b%d/parseFloat(d)}function x(b){return 1==b.length?"0"+b:""+b}function w(b){1>=b&&(b=100*b+"%");return b}var H=/^[\s,#]+/,I=/\s+$/,J=0,v=Math,g=v.round,q=v.min,r=v.max,A=v.random; -e.fromRatio=function(b){if("object"==typeof b){var d={},a;for(a in b)d[a]=w(b[a]);b=d}return e(b)};e.equals=function(b,d){return!b||!d?!1:e(b).toRgbString()==e(d).toRgbString()};e.random=function(){return e.fromRatio({r:A(),g:A(),b:A()})};e.desaturate=function(b,d){var a=e(b).toHsl();a.s-=(d||10)/100;a.s=q(1,r(0,a.s));return e(a)};e.saturate=function(b,d){var a=e(b).toHsl();a.s+=(d||10)/100;a.s=q(1,r(0,a.s));return e(a)};e.greyscale=function(b){return e.desaturate(b,100)};e.lighten=function(b,d){var a= -e(b).toHsl();a.l+=(d||10)/100;a.l=q(1,r(0,a.l));return e(a)};e.darken=function(b,d){var a=e(b).toHsl();a.l-=(d||10)/100;a.l=q(1,r(0,a.l));return e(a)};e.complement=function(b){b=e(b).toHsl();b.h=(b.h+180)%360;return e(b)};e.triad=function(b){var d=e(b).toHsl(),a=d.h;return[e(b),e({h:(a+120)%360,s:d.s,l:d.l}),e({h:(a+240)%360,s:d.s,l:d.l})]};e.tetrad=function(b){var d=e(b).toHsl(),a=d.h;return[e(b),e({h:(a+90)%360,s:d.s,l:d.l}),e({h:(a+180)%360,s:d.s,l:d.l}),e({h:(a+270)%360,s:d.s,l:d.l})]};e.splitcomplement= -function(b){var d=e(b).toHsl(),a=d.h;return[e(b),e({h:(a+72)%360,s:d.s,l:d.l}),e({h:(a+216)%360,s:d.s,l:d.l})]};e.analogous=function(b,d,a){var d=d||6,a=a||30,c=e(b).toHsl(),a=360/a,b=[e(b)];for(c.h=(c.h-(a*d>>1)+720)%360;--d;)c.h=(c.h+a)%360,b.push(e(c));return b};e.monochromatic=function(b,d){for(var d=d||6,a=e(b).toHsv(),c=a.h,g=a.s,a=a.v,i=[],h=1/d;d--;)i.push(e({h:c,s:g,v:a})),a=(a+h)%1;return i};e.readable=function(b,d){var a=e(b).toRgb(),c=e(d).toRgb();return 10404<(c.r-a.r)*(c.r-a.r)+(c.g- -a.g)*(c.g-a.g)+(c.b-a.b)*(c.b-a.b)};var z=e.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9", -darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff", -gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa", -lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6", -olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090", -slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},L=e,B=z,F={},s;for(s in B)B.hasOwnProperty(s)&&(F[B[s]]=s);var K=L.hexNames=F,t;t={rgb:RegExp("rgb[\\s|\\(]+((?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?))[,|\\s]+((?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?))[,|\\s]+((?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?))\\s*\\)?"), -rgba:RegExp("rgba[\\s|\\(]+((?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?))[,|\\s]+((?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?))[,|\\s]+((?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?))[,|\\s]+((?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?))\\s*\\)?"),hsl:RegExp("hsl[\\s|\\(]+((?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?))[,|\\s]+((?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?))[,|\\s]+((?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?))\\s*\\)?"),hsla:RegExp("hsla[\\s|\\(]+((?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?))[,|\\s]+((?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?))[,|\\s]+((?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?))[,|\\s]+((?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?))\\s*\\)?"), -hsv:RegExp("hsv[\\s|\\(]+((?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?))[,|\\s]+((?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?))[,|\\s]+((?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?))\\s*\\)?"),hex3:/^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/};"undefined"!==typeof module&&module.exports?module.exports=e:G.tinycolor=e})(this); +// TinyColor v1.1.1 +// https://github.com/bgrins/TinyColor +// 2014-12-20, Brian Grinstead, MIT License +!function(){function inputToRGB(color){var rgb={r:0,g:0,b:0},a=1,ok=!1,format=!1;return"string"==typeof color&&(color=stringInputToObject(color)),"object"==typeof color&&(color.hasOwnProperty("r")&&color.hasOwnProperty("g")&&color.hasOwnProperty("b")?(rgb=rgbToRgb(color.r,color.g,color.b),ok=!0,format="%"===String(color.r).substr(-1)?"prgb":"rgb"):color.hasOwnProperty("h")&&color.hasOwnProperty("s")&&color.hasOwnProperty("v")?(color.s=convertToPercentage(color.s),color.v=convertToPercentage(color.v),rgb=hsvToRgb(color.h,color.s,color.v),ok=!0,format="hsv"):color.hasOwnProperty("h")&&color.hasOwnProperty("s")&&color.hasOwnProperty("l")&&(color.s=convertToPercentage(color.s),color.l=convertToPercentage(color.l),rgb=hslToRgb(color.h,color.s,color.l),ok=!0,format="hsl"),color.hasOwnProperty("a")&&(a=color.a)),a=boundAlpha(a),{ok:ok,format:color.format||format,r:mathMin(255,mathMax(rgb.r,0)),g:mathMin(255,mathMax(rgb.g,0)),b:mathMin(255,mathMax(rgb.b,0)),a:a}}function rgbToRgb(r,g,b){return{r:255*bound01(r,255),g:255*bound01(g,255),b:255*bound01(b,255)}}function rgbToHsl(r,g,b){r=bound01(r,255),g=bound01(g,255),b=bound01(b,255);var h,s,max=mathMax(r,g,b),min=mathMin(r,g,b),l=(max+min)/2;if(max==min)h=s=0;else{var d=max-min;switch(s=l>.5?d/(2-max-min):d/(max+min),max){case r:h=(g-b)/d+(b>g?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4}h/=6}return{h:h,s:s,l:l}}function hslToRgb(h,s,l){function hue2rgb(p,q,t){return 0>t&&(t+=1),t>1&&(t-=1),1/6>t?p+6*(q-p)*t:.5>t?q:2/3>t?p+(q-p)*(2/3-t)*6:p}var r,g,b;if(h=bound01(h,360),s=bound01(s,100),l=bound01(l,100),0===s)r=g=b=l;else{var q=.5>l?l*(1+s):l+s-l*s,p=2*l-q;r=hue2rgb(p,q,h+1/3),g=hue2rgb(p,q,h),b=hue2rgb(p,q,h-1/3)}return{r:255*r,g:255*g,b:255*b}}function rgbToHsv(r,g,b){r=bound01(r,255),g=bound01(g,255),b=bound01(b,255);var h,s,max=mathMax(r,g,b),min=mathMin(r,g,b),v=max,d=max-min;if(s=0===max?0:d/max,max==min)h=0;else{switch(max){case r:h=(g-b)/d+(b>g?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4}h/=6}return{h:h,s:s,v:v}}function hsvToRgb(h,s,v){h=6*bound01(h,360),s=bound01(s,100),v=bound01(v,100);var i=math.floor(h),f=h-i,p=v*(1-s),q=v*(1-f*s),t=v*(1-(1-f)*s),mod=i%6,r=[v,q,p,p,t,v][mod],g=[t,v,v,q,p,p][mod],b=[p,p,t,v,v,q][mod];return{r:255*r,g:255*g,b:255*b}}function rgbToHex(r,g,b,allow3Char){var hex=[pad2(mathRound(r).toString(16)),pad2(mathRound(g).toString(16)),pad2(mathRound(b).toString(16))];return allow3Char&&hex[0].charAt(0)==hex[0].charAt(1)&&hex[1].charAt(0)==hex[1].charAt(1)&&hex[2].charAt(0)==hex[2].charAt(1)?hex[0].charAt(0)+hex[1].charAt(0)+hex[2].charAt(0):hex.join("")}function rgbaToHex(r,g,b,a){var hex=[pad2(convertDecimalToHex(a)),pad2(mathRound(r).toString(16)),pad2(mathRound(g).toString(16)),pad2(mathRound(b).toString(16))];return hex.join("")}function desaturate(color,amount){amount=0===amount?0:amount||10;var hsl=tinycolor(color).toHsl();return hsl.s-=amount/100,hsl.s=clamp01(hsl.s),tinycolor(hsl)}function saturate(color,amount){amount=0===amount?0:amount||10;var hsl=tinycolor(color).toHsl();return hsl.s+=amount/100,hsl.s=clamp01(hsl.s),tinycolor(hsl)}function greyscale(color){return tinycolor(color).desaturate(100)}function lighten(color,amount){amount=0===amount?0:amount||10;var hsl=tinycolor(color).toHsl();return hsl.l+=amount/100,hsl.l=clamp01(hsl.l),tinycolor(hsl)}function brighten(color,amount){amount=0===amount?0:amount||10;var rgb=tinycolor(color).toRgb();return rgb.r=mathMax(0,mathMin(255,rgb.r-mathRound(255*-(amount/100)))),rgb.g=mathMax(0,mathMin(255,rgb.g-mathRound(255*-(amount/100)))),rgb.b=mathMax(0,mathMin(255,rgb.b-mathRound(255*-(amount/100)))),tinycolor(rgb)}function darken(color,amount){amount=0===amount?0:amount||10;var hsl=tinycolor(color).toHsl();return hsl.l-=amount/100,hsl.l=clamp01(hsl.l),tinycolor(hsl)}function spin(color,amount){var hsl=tinycolor(color).toHsl(),hue=(mathRound(hsl.h)+amount)%360;return hsl.h=0>hue?360+hue:hue,tinycolor(hsl)}function complement(color){var hsl=tinycolor(color).toHsl();return hsl.h=(hsl.h+180)%360,tinycolor(hsl)}function triad(color){var hsl=tinycolor(color).toHsl(),h=hsl.h;return[tinycolor(color),tinycolor({h:(h+120)%360,s:hsl.s,l:hsl.l}),tinycolor({h:(h+240)%360,s:hsl.s,l:hsl.l})]}function tetrad(color){var hsl=tinycolor(color).toHsl(),h=hsl.h;return[tinycolor(color),tinycolor({h:(h+90)%360,s:hsl.s,l:hsl.l}),tinycolor({h:(h+180)%360,s:hsl.s,l:hsl.l}),tinycolor({h:(h+270)%360,s:hsl.s,l:hsl.l})]}function splitcomplement(color){var hsl=tinycolor(color).toHsl(),h=hsl.h;return[tinycolor(color),tinycolor({h:(h+72)%360,s:hsl.s,l:hsl.l}),tinycolor({h:(h+216)%360,s:hsl.s,l:hsl.l})]}function analogous(color,results,slices){results=results||6,slices=slices||30;var hsl=tinycolor(color).toHsl(),part=360/slices,ret=[tinycolor(color)];for(hsl.h=(hsl.h-(part*results>>1)+720)%360;--results;)hsl.h=(hsl.h+part)%360,ret.push(tinycolor(hsl));return ret}function monochromatic(color,results){results=results||6;for(var hsv=tinycolor(color).toHsv(),h=hsv.h,s=hsv.s,v=hsv.v,ret=[],modification=1/results;results--;)ret.push(tinycolor({h:h,s:s,v:v})),v=(v+modification)%1;return ret}function flip(o){var flipped={};for(var i in o)o.hasOwnProperty(i)&&(flipped[o[i]]=i);return flipped}function boundAlpha(a){return a=parseFloat(a),(isNaN(a)||0>a||a>1)&&(a=1),a}function bound01(n,max){isOnePointZero(n)&&(n="100%");var processPercent=isPercentage(n);return n=mathMin(max,mathMax(0,parseFloat(n))),processPercent&&(n=parseInt(n*max,10)/100),math.abs(n-max)<1e-6?1:n%max/parseFloat(max)}function clamp01(val){return mathMin(1,mathMax(0,val))}function parseIntFromHex(val){return parseInt(val,16)}function isOnePointZero(n){return"string"==typeof n&&-1!=n.indexOf(".")&&1===parseFloat(n)}function isPercentage(n){return"string"==typeof n&&-1!=n.indexOf("%")}function pad2(c){return 1==c.length?"0"+c:""+c}function convertToPercentage(n){return 1>=n&&(n=100*n+"%"),n}function convertDecimalToHex(d){return Math.round(255*parseFloat(d)).toString(16)}function convertHexToDecimal(h){return parseIntFromHex(h)/255}function stringInputToObject(color){color=color.replace(trimLeft,"").replace(trimRight,"").toLowerCase();var named=!1;if(names[color])color=names[color],named=!0;else if("transparent"==color)return{r:0,g:0,b:0,a:0,format:"name"};var match;return(match=matchers.rgb.exec(color))?{r:match[1],g:match[2],b:match[3]}:(match=matchers.rgba.exec(color))?{r:match[1],g:match[2],b:match[3],a:match[4]}:(match=matchers.hsl.exec(color))?{h:match[1],s:match[2],l:match[3]}:(match=matchers.hsla.exec(color))?{h:match[1],s:match[2],l:match[3],a:match[4]}:(match=matchers.hsv.exec(color))?{h:match[1],s:match[2],v:match[3]}:(match=matchers.hsva.exec(color))?{h:match[1],s:match[2],v:match[3],a:match[4]}:(match=matchers.hex8.exec(color))?{a:convertHexToDecimal(match[1]),r:parseIntFromHex(match[2]),g:parseIntFromHex(match[3]),b:parseIntFromHex(match[4]),format:named?"name":"hex8"}:(match=matchers.hex6.exec(color))?{r:parseIntFromHex(match[1]),g:parseIntFromHex(match[2]),b:parseIntFromHex(match[3]),format:named?"name":"hex"}:(match=matchers.hex3.exec(color))?{r:parseIntFromHex(match[1]+""+match[1]),g:parseIntFromHex(match[2]+""+match[2]),b:parseIntFromHex(match[3]+""+match[3]),format:named?"name":"hex"}:!1}var trimLeft=/^[\s,#]+/,trimRight=/\s+$/,tinyCounter=0,math=Math,mathRound=math.round,mathMin=math.min,mathMax=math.max,mathRandom=math.random,tinycolor=function tinycolor(color,opts){if(color=color?color:"",opts=opts||{},color instanceof tinycolor)return color;if(!(this instanceof tinycolor))return new tinycolor(color,opts);var rgb=inputToRGB(color);this._originalInput=color,this._r=rgb.r,this._g=rgb.g,this._b=rgb.b,this._a=rgb.a,this._roundA=mathRound(100*this._a)/100,this._format=opts.format||rgb.format,this._gradientType=opts.gradientType,this._r<1&&(this._r=mathRound(this._r)),this._g<1&&(this._g=mathRound(this._g)),this._b<1&&(this._b=mathRound(this._b)),this._ok=rgb.ok,this._tc_id=tinyCounter++};tinycolor.prototype={isDark:function(){return this.getBrightness()<128},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var rgb=this.toRgb();return(299*rgb.r+587*rgb.g+114*rgb.b)/1e3},setAlpha:function(value){return this._a=boundAlpha(value),this._roundA=mathRound(100*this._a)/100,this},toHsv:function(){var hsv=rgbToHsv(this._r,this._g,this._b);return{h:360*hsv.h,s:hsv.s,v:hsv.v,a:this._a}},toHsvString:function(){var hsv=rgbToHsv(this._r,this._g,this._b),h=mathRound(360*hsv.h),s=mathRound(100*hsv.s),v=mathRound(100*hsv.v);return 1==this._a?"hsv("+h+", "+s+"%, "+v+"%)":"hsva("+h+", "+s+"%, "+v+"%, "+this._roundA+")"},toHsl:function(){var hsl=rgbToHsl(this._r,this._g,this._b);return{h:360*hsl.h,s:hsl.s,l:hsl.l,a:this._a}},toHslString:function(){var hsl=rgbToHsl(this._r,this._g,this._b),h=mathRound(360*hsl.h),s=mathRound(100*hsl.s),l=mathRound(100*hsl.l);return 1==this._a?"hsl("+h+", "+s+"%, "+l+"%)":"hsla("+h+", "+s+"%, "+l+"%, "+this._roundA+")"},toHex:function(allow3Char){return rgbToHex(this._r,this._g,this._b,allow3Char)},toHexString:function(allow3Char){return"#"+this.toHex(allow3Char)},toHex8:function(){return rgbaToHex(this._r,this._g,this._b,this._a)},toHex8String:function(){return"#"+this.toHex8()},toRgb:function(){return{r:mathRound(this._r),g:mathRound(this._g),b:mathRound(this._b),a:this._a}},toRgbString:function(){return 1==this._a?"rgb("+mathRound(this._r)+", "+mathRound(this._g)+", "+mathRound(this._b)+")":"rgba("+mathRound(this._r)+", "+mathRound(this._g)+", "+mathRound(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:mathRound(100*bound01(this._r,255))+"%",g:mathRound(100*bound01(this._g,255))+"%",b:mathRound(100*bound01(this._b,255))+"%",a:this._a}},toPercentageRgbString:function(){return 1==this._a?"rgb("+mathRound(100*bound01(this._r,255))+"%, "+mathRound(100*bound01(this._g,255))+"%, "+mathRound(100*bound01(this._b,255))+"%)":"rgba("+mathRound(100*bound01(this._r,255))+"%, "+mathRound(100*bound01(this._g,255))+"%, "+mathRound(100*bound01(this._b,255))+"%, "+this._roundA+")"},toName:function(){return 0===this._a?"transparent":this._a<1?!1:hexNames[rgbToHex(this._r,this._g,this._b,!0)]||!1},toFilter:function(secondColor){var hex8String="#"+rgbaToHex(this._r,this._g,this._b,this._a),secondHex8String=hex8String,gradientType=this._gradientType?"GradientType = 1, ":"";if(secondColor){var s=tinycolor(secondColor);secondHex8String=s.toHex8String()}return"progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")"},toString:function(format){var formatSet=!!format;format=format||this._format;var formattedString=!1,hasAlpha=this._a<1&&this._a>=0,needsAlphaFormat=!formatSet&&hasAlpha&&("hex"===format||"hex6"===format||"hex3"===format||"name"===format);return needsAlphaFormat?"name"===format&&0===this._a?this.toName():this.toRgbString():("rgb"===format&&(formattedString=this.toRgbString()),"prgb"===format&&(formattedString=this.toPercentageRgbString()),("hex"===format||"hex6"===format)&&(formattedString=this.toHexString()),"hex3"===format&&(formattedString=this.toHexString(!0)),"hex8"===format&&(formattedString=this.toHex8String()),"name"===format&&(formattedString=this.toName()),"hsl"===format&&(formattedString=this.toHslString()),"hsv"===format&&(formattedString=this.toHsvString()),formattedString||this.toHexString())},_applyModification:function(fn,args){var color=fn.apply(null,[this].concat([].slice.call(args)));return this._r=color._r,this._g=color._g,this._b=color._b,this.setAlpha(color._a),this},lighten:function(){return this._applyModification(lighten,arguments)},brighten:function(){return this._applyModification(brighten,arguments)},darken:function(){return this._applyModification(darken,arguments)},desaturate:function(){return this._applyModification(desaturate,arguments)},saturate:function(){return this._applyModification(saturate,arguments)},greyscale:function(){return this._applyModification(greyscale,arguments)},spin:function(){return this._applyModification(spin,arguments)},_applyCombination:function(fn,args){return fn.apply(null,[this].concat([].slice.call(args)))},analogous:function(){return this._applyCombination(analogous,arguments)},complement:function(){return this._applyCombination(complement,arguments)},monochromatic:function(){return this._applyCombination(monochromatic,arguments)},splitcomplement:function(){return this._applyCombination(splitcomplement,arguments)},triad:function(){return this._applyCombination(triad,arguments)},tetrad:function(){return this._applyCombination(tetrad,arguments)}},tinycolor.fromRatio=function(color,opts){if("object"==typeof color){var newColor={};for(var i in color)color.hasOwnProperty(i)&&(newColor[i]="a"===i?color[i]:convertToPercentage(color[i]));color=newColor}return tinycolor(color,opts)},tinycolor.equals=function(color1,color2){return color1&&color2?tinycolor(color1).toRgbString()==tinycolor(color2).toRgbString():!1},tinycolor.random=function(){return tinycolor.fromRatio({r:mathRandom(),g:mathRandom(),b:mathRandom()})},tinycolor.mix=function(color1,color2,amount){amount=0===amount?0:amount||50;var w1,rgb1=tinycolor(color1).toRgb(),rgb2=tinycolor(color2).toRgb(),p=amount/100,w=2*p-1,a=rgb2.a-rgb1.a;w1=w*a==-1?w:(w+a)/(1+w*a),w1=(w1+1)/2;var w2=1-w1,rgba={r:rgb2.r*w1+rgb1.r*w2,g:rgb2.g*w1+rgb1.g*w2,b:rgb2.b*w1+rgb1.b*w2,a:rgb2.a*p+rgb1.a*(1-p)};return tinycolor(rgba)},tinycolor.readability=function(color1,color2){var c1=tinycolor(color1),c2=tinycolor(color2),rgb1=c1.toRgb(),rgb2=c2.toRgb(),brightnessA=c1.getBrightness(),brightnessB=c2.getBrightness(),colorDiff=Math.max(rgb1.r,rgb2.r)-Math.min(rgb1.r,rgb2.r)+Math.max(rgb1.g,rgb2.g)-Math.min(rgb1.g,rgb2.g)+Math.max(rgb1.b,rgb2.b)-Math.min(rgb1.b,rgb2.b);return{brightness:Math.abs(brightnessA-brightnessB),color:colorDiff}},tinycolor.isReadable=function(color1,color2){var readability=tinycolor.readability(color1,color2);return readability.brightness>125&&readability.color>500},tinycolor.mostReadable=function(baseColor,colorList){for(var bestColor=null,bestScore=0,bestIsReadable=!1,i=0;i125&&readability.color>500,score=3*(readability.brightness/125)+readability.color/500;(readable&&!bestIsReadable||readable&&bestIsReadable&&score>bestScore||!readable&&!bestIsReadable&&score>bestScore)&&(bestIsReadable=readable,bestScore=score,bestColor=tinycolor(colorList[i]))}return bestColor};var names=tinycolor.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"663399",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},hexNames=tinycolor.hexNames=flip(names),matchers=function(){var CSS_INTEGER="[-\\+]?\\d+%?",CSS_NUMBER="[-\\+]?\\d*\\.\\d+%?",CSS_UNIT="(?:"+CSS_NUMBER+")|(?:"+CSS_INTEGER+")",PERMISSIVE_MATCH3="[\\s|\\(]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")\\s*\\)?",PERMISSIVE_MATCH4="[\\s|\\(]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")[,|\\s]+("+CSS_UNIT+")\\s*\\)?";return{rgb:new RegExp("rgb"+PERMISSIVE_MATCH3),rgba:new RegExp("rgba"+PERMISSIVE_MATCH4),hsl:new RegExp("hsl"+PERMISSIVE_MATCH3),hsla:new RegExp("hsla"+PERMISSIVE_MATCH4),hsv:new RegExp("hsv"+PERMISSIVE_MATCH3),hsva:new RegExp("hsva"+PERMISSIVE_MATCH4),hex3:/^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex8:/^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/}}();"undefined"!=typeof module&&module.exports?module.exports=tinycolor:"function"==typeof define&&define.amd?define(function(){return tinycolor}):window.tinycolor=tinycolor}(); diff --git a/src/extensions/default/InlineColorEditor/unittests.js b/src/extensions/default/InlineColorEditor/unittests.js index 0f5733fb51b..890041f0e24 100644 --- a/src/extensions/default/InlineColorEditor/unittests.js +++ b/src/extensions/default/InlineColorEditor/unittests.js @@ -23,21 +23,21 @@ /*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */ -/*global define, describe, it, expect, beforeEach, afterEach, waits, runs, $, brackets, waitsForDone, spyOn, tinycolor */ +/*global define, describe, it, expect, beforeEach, afterEach, waits, runs, $, brackets, waitsForDone, spyOn */ define(function (require, exports, module) { "use strict"; // Modules from the SpecRunner window - var SpecRunnerUtils = brackets.getModule("spec/SpecRunnerUtils"), - KeyEvent = brackets.getModule("utils/KeyEvent"), - testContentCSS = require("text!unittest-files/unittests.css"), - testContentHTML = require("text!unittest-files/unittests.html"), - provider = require("main").inlineColorEditorProvider, - InlineColorEditor = require("InlineColorEditor").InlineColorEditor, - ColorEditor = require("ColorEditor").ColorEditor; - - require("thirdparty/tinycolor-min"); + var KeyEvent = brackets.getModule("utils/KeyEvent"), + PreferencesManager = brackets.getModule("preferences/PreferencesManager"), + SpecRunnerUtils = brackets.getModule("spec/SpecRunnerUtils"), + testContentCSS = require("text!unittest-files/unittests.css"), + testContentHTML = require("text!unittest-files/unittests.html"), + provider = require("main").inlineColorEditorProvider, + InlineColorEditor = require("InlineColorEditor").InlineColorEditor, + ColorEditor = require("ColorEditor").ColorEditor, + tinycolor = require("thirdparty/tinycolor-min"); describe("Inline Color Editor - unit", function () { @@ -454,24 +454,24 @@ define(function (require, exports, module) { }); - describe("conversions", function () { - - /** - * Test whether converting the given color to the given mode results in the expected color. - * @param {string} initialColor The color to convert. - * @param {string} mode The mode to convert to: most be "rgba", "hsla", or "hex". - * @param {string} result The expected result of the conversion. - */ - function testConvert(initialColor, mode, result) { - makeUI(initialColor); - var buttonMap = { - "rgba": "$rgbaButton", - "hsla": "$hslButton", - "hex": "$hexButton" - }; - colorEditor[buttonMap[mode]].trigger("click"); - expect(colorEditor.getColor().toString()).toBe(result); - } + /** + * Test whether converting the given color to the given mode results in the expected color. + * @param {string} initialColor The color to convert. + * @param {string} mode The mode to convert to: must be "rgba", "hsla", or "hex". + * @param {string} result The expected result of the conversion. + */ + function testConvert(initialColor, mode, result) { + makeUI(initialColor); + var buttonMap = { + "rgba": "$rgbaButton", + "hsla": "$hslButton", + "hex": "$hexButton" + }; + colorEditor[buttonMap[mode]].trigger("click"); + expect(colorEditor.getColor().getOriginalInput()).toBe(result); + } + + describe("conversions in lower case", function () { it("should convert a hex color to rgb when mode button clicked", function () { testConvert("#112233", "rgba", "rgb(17, 34, 51)"); @@ -503,6 +503,65 @@ define(function (require, exports, module) { it("should convert an hsla color to rgba when mode button clicked", function () { testConvert("hsla(152, 12%, 22%, 0.7)", "rgba", "rgba(49, 63, 57, 0.7)"); }); + it("should convert a mixed case hsla color to rgba when mode button clicked", function () { + testConvert("HsLa(152, 12%, 22%, 0.7)", "rgba", "rgba(49, 63, 57, 0.7)"); + }); + it("should convert a mixed case hex color to rgb when mode button clicked", function () { + testConvert("#fFfFfF", "rgba", "rgb(255, 255, 255)"); + }); + + }); + + describe("conversions in UPPER CASE", function () { + + beforeEach(function () { + // Enable uppercase colors + PreferencesManager.set("uppercaseColors", true); + }); + afterEach(function () { + // Re-disable uppercase colors + PreferencesManager.set("uppercaseColors", false); + }); + + it("should use uppercase colors", function () { + expect(PreferencesManager.get("uppercaseColors")).toBe(true); + }); + it("should convert a hex color to rgb in uppercase when mode button clicked", function () { + testConvert("#112233", "rgba", "RGB(17, 34, 51)"); + }); + it("should convert a hex color to hsl in uppercase when mode button clicked", function () { + testConvert("#112233", "hsla", "HSL(210, 50%, 13%)"); + }); + it("should convert an rgb color to hex in uppercase when mode button clicked", function () { + testConvert("RGB(15, 160, 21)", "hex", "#0FA015"); + }); + it("should convert an rgba color to hex (dropping alpha) in uppercase when mode button clicked", function () { + testConvert("RGBA(15, 160, 21, 0.5)", "hex", "#0FA015"); + }); + it("should convert an rgb color to hsl in uppercase when mode button clicked", function () { + testConvert("RGB(15, 160, 21)", "hsla", "HSL(122, 83%, 34%)"); + }); + it("should convert an rgba color to hsla in uppercase when mode button clicked", function () { + testConvert("RGBA(15, 160, 21, 0.3)", "hsla", "HSLA(122, 83%, 34%, 0.3)"); + }); + it("should convert an hsl color to hex in uppercase when mode button clicked", function () { + testConvert("HSL(152, 12%, 22%)", "hex", "#313F39"); + }); + it("should convert an hsla color to hex (dropping alpha) in uppercase when mode button clicked", function () { + testConvert("HSLA(152, 12%, 22%, 0.7)", "hex", "#313F39"); + }); + it("should convert an hsl color to rgb in uppercase when mode button clicked", function () { + testConvert("HSL(152, 12%, 22%)", "rgba", "RGB(49, 63, 57)"); + }); + it("should convert an hsla color to rgba in uppercase when mode button clicked", function () { + testConvert("HSLA(152, 12%, 22%, 0.7)", "rgba", "RGBA(49, 63, 57, 0.7)"); + }); + it("should convert a mixed case hsla color to rgba in uppercase when mode button clicked", function () { + testConvert("HsLa(152, 12%, 22%, 0.7)", "rgba", "RGBA(49, 63, 57, 0.7)"); + }); + it("should convert a mixed case hex color to rgb in uppercase when mode button clicked", function () { + testConvert("#fFfFfF", "rgba", "RGB(255, 255, 255)"); + }); }); From 90fd4dce73f7ac2a384811104f904793d48c6251 Mon Sep 17 00:00:00 2001 From: Triangle717 Date: Tue, 13 Jan 2015 20:54:01 -0500 Subject: [PATCH 2/3] Fix leaky listener --- src/extensions/default/InlineColorEditor/ColorEditor.js | 7 +++++++ .../default/InlineColorEditor/InlineColorEditor.js | 1 + 2 files changed, 8 insertions(+) diff --git a/src/extensions/default/InlineColorEditor/ColorEditor.js b/src/extensions/default/InlineColorEditor/ColorEditor.js index 3995a02465a..ade886dbd3e 100644 --- a/src/extensions/default/InlineColorEditor/ColorEditor.js +++ b/src/extensions/default/InlineColorEditor/ColorEditor.js @@ -199,6 +199,13 @@ define(function (require, exports, module) { } return false; }; + + /** + * Remove any preference listeners before destroying the editor. + */ + ColorEditor.prototype.destroy = function () { + PreferencesManager.off("change", "uppercaseColors"); + }; /** * @return {tinycolor|string} The currently selected color (TODO (#2201): type is unpredictable). diff --git a/src/extensions/default/InlineColorEditor/InlineColorEditor.js b/src/extensions/default/InlineColorEditor/InlineColorEditor.js index 06fc801a7d7..078950babaf 100644 --- a/src/extensions/default/InlineColorEditor/InlineColorEditor.js +++ b/src/extensions/default/InlineColorEditor/InlineColorEditor.js @@ -212,6 +212,7 @@ define(function (require, exports, module) { var doc = this.hostEditor.document; $(doc).off("change", this._handleHostDocumentChange); doc.releaseRef(); + this.colorEditor.destroy(); }; /** Comparator to sort by which colors are used the most */ From c9c7a2e8592576f51b9bdce73535d65a4b4ba8f3 Mon Sep 17 00:00:00 2001 From: Triangle717 Date: Fri, 16 Jan 2015 12:56:11 -0500 Subject: [PATCH 3/3] Use `getOriginalInput()` in tests --- src/extensions/default/InlineColorEditor/unittests.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/extensions/default/InlineColorEditor/unittests.js b/src/extensions/default/InlineColorEditor/unittests.js index 890041f0e24..8e5814ecf40 100644 --- a/src/extensions/default/InlineColorEditor/unittests.js +++ b/src/extensions/default/InlineColorEditor/unittests.js @@ -384,7 +384,7 @@ define(function (require, exports, module) { /** Returns the colorEditor's current value as a string in its current format */ function getColorString() { - return tinycolor(colorEditor.getColor()).toString(); + return tinycolor(colorEditor.getColor()).getOriginalInput(); } describe("simple load/commit", function () { @@ -395,7 +395,7 @@ define(function (require, exports, module) { runs(function () { makeUI(colorStr); - expect(colorEditor.getColor().toString()).toBe(colorStr); + expect(colorEditor.getColor().getOriginalInput()).toBe(colorStr); expect(colorEditor.$colorValue.val()).toBe(colorStr); expect(tinycolor.equals(colorEditor.$currentColor.css("background-color"), colorStr)).toBe(true); @@ -424,7 +424,7 @@ define(function (require, exports, module) { runs(function () { makeUI("#0a0a0a"); colorEditor.setColorFromString(colorStr); - expect(colorEditor.getColor().toString()).toBe(colorStr); + expect(colorEditor.getColor().getOriginalInput()).toBe(colorStr); expect(colorEditor.$colorValue.val()).toBe(colorStr); expect(tinycolor.equals(colorEditor.$currentColor.css("background-color"), colorStr)).toBe(true); checkNear(tinycolor(colorEditor.$selection.css("background-color")).toHsv().h, tinycolor(colorStr).toHsv().h);