tinycolor.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870
  1. // TinyColor v0.9.13
  2. // https://github.com/bgrins/TinyColor
  3. // 2012-11-28, Brian Grinstead, MIT License
  4. (function(root) {
  5. var trimLeft = /^[\s,#]+/,
  6. trimRight = /\s+$/,
  7. tinyCounter = 0,
  8. math = Math,
  9. mathRound = math.round,
  10. mathMin = math.min,
  11. mathMax = math.max,
  12. mathRandom = math.random;
  13. function tinycolor (color, opts) {
  14. color = (color) ? color : '';
  15. // If input is already a tinycolor, return itself
  16. if (typeof color == "object" && color.hasOwnProperty("_tc_id")) {
  17. return color;
  18. }
  19. var rgb = inputToRGB(color);
  20. var r = rgb.r,
  21. g = rgb.g,
  22. b = rgb.b,
  23. a = rgb.a,
  24. roundA = mathRound(100*a) / 100,
  25. format = rgb.format;
  26. // Don't let the range of [0,255] come back in [0,1].
  27. // Potentially lose a little bit of precision here, but will fix issues where
  28. // .5 gets interpreted as half of the total, instead of half of 1
  29. // If it was supposed to be 128, this was already taken care of by `inputToRgb`
  30. if (r < 1) { r = mathRound(r); }
  31. if (g < 1) { g = mathRound(g); }
  32. if (b < 1) { b = mathRound(b); }
  33. return {
  34. ok: rgb.ok,
  35. format: format,
  36. _tc_id: tinyCounter++,
  37. alpha: a,
  38. toHsv: function() {
  39. var hsv = rgbToHsv(r, g, b);
  40. return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: a };
  41. },
  42. toHsvString: function() {
  43. var hsv = rgbToHsv(r, g, b);
  44. var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);
  45. return (a == 1) ?
  46. "hsv(" + h + ", " + s + "%, " + v + "%)" :
  47. "hsva(" + h + ", " + s + "%, " + v + "%, "+ roundA + ")";
  48. },
  49. toHsl: function() {
  50. var hsl = rgbToHsl(r, g, b);
  51. return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: a };
  52. },
  53. toHslString: function() {
  54. var hsl = rgbToHsl(r, g, b);
  55. var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);
  56. return (a == 1) ?
  57. "hsl(" + h + ", " + s + "%, " + l + "%)" :
  58. "hsla(" + h + ", " + s + "%, " + l + "%, "+ roundA + ")";
  59. },
  60. toHex: function() {
  61. return rgbToHex(r, g, b);
  62. },
  63. toHexString: function() {
  64. return '#' + rgbToHex(r, g, b);
  65. },
  66. toRgb: function() {
  67. return { r: mathRound(r), g: mathRound(g), b: mathRound(b), a: a };
  68. },
  69. toRgbString: function() {
  70. return (a == 1) ?
  71. "rgb(" + mathRound(r) + ", " + mathRound(g) + ", " + mathRound(b) + ")" :
  72. "rgba(" + mathRound(r) + ", " + mathRound(g) + ", " + mathRound(b) + ", " + roundA + ")";
  73. },
  74. toPercentageRgb: function() {
  75. return { r: mathRound(bound01(r, 255) * 100) + "%", g: mathRound(bound01(g, 255) * 100) + "%", b: mathRound(bound01(b, 255) * 100) + "%", a: a };
  76. },
  77. toPercentageRgbString: function() {
  78. return (a == 1) ?
  79. "rgb(" + mathRound(bound01(r, 255) * 100) + "%, " + mathRound(bound01(g, 255) * 100) + "%, " + mathRound(bound01(b, 255) * 100) + "%)" :
  80. "rgba(" + mathRound(bound01(r, 255) * 100) + "%, " + mathRound(bound01(g, 255) * 100) + "%, " + mathRound(bound01(b, 255) * 100) + "%, " + roundA + ")";
  81. },
  82. toName: function() {
  83. return hexNames[rgbToHex(r, g, b)] || false;
  84. },
  85. toFilter: function() {
  86. var hex = rgbToHex(r, g, b);
  87. var secondHex = hex;
  88. var alphaHex = Math.round(parseFloat(a) * 255).toString(16);
  89. var secondAlphaHex = alphaHex;
  90. var gradientType = opts && opts.gradientType ? "GradientType = 1, " : "";
  91. if (secondColor) {
  92. var s = tinycolor(secondColor);
  93. secondHex = s.toHex();
  94. secondAlphaHex = Math.round(parseFloat(s.alpha) * 255).toString(16);
  95. }
  96. return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr=#" + pad2(alphaHex) + hex + ",endColorstr=#" + pad2(secondAlphaHex) + secondHex + ")";
  97. },
  98. toString: function(format) {
  99. format = format || this.format;
  100. var formattedString = false;
  101. if (format === "rgb") {
  102. formattedString = this.toRgbString();
  103. }
  104. if (format === "prgb") {
  105. formattedString = this.toPercentageRgbString();
  106. }
  107. if (format === "hex") {
  108. formattedString = this.toHexString();
  109. }
  110. if (format === "name") {
  111. formattedString = this.toName();
  112. }
  113. if (format === "hsl") {
  114. formattedString = this.toHslString();
  115. }
  116. if (format === "hsv") {
  117. formattedString = this.toHsvString();
  118. }
  119. return formattedString || this.toHexString();
  120. }
  121. };
  122. }
  123. // If input is an object, force 1 into "1.0" to handle ratios properly
  124. // String input requires "1.0" as input, so 1 will be treated as 1
  125. tinycolor.fromRatio = function(color) {
  126. if (typeof color == "object") {
  127. var newColor = {};
  128. for (var i in color) {
  129. newColor[i] = convertToPercentage(color[i]);
  130. }
  131. color = newColor;
  132. }
  133. return tinycolor(color);
  134. };
  135. // Given a string or object, convert that input to RGB
  136. // Possible string inputs:
  137. //
  138. // "red"
  139. // "#f00" or "f00"
  140. // "#ff0000" or "ff0000"
  141. // "rgb 255 0 0" or "rgb (255, 0, 0)"
  142. // "rgb 1.0 0 0" or "rgb (1, 0, 0)"
  143. // "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
  144. // "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
  145. // "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
  146. // "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
  147. // "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
  148. //
  149. function inputToRGB(color) {
  150. var rgb = { r: 255, g: 255, b: 255 };
  151. var a = 1;
  152. var ok = false;
  153. var format = false;
  154. if (typeof color == "string") {
  155. color = stringInputToObject(color);
  156. }
  157. if (typeof color == "object") {
  158. if (color.hasOwnProperty("r") && color.hasOwnProperty("g") && color.hasOwnProperty("b")) {
  159. rgb = rgbToRgb(color.r, color.g, color.b);
  160. ok = true;
  161. format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb";
  162. }
  163. else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) {
  164. color.s = convertToPercentage(color.s);
  165. color.v = convertToPercentage(color.v);
  166. rgb = hsvToRgb(color.h, color.s, color.v);
  167. ok = true;
  168. format = "hsv";
  169. }
  170. else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) {
  171. color.s = convertToPercentage(color.s);
  172. color.l = convertToPercentage(color.l);
  173. rgb = hslToRgb(color.h, color.s, color.l);
  174. ok = true;
  175. format = "hsl";
  176. }
  177. if (color.hasOwnProperty("a")) {
  178. a = color.a;
  179. }
  180. }
  181. a = parseFloat(a);
  182. // Handle invalid alpha characters by setting to 1
  183. if (isNaN(a) || a < 0 || a > 1) {
  184. a = 1;
  185. }
  186. return {
  187. ok: ok,
  188. format: color.format || format,
  189. r: mathMin(255, mathMax(rgb.r, 0)),
  190. g: mathMin(255, mathMax(rgb.g, 0)),
  191. b: mathMin(255, mathMax(rgb.b, 0)),
  192. a: a
  193. };
  194. }
  195. // Conversion Functions
  196. // --------------------
  197. // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
  198. // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
  199. // `rgbToRgb`
  200. // Handle bounds / percentage checking to conform to CSS color spec
  201. // <http://www.w3.org/TR/css3-color/>
  202. // *Assumes:* r, g, b in [0, 255] or [0, 1]
  203. // *Returns:* { r, g, b } in [0, 255]
  204. function rgbToRgb(r, g, b){
  205. return {
  206. r: bound01(r, 255) * 255,
  207. g: bound01(g, 255) * 255,
  208. b: bound01(b, 255) * 255
  209. };
  210. }
  211. // `rgbToHsl`
  212. // Converts an RGB color value to HSL.
  213. // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
  214. // *Returns:* { h, s, l } in [0,1]
  215. function rgbToHsl(r, g, b) {
  216. r = bound01(r, 255);
  217. g = bound01(g, 255);
  218. b = bound01(b, 255);
  219. var max = mathMax(r, g, b), min = mathMin(r, g, b);
  220. var h, s, l = (max + min) / 2;
  221. if(max == min) {
  222. h = s = 0; // achromatic
  223. }
  224. else {
  225. var d = max - min;
  226. s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
  227. switch(max) {
  228. case r: h = (g - b) / d + (g < b ? 6 : 0); break;
  229. case g: h = (b - r) / d + 2; break;
  230. case b: h = (r - g) / d + 4; break;
  231. }
  232. h /= 6;
  233. }
  234. return { h: h, s: s, l: l };
  235. }
  236. // `hslToRgb`
  237. // Converts an HSL color value to RGB.
  238. // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
  239. // *Returns:* { r, g, b } in the set [0, 255]
  240. function hslToRgb(h, s, l) {
  241. var r, g, b;
  242. h = bound01(h, 360);
  243. s = bound01(s, 100);
  244. l = bound01(l, 100);
  245. function hue2rgb(p, q, t) {
  246. if(t < 0) t += 1;
  247. if(t > 1) t -= 1;
  248. if(t < 1/6) return p + (q - p) * 6 * t;
  249. if(t < 1/2) return q;
  250. if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
  251. return p;
  252. }
  253. if(s === 0) {
  254. r = g = b = l; // achromatic
  255. }
  256. else {
  257. var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
  258. var p = 2 * l - q;
  259. r = hue2rgb(p, q, h + 1/3);
  260. g = hue2rgb(p, q, h);
  261. b = hue2rgb(p, q, h - 1/3);
  262. }
  263. return { r: r * 255, g: g * 255, b: b * 255 };
  264. }
  265. // `rgbToHsv`
  266. // Converts an RGB color value to HSV
  267. // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
  268. // *Returns:* { h, s, v } in [0,1]
  269. function rgbToHsv(r, g, b) {
  270. r = bound01(r, 255);
  271. g = bound01(g, 255);
  272. b = bound01(b, 255);
  273. var max = mathMax(r, g, b), min = mathMin(r, g, b);
  274. var h, s, v = max;
  275. var d = max - min;
  276. s = max === 0 ? 0 : d / max;
  277. if(max == min) {
  278. h = 0; // achromatic
  279. }
  280. else {
  281. switch(max) {
  282. case r: h = (g - b) / d + (g < b ? 6 : 0); break;
  283. case g: h = (b - r) / d + 2; break;
  284. case b: h = (r - g) / d + 4; break;
  285. }
  286. h /= 6;
  287. }
  288. return { h: h, s: s, v: v };
  289. }
  290. // `hsvToRgb`
  291. // Converts an HSV color value to RGB.
  292. // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
  293. // *Returns:* { r, g, b } in the set [0, 255]
  294. function hsvToRgb(h, s, v) {
  295. h = bound01(h, 360) * 6;
  296. s = bound01(s, 100);
  297. v = bound01(v, 100);
  298. var i = math.floor(h),
  299. f = h - i,
  300. p = v * (1 - s),
  301. q = v * (1 - f * s),
  302. t = v * (1 - (1 - f) * s),
  303. mod = i % 6,
  304. r = [v, q, p, p, t, v][mod],
  305. g = [t, v, v, q, p, p][mod],
  306. b = [p, p, t, v, v, q][mod];
  307. return { r: r * 255, g: g * 255, b: b * 255 };
  308. }
  309. // `rgbToHex`
  310. // Converts an RGB color to hex
  311. // Assumes r, g, and b are contained in the set [0, 255]
  312. // Returns a 3 or 6 character hex
  313. function rgbToHex(r, g, b) {
  314. var hex = [
  315. pad2(mathRound(r).toString(16)),
  316. pad2(mathRound(g).toString(16)),
  317. pad2(mathRound(b).toString(16))
  318. ];
  319. // Return a 3 character hex if possible
  320. if (hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {
  321. return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
  322. }
  323. return hex.join("");
  324. }
  325. // `equals`
  326. // Can be called with any tinycolor input
  327. tinycolor.equals = function (color1, color2) {
  328. if (!color1 || !color2) { return false; }
  329. return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
  330. };
  331. tinycolor.random = function() {
  332. return tinycolor.fromRatio({
  333. r: mathRandom(),
  334. g: mathRandom(),
  335. b: mathRandom()
  336. });
  337. };
  338. // Modification Functions
  339. // ----------------------
  340. // Thanks to less.js for some of the basics here
  341. // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>
  342. tinycolor.desaturate = function (color, amount) {
  343. var hsl = tinycolor(color).toHsl();
  344. hsl.s -= ((amount || 10) / 100);
  345. hsl.s = clamp01(hsl.s);
  346. return tinycolor(hsl);
  347. };
  348. tinycolor.saturate = function (color, amount) {
  349. var hsl = tinycolor(color).toHsl();
  350. hsl.s += ((amount || 10) / 100);
  351. hsl.s = clamp01(hsl.s);
  352. return tinycolor(hsl);
  353. };
  354. tinycolor.greyscale = function(color) {
  355. return tinycolor.desaturate(color, 100);
  356. };
  357. tinycolor.lighten = function(color, amount) {
  358. var hsl = tinycolor(color).toHsl();
  359. hsl.l += ((amount || 10) / 100);
  360. hsl.l = clamp01(hsl.l);
  361. return tinycolor(hsl);
  362. };
  363. tinycolor.darken = function (color, amount) {
  364. var hsl = tinycolor(color).toHsl();
  365. hsl.l -= ((amount || 10) / 100);
  366. hsl.l = clamp01(hsl.l);
  367. return tinycolor(hsl);
  368. };
  369. tinycolor.complement = function(color) {
  370. var hsl = tinycolor(color).toHsl();
  371. hsl.h = (hsl.h + 180) % 360;
  372. return tinycolor(hsl);
  373. };
  374. // Combination Functions
  375. // ---------------------
  376. // Thanks to jQuery xColor for some of the ideas behind these
  377. // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>
  378. tinycolor.triad = function(color) {
  379. var hsl = tinycolor(color).toHsl();
  380. var h = hsl.h;
  381. return [
  382. tinycolor(color),
  383. tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
  384. tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })
  385. ];
  386. };
  387. tinycolor.tetrad = function(color) {
  388. var hsl = tinycolor(color).toHsl();
  389. var h = hsl.h;
  390. return [
  391. tinycolor(color),
  392. tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
  393. tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
  394. tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })
  395. ];
  396. };
  397. tinycolor.splitcomplement = function(color) {
  398. var hsl = tinycolor(color).toHsl();
  399. var h = hsl.h;
  400. return [
  401. tinycolor(color),
  402. tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),
  403. tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})
  404. ];
  405. };
  406. tinycolor.analogous = function(color, results, slices) {
  407. results = results || 6;
  408. slices = slices || 30;
  409. var hsl = tinycolor(color).toHsl();
  410. var part = 360 / slices;
  411. var ret = [tinycolor(color)];
  412. for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {
  413. hsl.h = (hsl.h + part) % 360;
  414. ret.push(tinycolor(hsl));
  415. }
  416. return ret;
  417. };
  418. tinycolor.monochromatic = function(color, results) {
  419. results = results || 6;
  420. var hsv = tinycolor(color).toHsv();
  421. var h = hsv.h, s = hsv.s, v = hsv.v;
  422. var ret = [];
  423. var modification = 1 / results;
  424. while (results--) {
  425. ret.push(tinycolor({ h: h, s: s, v: v}));
  426. v = (v + modification) % 1;
  427. }
  428. return ret;
  429. };
  430. // Readability based on W3C recommendations: http://www.w3.org/TR/AERT#color-contrast
  431. // Returns object with two properties:
  432. // .brightness: the difference in brightness between the two colors
  433. // .color: the difference in color/hue between the two colors
  434. // An "acceptable" color is considered to have a brightness difference of 125 and a
  435. // color difference of 500
  436. tinycolor.readability = function(color1, color2) {
  437. var a = tinycolor(color1).toRgb(), b = tinycolor(color2).toRgb();
  438. var brightnessA = (a.r * 299 + a.g * 587 + a.b * 114) / 1000;
  439. var brightnessB = (b.r * 299 + b.g * 587 + b.b * 114) / 1000;
  440. var colorDiff = (
  441. Math.max(a.r, b.r) - Math.min(a.r, b.r) +
  442. Math.max(a.g, b.g) - Math.min(a.g, b.g) +
  443. Math.max(a.b, b.b) - Math.min(a.b, b.b));
  444. return {
  445. brightness: Math.abs(brightnessA - brightnessB),
  446. color: colorDiff
  447. };
  448. };
  449. // True if using color1 over color2 (or vice versa) is "readable"
  450. // Based on: http://www.w3.org/TR/AERT#color-contrast
  451. // Example:
  452. // tinycolor.readable("#000", "#111") => false
  453. tinycolor.readable = function(color1, color2) {
  454. var readability = tinycolor.readability(color1, color2);
  455. return readability.brightness > 125 && readability.color > 500;
  456. };
  457. // Given a base color and a list of possible foreground or background
  458. // colors for that base, returns the most readable color.
  459. // Example:
  460. // tinycolor.mostReadable("#123", ["#fff", "#000"]) => "#000"
  461. tinycolor.mostReadable = function(baseColor, colorList) {
  462. var bestColor;
  463. var bestScore = 0;
  464. var bestIsReadable = false;
  465. for (var i=0; i < colorList.length; i++) {
  466. var readability = tinycolor.readability(baseColor, colorList[i]);
  467. var readable = readability.brightness > 125 && readability.color > 500;
  468. // We normalize both around the "acceptable" breaking point,
  469. // but rank brightness constrast higher than hue. Why? I'm
  470. // not sure, seems reasonable.
  471. var score = 3 * (readability.brightness / 125) + (readability.color / 500);
  472. if ((readable && ! bestIsReadable) ||
  473. (readable && bestIsReadable && score > bestScore) ||
  474. ((! readable) && (! bestIsReadable) && score > bestScore)) {
  475. bestIsReadable = readable;
  476. bestScore = score;
  477. bestColor = colorList[i];
  478. }
  479. }
  480. return bestColor;
  481. };
  482. // Big List of Colors
  483. // ---------
  484. // <http://www.w3.org/TR/css3-color/#svg-color>
  485. var names = tinycolor.names = {
  486. aliceblue: "f0f8ff",
  487. antiquewhite: "faebd7",
  488. aqua: "0ff",
  489. aquamarine: "7fffd4",
  490. azure: "f0ffff",
  491. beige: "f5f5dc",
  492. bisque: "ffe4c4",
  493. black: "000",
  494. blanchedalmond: "ffebcd",
  495. blue: "00f",
  496. blueviolet: "8a2be2",
  497. brown: "a52a2a",
  498. burlywood: "deb887",
  499. burntsienna: "ea7e5d",
  500. cadetblue: "5f9ea0",
  501. chartreuse: "7fff00",
  502. chocolate: "d2691e",
  503. coral: "ff7f50",
  504. cornflowerblue: "6495ed",
  505. cornsilk: "fff8dc",
  506. crimson: "dc143c",
  507. cyan: "0ff",
  508. darkblue: "00008b",
  509. darkcyan: "008b8b",
  510. darkgoldenrod: "b8860b",
  511. darkgray: "a9a9a9",
  512. darkgreen: "006400",
  513. darkgrey: "a9a9a9",
  514. darkkhaki: "bdb76b",
  515. darkmagenta: "8b008b",
  516. darkolivegreen: "556b2f",
  517. darkorange: "ff8c00",
  518. darkorchid: "9932cc",
  519. darkred: "8b0000",
  520. darksalmon: "e9967a",
  521. darkseagreen: "8fbc8f",
  522. darkslateblue: "483d8b",
  523. darkslategray: "2f4f4f",
  524. darkslategrey: "2f4f4f",
  525. darkturquoise: "00ced1",
  526. darkviolet: "9400d3",
  527. deeppink: "ff1493",
  528. deepskyblue: "00bfff",
  529. dimgray: "696969",
  530. dimgrey: "696969",
  531. dodgerblue: "1e90ff",
  532. firebrick: "b22222",
  533. floralwhite: "fffaf0",
  534. forestgreen: "228b22",
  535. fuchsia: "f0f",
  536. gainsboro: "dcdcdc",
  537. ghostwhite: "f8f8ff",
  538. gold: "ffd700",
  539. goldenrod: "daa520",
  540. gray: "808080",
  541. green: "008000",
  542. greenyellow: "adff2f",
  543. grey: "808080",
  544. honeydew: "f0fff0",
  545. hotpink: "ff69b4",
  546. indianred: "cd5c5c",
  547. indigo: "4b0082",
  548. ivory: "fffff0",
  549. khaki: "f0e68c",
  550. lavender: "e6e6fa",
  551. lavenderblush: "fff0f5",
  552. lawngreen: "7cfc00",
  553. lemonchiffon: "fffacd",
  554. lightblue: "add8e6",
  555. lightcoral: "f08080",
  556. lightcyan: "e0ffff",
  557. lightgoldenrodyellow: "fafad2",
  558. lightgray: "d3d3d3",
  559. lightgreen: "90ee90",
  560. lightgrey: "d3d3d3",
  561. lightpink: "ffb6c1",
  562. lightsalmon: "ffa07a",
  563. lightseagreen: "20b2aa",
  564. lightskyblue: "87cefa",
  565. lightslategray: "789",
  566. lightslategrey: "789",
  567. lightsteelblue: "b0c4de",
  568. lightyellow: "ffffe0",
  569. lime: "0f0",
  570. limegreen: "32cd32",
  571. linen: "faf0e6",
  572. magenta: "f0f",
  573. maroon: "800000",
  574. mediumaquamarine: "66cdaa",
  575. mediumblue: "0000cd",
  576. mediumorchid: "ba55d3",
  577. mediumpurple: "9370db",
  578. mediumseagreen: "3cb371",
  579. mediumslateblue: "7b68ee",
  580. mediumspringgreen: "00fa9a",
  581. mediumturquoise: "48d1cc",
  582. mediumvioletred: "c71585",
  583. midnightblue: "191970",
  584. mintcream: "f5fffa",
  585. mistyrose: "ffe4e1",
  586. moccasin: "ffe4b5",
  587. navajowhite: "ffdead",
  588. navy: "000080",
  589. oldlace: "fdf5e6",
  590. olive: "808000",
  591. olivedrab: "6b8e23",
  592. orange: "ffa500",
  593. orangered: "ff4500",
  594. orchid: "da70d6",
  595. palegoldenrod: "eee8aa",
  596. palegreen: "98fb98",
  597. paleturquoise: "afeeee",
  598. palevioletred: "db7093",
  599. papayawhip: "ffefd5",
  600. peachpuff: "ffdab9",
  601. peru: "cd853f",
  602. pink: "ffc0cb",
  603. plum: "dda0dd",
  604. powderblue: "b0e0e6",
  605. purple: "800080",
  606. red: "f00",
  607. rosybrown: "bc8f8f",
  608. royalblue: "4169e1",
  609. saddlebrown: "8b4513",
  610. salmon: "fa8072",
  611. sandybrown: "f4a460",
  612. seagreen: "2e8b57",
  613. seashell: "fff5ee",
  614. sienna: "a0522d",
  615. silver: "c0c0c0",
  616. skyblue: "87ceeb",
  617. slateblue: "6a5acd",
  618. slategray: "708090",
  619. slategrey: "708090",
  620. snow: "fffafa",
  621. springgreen: "00ff7f",
  622. steelblue: "4682b4",
  623. tan: "d2b48c",
  624. teal: "008080",
  625. thistle: "d8bfd8",
  626. tomato: "ff6347",
  627. turquoise: "40e0d0",
  628. violet: "ee82ee",
  629. wheat: "f5deb3",
  630. white: "fff",
  631. whitesmoke: "f5f5f5",
  632. yellow: "ff0",
  633. yellowgreen: "9acd32"
  634. };
  635. // Make it easy to access colors via `hexNames[hex]`
  636. var hexNames = tinycolor.hexNames = flip(names);
  637. // Utilities
  638. // ---------
  639. // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
  640. function flip(o) {
  641. var flipped = { };
  642. for (var i in o) {
  643. if (o.hasOwnProperty(i)) {
  644. flipped[o[i]] = i;
  645. }
  646. }
  647. return flipped;
  648. }
  649. // Take input from [0, n] and return it as [0, 1]
  650. function bound01(n, max) {
  651. if (isOnePointZero(n)) { n = "100%"; }
  652. var processPercent = isPercentage(n);
  653. n = mathMin(max, mathMax(0, parseFloat(n)));
  654. // Automatically convert percentage into number
  655. if (processPercent) {
  656. n = parseInt(n * max, 10) / 100;
  657. }
  658. // Handle floating point rounding errors
  659. if ((math.abs(n - max) < 0.000001)) {
  660. return 1;
  661. }
  662. // Convert into [0, 1] range if it isn't already
  663. return (n % max) / parseFloat(max);
  664. }
  665. // Force a number between 0 and 1
  666. function clamp01(val) {
  667. return mathMin(1, mathMax(0, val));
  668. }
  669. // Parse an integer into hex
  670. function parseHex(val) {
  671. return parseInt(val, 16);
  672. }
  673. // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
  674. // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
  675. function isOnePointZero(n) {
  676. return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1;
  677. }
  678. // Check to see if string passed in is a percentage
  679. function isPercentage(n) {
  680. return typeof n === "string" && n.indexOf('%') != -1;
  681. }
  682. // Force a hex value to have 2 characters
  683. function pad2(c) {
  684. return c.length == 1 ? '0' + c : '' + c;
  685. }
  686. // Replace a decimal with it's percentage value
  687. function convertToPercentage(n) {
  688. if (n <= 1) {
  689. n = (n * 100) + "%";
  690. }
  691. return n;
  692. }
  693. var matchers = (function() {
  694. // <http://www.w3.org/TR/css3-values/#integers>
  695. var CSS_INTEGER = "[-\\+]?\\d+%?";
  696. // <http://www.w3.org/TR/css3-values/#number-value>
  697. var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?";
  698. // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome.
  699. var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")";
  700. // Actual matching.
  701. // Parentheses and commas are optional, but not required.
  702. // Whitespace can take the place of commas or opening paren
  703. var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
  704. var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
  705. return {
  706. rgb: new RegExp("rgb" + PERMISSIVE_MATCH3),
  707. rgba: new RegExp("rgba" + PERMISSIVE_MATCH4),
  708. hsl: new RegExp("hsl" + PERMISSIVE_MATCH3),
  709. hsla: new RegExp("hsla" + PERMISSIVE_MATCH4),
  710. hsv: new RegExp("hsv" + PERMISSIVE_MATCH3),
  711. hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
  712. hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/
  713. };
  714. })();
  715. // `stringInputToObject`
  716. // Permissive string parsing. Take in a number of formats, and output an object
  717. // based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
  718. function stringInputToObject(color) {
  719. color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase();
  720. var named = false;
  721. if (names[color]) {
  722. color = names[color];
  723. named = true;
  724. }
  725. else if (color == 'transparent') {
  726. return { r: 0, g: 0, b: 0, a: 0 };
  727. }
  728. // Try to match string input using regular expressions.
  729. // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
  730. // Just return an object and let the conversion functions handle that.
  731. // This way the result will be the same whether the tinycolor is initialized with string or object.
  732. var match;
  733. if ((match = matchers.rgb.exec(color))) {
  734. return { r: match[1], g: match[2], b: match[3] };
  735. }
  736. if ((match = matchers.rgba.exec(color))) {
  737. return { r: match[1], g: match[2], b: match[3], a: match[4] };
  738. }
  739. if ((match = matchers.hsl.exec(color))) {
  740. return { h: match[1], s: match[2], l: match[3] };
  741. }
  742. if ((match = matchers.hsla.exec(color))) {
  743. return { h: match[1], s: match[2], l: match[3], a: match[4] };
  744. }
  745. if ((match = matchers.hsv.exec(color))) {
  746. return { h: match[1], s: match[2], v: match[3] };
  747. }
  748. if ((match = matchers.hex6.exec(color))) {
  749. return {
  750. r: parseHex(match[1]),
  751. g: parseHex(match[2]),
  752. b: parseHex(match[3]),
  753. format: named ? "name" : "hex"
  754. };
  755. }
  756. if ((match = matchers.hex3.exec(color))) {
  757. return {
  758. r: parseHex(match[1] + '' + match[1]),
  759. g: parseHex(match[2] + '' + match[2]),
  760. b: parseHex(match[3] + '' + match[3]),
  761. format: named ? "name" : "hex"
  762. };
  763. }
  764. return false;
  765. }
  766. // Node: Export function
  767. if (typeof module !== "undefined" && module.exports) {
  768. module.exports = tinycolor;
  769. }
  770. // AMD/requirejs: Define the module
  771. else if (typeof define !== "undefined") {
  772. define(function () {return tinycolor;});
  773. }
  774. // Browser: Expose to window
  775. else {
  776. root.tinycolor = tinycolor;
  777. }
  778. })(this);