vendor: 30,735 bytes, lines 1-1041
1// TinyColor v1.1.0 2// https://github.com/bgrins/TinyColor 3// Brian Grinstead, MIT License 4 5(function() { 6 7var trimLeft = /^[\s,#]+/, 8 trimRight = /\s+$/, 9 tinyCounter = 0, 10 math = Math, 11 mathRound = math.round, 12 mathMin = math.min, 13 mathMax = math.max, 14 mathRandom = math.random; 15 16var tinycolor = function tinycolor (color, opts) { 17 18 color = (color) ? color : ''; 19 opts = opts || { }; 20 21 // If input is already a tinycolor, return itself 22 if (color instanceof tinycolor) { 23 return color; 24 } 25 // If we are called as a function, call using new instead 26 if (!(this instanceof tinycolor)) { 27 return new tinycolor(color, opts); 28 } 29 30 var rgb = inputToRGB(color); 31 this._originalInput = color, 32 this._r = rgb.r, 33 this._g = rgb.g, 34 this._b = rgb.b, 35 this._a = rgb.a, 36 this._roundA = mathRound(100*this._a) / 100, 37 this._format = opts.format || rgb.format; 38 this._gradientType = opts.gradientType; 39 40 // Don't let the range of [0,255] come back in [0,1]. 41 // Potentially lose a little bit of precision here, but will fix issues where 42 // .5 gets interpreted as half of the total, instead of half of 1 43 // If it was supposed to be 128, this was already taken care of by `inputToRgb` 44 if (this._r < 1) { this._r = mathRound(this._r); } 45 if (this._g < 1) { this._g = mathRound(this._g); } 46 if (this._b < 1) { this._b = mathRound(this._b); } 47 48 this._ok = rgb.ok; 49 this._tc_id = tinyCounter++; 50}; 51 52tinycolor.prototype = { 53 isDark: function() { 54 return this.getBrightness() < 128; 55 }, 56 isLight: function() { 57 return !this.isDark(); 58 }, 59 isValid: function() { 60 return this._ok; 61 }, 62 getOriginalInput: function() { 63 return this._originalInput; 64 }, 65 getFormat: function() { 66 return this._format; 67 }, 68 getAlpha: function() { 69 return this._a; 70 }, 71 getBrightness: function() { 72 var rgb = this.toRgb(); 73 return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000; 74 }, 75 setAlpha: function(value) { 76 this._a = boundAlpha(value); 77 this._roundA = mathRound(100*this._a) / 100; 78 return this; 79 }, 80 toHsv: function() { 81 var hsv = rgbToHsv(this._r, this._g, this._b); 82 return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a }; 83 }, 84 toHsvString: function() { 85 var hsv = rgbToHsv(this._r, this._g, this._b); 86 var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100); 87 return (this._a == 1) ? 88 "hsv(" + h + ", " + s + "%, " + v + "%)" : 89 "hsva(" + h + ", " + s + "%, " + v + "%, "+ this._roundA + ")"; 90 }, 91 toHsl: function() { 92 var hsl = rgbToHsl(this._r, this._g, this._b); 93 return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a }; 94 }, 95 toHslString: function() { 96 var hsl = rgbToHsl(this._r, this._g, this._b); 97 var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100); 98 return (this._a == 1) ? 99 "hsl(" + h + ", " + s + "%, " + l + "%)" : 100 "hsla(" + h + ", " + s + "%, " + l + "%, "+ this._roundA + ")"; 101 }, 102 toHex: function(allow3Char) { 103 return rgbToHex(this._r, this._g, this._b, allow3Char); 104 }, 105 toHexString: function(allow3Char) { 106 return '#' + this.toHex(allow3Char); 107 }, 108 toHex8: function() { 109 return rgbaToHex(this._r, this._g, this._b, this._a); 110 }, 111 toHex8String: function() { 112 return '#' + this.toHex8(); 113 }, 114 toRgb: function() { 115 return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a }; 116 }, 117 toRgbString: function() { 118 return (this._a == 1) ? 119 "rgb(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ")" : 120 "rgba(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ", " + this._roundA + ")"; 121 }, 122 toPercentageRgb: function() { 123 return { r: mathRound(bound01(this._r, 255) * 100) + "%", g: mathRound(bound01(this._g, 255) * 100) + "%", b: mathRound(bound01(this._b, 255) * 100) + "%", a: this._a }; 124 }, 125 toPercentageRgbString: function() { 126 return (this._a == 1) ? 127 "rgb(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%)" : 128 "rgba(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")"; 129 }, 130 toName: function() { 131 if (this._a === 0) { 132 return "transparent"; 133 } 134 135 if (this._a < 1) { 136 return false; 137 } 138 139 return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false; 140 }, 141 toFilter: function(secondColor) { 142 var hex8String = '#' + rgbaToHex(this._r, this._g, this._b, this._a); 143 var secondHex8String = hex8String; 144 var gradientType = this._gradientType ? "GradientType = 1, " : ""; 145 146 if (secondColor) { 147 var s = tinycolor(secondColor); 148 secondHex8String = s.toHex8String(); 149 } 150 151 return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")"; 152 }, 153 toString: function(format) { 154 var formatSet = !!format; 155 format = format || this._format; 156 157 var formattedString = false; 158 var hasAlpha = this._a < 1 && this._a >= 0; 159 var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "name"); 160 161 if (needsAlphaFormat) { 162 // Special case for "transparent", all other non-alpha formats 163 // will return rgba when there is transparency. 164 if (format === "name" && this._a === 0) { 165 return this.toName(); 166 } 167 return this.toRgbString(); 168 } 169 if (format === "rgb") { 170 formattedString = this.toRgbString(); 171 } 172 if (format === "prgb") { 173 formattedString = this.toPercentageRgbString(); 174 } 175 if (format === "hex" || format === "hex6") { 176 formattedString = this.toHexString(); 177 } 178 if (format === "hex3") { 179 formattedString = this.toHexString(true); 180 } 181 if (format === "hex8") { 182 formattedString = this.toHex8String(); 183 } 184 if (format === "name") { 185 formattedString = this.toName(); 186 } 187 if (format === "hsl") { 188 formattedString = this.toHslString(); 189 } 190 if (format === "hsv") { 191 formattedString = this.toHsvString(); 192 } 193 194 return formattedString || this.toHexString(); 195 }, 196 197 _applyModification: function(fn, args) { 198 var color = fn.apply(null, [this].concat([].slice.call(args))); 199 this._r = color._r; 200 this._g = color._g; 201 this._b = color._b; 202 this.setAlpha(color._a); 203 return this; 204 }, 205 lighten: function() { 206 return this._applyModification(lighten, arguments); 207 }, 208 brighten: function() { 209 return this._applyModification(brighten, arguments); 210 }, 211 darken: function() { 212 return this._applyModification(darken, arguments); 213 }, 214 desaturate: function() { 215 return this._applyModification(desaturate, arguments); 216 }, 217 saturate: function() { 218 return this._applyModification(saturate, arguments); 219 }, 220 greyscale: function() { 221 return this._applyModification(greyscale, arguments); 222 }, 223 spin: function() { 224 return this._applyModification(spin, arguments); 225 }, 226 227 _applyCombination: function(fn, args) { 228 return fn.apply(null, [this].concat([].slice.call(args))); 229 }, 230 analogous: function() { 231 return this._applyCombination(analogous, arguments); 232 }, 233 complement: function() { 234 return this._applyCombination(complement, arguments); 235 }, 236 monochromatic: function() { 237 return this._applyCombination(monochromatic, arguments); 238 }, 239 splitcomplement: function() { 240 return this._applyCombination(splitcomplement, arguments); 241 }, 242 triad: function() { 243 return this._applyCombination(triad, arguments); 244 }, 245 tetrad: function() { 246 return this._applyCombination(tetrad, arguments); 247 } 248}; 249 250// If input is an object, force 1 into "1.0" to handle ratios properly 251// String input requires "1.0" as input, so 1 will be treated as 1 252tinycolor.fromRatio = function(color, opts) { 253 if (typeof color == "object") { 254 var newColor = {}; 255 for (var i in color) { 256 if (color.hasOwnProperty(i)) { 257 if (i === "a") { 258 newColor[i] = color[i]; 259 } 260 else { 261 newColor[i] = convertToPercentage(color[i]); 262 } 263 } 264 } 265 color = newColor; 266 } 267 268 return tinycolor(color, opts); 269}; 270 271// Given a string or object, convert that input to RGB 272// Possible string inputs: 273// 274// "red" 275// "#f00" or "f00" 276// "#ff0000" or "ff0000" 277// "#ff000000" or "ff000000" 278// "rgb 255 0 0" or "rgb (255, 0, 0)" 279// "rgb 1.0 0 0" or "rgb (1, 0, 0)" 280// "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1" 281// "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1" 282// "hsl(0, 100%, 50%)" or "hsl 0 100% 50%" 283// "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1" 284// "hsv(0, 100%, 100%)" or "hsv 0 100% 100%" 285// 286function inputToRGB(color) { 287 288 var rgb = { r: 0, g: 0, b: 0 }; 289 var a = 1; 290 var ok = false; 291 var format = false; 292 293 if (typeof color == "string") { 294 color = stringInputToObject(color); 295 } 296 297 if (typeof color == "object") { 298 if (color.hasOwnProperty("r") && color.hasOwnProperty("g") && color.hasOwnProperty("b")) { 299 rgb = rgbToRgb(color.r, color.g, color.b); 300 ok = true; 301 format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb"; 302 } 303 else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) { 304 color.s = convertToPercentage(color.s); 305 color.v = convertToPercentage(color.v); 306 rgb = hsvToRgb(color.h, color.s, color.v); 307 ok = true; 308 format = "hsv"; 309 } 310 else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) { 311 color.s = convertToPercentage(color.s); 312 color.l = convertToPercentage(color.l); 313 rgb = hslToRgb(color.h, color.s, color.l); 314 ok = true; 315 format = "hsl"; 316 } 317 318 if (color.hasOwnProperty("a")) { 319 a = color.a; 320 } 321 } 322 323 a = boundAlpha(a); 324 325 return { 326 ok: ok, 327 format: color.format || format, 328 r: mathMin(255, mathMax(rgb.r, 0)), 329 g: mathMin(255, mathMax(rgb.g, 0)), 330 b: mathMin(255, mathMax(rgb.b, 0)), 331 a: a 332 }; 333} 334 335 336// Conversion Functions 337// -------------------- 338 339// `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from: 340// <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript> 341 342// `rgbToRgb` 343// Handle bounds / percentage checking to conform to CSS color spec 344// <http://www.w3.org/TR/css3-color/> 345// *Assumes:* r, g, b in [0, 255] or [0, 1] 346// *Returns:* { r, g, b } in [0, 255] 347function rgbToRgb(r, g, b){ 348 return { 349 r: bound01(r, 255) * 255, 350 g: bound01(g, 255) * 255, 351 b: bound01(b, 255) * 255 352 }; 353} 354 355// `rgbToHsl` 356// Converts an RGB color value to HSL. 357// *Assumes:* r, g, and b are contained in [0, 255] or [0, 1] 358// *Returns:* { h, s, l } in [0,1] 359function rgbToHsl(r, g, b) { 360 361 r = bound01(r, 255); 362 g = bound01(g, 255); 363 b = bound01(b, 255); 364 365 var max = mathMax(r, g, b), min = mathMin(r, g, b); 366 var h, s, l = (max + min) / 2; 367 368 if(max == min) { 369 h = s = 0; // achromatic 370 } 371 else { 372 var d = max - min; 373 s = l > 0.5 ? d / (2 - max - min) : d / (max + min); 374 switch(max) { 375 case r: h = (g - b) / d + (g < b ? 6 : 0); break; 376 case g: h = (b - r) / d + 2; break; 377 case b: h = (r - g) / d + 4; break; 378 } 379 380 h /= 6; 381 } 382 383 return { h: h, s: s, l: l }; 384} 385 386// `hslToRgb` 387// Converts an HSL color value to RGB. 388// *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100] 389// *Returns:* { r, g, b } in the set [0, 255] 390function hslToRgb(h, s, l) { 391 var r, g, b; 392 393 h = bound01(h, 360); 394 s = bound01(s, 100); 395 l = bound01(l, 100); 396 397 function hue2rgb(p, q, t) { 398 if(t < 0) t += 1; 399 if(t > 1) t -= 1; 400 if(t < 1/6) return p + (q - p) * 6 * t; 401 if(t < 1/2) return q; 402 if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; 403 return p; 404 } 405 406 if(s === 0) { 407 r = g = b = l; // achromatic 408 } 409 else { 410 var q = l < 0.5 ? l * (1 + s) : l + s - l * s; 411 var p = 2 * l - q; 412 r = hue2rgb(p, q, h + 1/3); 413 g = hue2rgb(p, q, h); 414 b = hue2rgb(p, q, h - 1/3); 415 } 416 417 return { r: r * 255, g: g * 255, b: b * 255 }; 418} 419 420// `rgbToHsv` 421// Converts an RGB color value to HSV 422// *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1] 423// *Returns:* { h, s, v } in [0,1] 424function rgbToHsv(r, g, b) { 425 426 r = bound01(r, 255); 427 g = bound01(g, 255); 428 b = bound01(b, 255); 429 430 var max = mathMax(r, g, b), min = mathMin(r, g, b); 431 var h, s, v = max; 432 433 var d = max - min; 434 s = max === 0 ? 0 : d / max; 435 436 if(max == min) { 437 h = 0; // achromatic 438 } 439 else { 440 switch(max) { 441 case r: h = (g - b) / d + (g < b ? 6 : 0); break; 442 case g: h = (b - r) / d + 2; break; 443 case b: h = (r - g) / d + 4; break; 444 } 445 h /= 6; 446 } 447 return { h: h, s: s, v: v }; 448} 449 450// `hsvToRgb` 451// Converts an HSV color value to RGB. 452// *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100] 453// *Returns:* { r, g, b } in the set [0, 255] 454 function hsvToRgb(h, s, v) { 455 456 h = bound01(h, 360) * 6; 457 s = bound01(s, 100); 458 v = bound01(v, 100); 459 460 var i = math.floor(h), 461 f = h - i, 462 p = v * (1 - s), 463 q = v * (1 - f * s), 464 t = v * (1 - (1 - f) * s), 465 mod = i % 6, 466 r = [v, q, p, p, t, v][mod], 467 g = [t, v, v, q, p, p][mod], 468 b = [p, p, t, v, v, q][mod]; 469 470 return { r: r * 255, g: g * 255, b: b * 255 }; 471} 472 473// `rgbToHex` 474// Converts an RGB color to hex 475// Assumes r, g, and b are contained in the set [0, 255] 476// Returns a 3 or 6 character hex 477function rgbToHex(r, g, b, allow3Char) { 478 479 var hex = [ 480 pad2(mathRound(r).toString(16)), 481 pad2(mathRound(g).toString(16)), 482 pad2(mathRound(b).toString(16)) 483 ]; 484 485 // Return a 3 character hex if possible 486 if (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)) { 487 return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0); 488 } 489 490 return hex.join(""); 491} 492 // `rgbaToHex` 493 // Converts an RGBA color plus alpha transparency to hex 494 // Assumes r, g, b and a are contained in the set [0, 255] 495 // Returns an 8 character hex 496 function rgbaToHex(r, g, b, a) { 497 498 var hex = [ 499 pad2(convertDecimalToHex(a)), 500 pad2(mathRound(r).toString(16)), 501 pad2(mathRound(g).toString(16)), 502 pad2(mathRound(b).toString(16)) 503 ]; 504 505 return hex.join(""); 506 } 507 508// `equals` 509// Can be called with any tinycolor input 510tinycolor.equals = function (color1, color2) { 511 if (!color1 || !color2) { return false; } 512 return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString(); 513}; 514tinycolor.random = function() { 515 return tinycolor.fromRatio({ 516 r: mathRandom(), 517 g: mathRandom(), 518 b: mathRandom() 519 }); 520}; 521 522 523// Modification Functions 524// ---------------------- 525// Thanks to less.js for some of the basics here 526// <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js> 527 528function desaturate(color, amount) { 529 amount = (amount === 0) ? 0 : (amount || 10); 530 var hsl = tinycolor(color).toHsl(); 531 hsl.s -= amount / 100; 532 hsl.s = clamp01(hsl.s); 533 return tinycolor(hsl); 534} 535 536function saturate(color, amount) { 537 amount = (amount === 0) ? 0 : (amount || 10); 538 var hsl = tinycolor(color).toHsl(); 539 hsl.s += amount / 100; 540 hsl.s = clamp01(hsl.s); 541 return tinycolor(hsl); 542} 543 544function greyscale(color) { 545 return tinycolor(color).desaturate(100); 546} 547 548function lighten (color, amount) { 549 amount = (amount === 0) ? 0 : (amount || 10); 550 var hsl = tinycolor(color).toHsl(); 551 hsl.l += amount / 100; 552 hsl.l = clamp01(hsl.l); 553 return tinycolor(hsl); 554} 555 556function brighten(color, amount) { 557 amount = (amount === 0) ? 0 : (amount || 10); 558 var rgb = tinycolor(color).toRgb(); 559 rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100)))); 560 rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100)))); 561 rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100)))); 562 return tinycolor(rgb); 563} 564 565function darken (color, amount) { 566 amount = (amount === 0) ? 0 : (amount || 10); 567 var hsl = tinycolor(color).toHsl(); 568 hsl.l -= amount / 100; 569 hsl.l = clamp01(hsl.l); 570 return tinycolor(hsl); 571} 572 573// Spin takes a positive or negative amount within [-360, 360] indicating the change of hue. 574// Values outside of this range will be wrapped into this range. 575function spin(color, amount) { 576 var hsl = tinycolor(color).toHsl(); 577 var hue = (mathRound(hsl.h) + amount) % 360; 578 hsl.h = hue < 0 ? 360 + hue : hue; 579 return tinycolor(hsl); 580} 581 582// Combination Functions 583// --------------------- 584// Thanks to jQuery xColor for some of the ideas behind these 585// <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js> 586 587function complement(color) { 588 var hsl = tinycolor(color).toHsl(); 589 hsl.h = (hsl.h + 180) % 360; 590 return tinycolor(hsl); 591} 592 593function triad(color) { 594 var hsl = tinycolor(color).toHsl(); 595 var h = hsl.h; 596 return [ 597 tinycolor(color), 598 tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }), 599 tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l }) 600 ]; 601} 602 603function tetrad(color) { 604 var hsl = tinycolor(color).toHsl(); 605 var h = hsl.h; 606 return [ 607 tinycolor(color), 608 tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }), 609 tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }), 610 tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l }) 611 ]; 612} 613 614function splitcomplement(color) { 615 var hsl = tinycolor(color).toHsl(); 616 var h = hsl.h; 617 return [ 618 tinycolor(color), 619 tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}), 620 tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l}) 621 ]; 622} 623 624function analogous(color, results, slices) { 625 results = results || 6; 626 slices = slices || 30; 627 628 var hsl = tinycolor(color).toHsl(); 629 var part = 360 / slices; 630 var ret = [tinycolor(color)]; 631 632 for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) { 633 hsl.h = (hsl.h + part) % 360; 634 ret.push(tinycolor(hsl)); 635 } 636 return ret; 637} 638 639function monochromatic(color, results) { 640 results = results || 6; 641 var hsv = tinycolor(color).toHsv(); 642 var h = hsv.h, s = hsv.s, v = hsv.v; 643 var ret = []; 644 var modification = 1 / results; 645 646 while (results--) { 647 ret.push(tinycolor({ h: h, s: s, v: v})); 648 v = (v + modification) % 1; 649 } 650 651 return ret; 652} 653 654// Utility Functions 655// --------------------- 656 657tinycolor.mix = function(color1, color2, amount) { 658 amount = (amount === 0) ? 0 : (amount || 50); 659 660 var rgb1 = tinycolor(color1).toRgb(); 661 var rgb2 = tinycolor(color2).toRgb(); 662 663 var p = amount / 100; 664 var w = p * 2 - 1; 665 var a = rgb2.a - rgb1.a; 666 667 var w1; 668 669 if (w * a == -1) { 670 w1 = w; 671 } else { 672 w1 = (w + a) / (1 + w * a); 673 } 674 675 w1 = (w1 + 1) / 2; 676 677 var w2 = 1 - w1; 678 679 var rgba = { 680 r: rgb2.r * w1 + rgb1.r * w2, 681 g: rgb2.g * w1 + rgb1.g * w2, 682 b: rgb2.b * w1 + rgb1.b * w2, 683 a: rgb2.a * p + rgb1.a * (1 - p) 684 }; 685 686 return tinycolor(rgba); 687}; 688 689 690// Readability Functions 691// --------------------- 692// <http://www.w3.org/TR/AERT#color-contrast> 693 694// `readability` 695// Analyze the 2 colors and returns an object with the following properties: 696// `brightness`: difference in brightness between the two colors 697// `color`: difference in color/hue between the two colors 698tinycolor.readability = function(color1, color2) { 699 var c1 = tinycolor(color1); 700 var c2 = tinycolor(color2); 701 var rgb1 = c1.toRgb(); 702 var rgb2 = c2.toRgb(); 703 var brightnessA = c1.getBrightness(); 704 var brightnessB = c2.getBrightness(); 705 var colorDiff = ( 706 Math.max(rgb1.r, rgb2.r) - Math.min(rgb1.r, rgb2.r) + 707 Math.max(rgb1.g, rgb2.g) - Math.min(rgb1.g, rgb2.g) + 708 Math.max(rgb1.b, rgb2.b) - Math.min(rgb1.b, rgb2.b) 709 ); 710 711 return { 712 brightness: Math.abs(brightnessA - brightnessB), 713 color: colorDiff 714 }; 715}; 716 717// `readable` 718// http://www.w3.org/TR/AERT#color-contrast 719// Ensure that foreground and background color combinations provide sufficient contrast. 720// *Example* 721// tinycolor.isReadable("#000", "#111") => false 722tinycolor.isReadable = function(color1, color2) { 723 var readability = tinycolor.readability(color1, color2); 724 return readability.brightness > 125 && readability.color > 500; 725}; 726 727// `mostReadable` 728// Given a base color and a list of possible foreground or background 729// colors for that base, returns the most readable color. 730// *Example* 731// tinycolor.mostReadable("#123", ["#fff", "#000"]) => "#000" 732tinycolor.mostReadable = function(baseColor, colorList) { 733 var bestColor = null; 734 var bestScore = 0; 735 var bestIsReadable = false; 736 for (var i=0; i < colorList.length; i++) { 737 738 // We normalize both around the "acceptable" breaking point, 739 // but rank brightness constrast higher than hue. 740 741 var readability = tinycolor.readability(baseColor, colorList[i]); 742 var readable = readability.brightness > 125 && readability.color > 500; 743 var score = 3 * (readability.brightness / 125) + (readability.color / 500); 744 745 if ((readable && ! bestIsReadable) || 746 (readable && bestIsReadable && score > bestScore) || 747 ((! readable) && (! bestIsReadable) && score > bestScore)) { 748 bestIsReadable = readable; 749 bestScore = score; 750 bestColor = tinycolor(colorList[i]); 751 } 752 } 753 return bestColor; 754}; 755 756 757// Big List of Colors 758// ------------------ 759// <http://www.w3.org/TR/css3-color/#svg-color> 760var names = tinycolor.names = { 761 aliceblue: "f0f8ff", 762 antiquewhite: "faebd7", 763 aqua: "0ff", 764 aquamarine: "7fffd4", 765 azure: "f0ffff", 766 beige: "f5f5dc", 767 bisque: "ffe4c4", 768 black: "000", 769 blanchedalmond: "ffebcd", 770 blue: "00f", 771 blueviolet: "8a2be2", 772 brown: "a52a2a", 773 burlywood: "deb887", 774 burntsienna: "ea7e5d", 775 cadetblue: "5f9ea0", 776 chartreuse: "7fff00", 777 chocolate: "d2691e", 778 coral: "ff7f50", 779 cornflowerblue: "6495ed", 780 cornsilk: "fff8dc", 781 crimson: "dc143c", 782 cyan: "0ff", 783 darkblue: "00008b", 784 darkcyan: "008b8b", 785 darkgoldenrod: "b8860b", 786 darkgray: "a9a9a9", 787 darkgreen: "006400", 788 darkgrey: "a9a9a9", 789 darkkhaki: "bdb76b", 790 darkmagenta: "8b008b", 791 darkolivegreen: "556b2f", 792 darkorange: "ff8c00", 793 darkorchid: "9932cc", 794 darkred: "8b0000", 795 darksalmon: "e9967a", 796 darkseagreen: "8fbc8f", 797 darkslateblue: "483d8b", 798 darkslategray: "2f4f4f", 799 darkslategrey: "2f4f4f", 800 darkturquoise: "00ced1", 801 darkviolet: "9400d3", 802 deeppink: "ff1493", 803 deepskyblue: "00bfff", 804 dimgray: "696969", 805 dimgrey: "696969", 806 dodgerblue: "1e90ff", 807 firebrick: "b22222", 808 floralwhite: "fffaf0", 809 forestgreen: "228b22", 810 fuchsia: "f0f", 811 gainsboro: "dcdcdc", 812 ghostwhite: "f8f8ff", 813 gold: "ffd700", 814 goldenrod: "daa520", 815 gray: "808080", 816 green: "008000", 817 greenyellow: "adff2f", 818 grey: "808080", 819 honeydew: "f0fff0", 820 hotpink: "ff69b4", 821 indianred: "cd5c5c", 822 indigo: "4b0082", 823 ivory: "fffff0", 824 khaki: "f0e68c", 825 lavender: "e6e6fa", 826 lavenderblush: "fff0f5", 827 lawngreen: "7cfc00", 828 lemonchiffon: "fffacd", 829 lightblue: "add8e6", 830 lightcoral: "f08080", 831 lightcyan: "e0ffff", 832 lightgoldenrodyellow: "fafad2", 833 lightgray: "d3d3d3", 834 lightgreen: "90ee90", 835 lightgrey: "d3d3d3", 836 lightpink: "ffb6c1", 837 lightsalmon: "ffa07a", 838 lightseagreen: "20b2aa", 839 lightskyblue: "87cefa", 840 lightslategray: "789", 841 lightslategrey: "789", 842 lightsteelblue: "b0c4de", 843 lightyellow: "ffffe0", 844 lime: "0f0", 845 limegreen: "32cd32", 846 linen: "faf0e6", 847 magenta: "f0f", 848 maroon: "800000", 849 mediumaquamarine: "66cdaa", 850 mediumblue: "0000cd", 851 mediumorchid: "ba55d3", 852 mediumpurple: "9370db", 853 mediumseagreen: "3cb371", 854 mediumslateblue: "7b68ee", 855 mediumspringgreen: "00fa9a", 856 mediumturquoise: "48d1cc", 857 mediumvioletred: "c71585", 858 midnightblue: "191970", 859 mintcream: "f5fffa", 860 mistyrose: "ffe4e1", 861 moccasin: "ffe4b5", 862 navajowhite: "ffdead", 863 navy: "000080", 864 oldlace: "fdf5e6", 865 olive: "808000", 866 olivedrab: "6b8e23", 867 orange: "ffa500", 868 orangered: "ff4500", 869 orchid: "da70d6", 870 palegoldenrod: "eee8aa", 871 palegreen: "98fb98", 872 paleturquoise: "afeeee", 873 palevioletred: "db7093", 874 papayawhip: "ffefd5", 875 peachpuff: "ffdab9", 876 peru: "cd853f", 877 pink: "ffc0cb", 878 plum: "dda0dd", 879 powderblue: "b0e0e6", 880 purple: "800080", 881 rebeccapurple: "663399", 882 red: "f00", 883 rosybrown: "bc8f8f", 884 royalblue: "4169e1", 885 saddlebrown: "8b4513", 886 salmon: "fa8072", 887 sandybrown: "f4a460", 888 seagreen: "2e8b57", 889 seashell: "fff5ee", 890 sienna: "a0522d", 891 silver: "c0c0c0", 892 skyblue: "87ceeb", 893 slateblue: "6a5acd", 894 slategray: "708090", 895 slategrey: "708090", 896 snow: "fffafa", 897 springgreen: "00ff7f", 898 steelblue: "4682b4", 899 tan: "d2b48c", 900 teal: "008080", 901 thistle: "d8bfd8", 902 tomato: "ff6347", 903 turquoise: "40e0d0", 904 violet: "ee82ee", 905 wheat: "f5deb3", 906 white: "fff", 907 whitesmoke: "f5f5f5", 908 yellow: "ff0", 909 yellowgreen: "9acd32" 910}; 911 912// Make it easy to access colors via `hexNames[hex]` 913var hexNames = tinycolor.hexNames = flip(names); 914 915 916// Utilities 917// --------- 918 919// `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }` 920function flip(o) { 921 var flipped = { }; 922 for (var i in o) { 923 if (o.hasOwnProperty(i)) { 924 flipped[o[i]] = i; 925 } 926 } 927 return flipped; 928} 929 930// Return a valid alpha value [0,1] with all invalid values being set to 1 931function boundAlpha(a) { 932 a = parseFloat(a); 933 934 if (isNaN(a) || a < 0 || a > 1) { 935 a = 1; 936 } 937 938 return a; 939} 940 941// Take input from [0, n] and return it as [0, 1] 942function bound01(n, max) { 943 if (isOnePointZero(n)) { n = "100%"; } 944 945 var processPercent = isPercentage(n); 946 n = mathMin(max, mathMax(0, parseFloat(n))); 947 948 // Automatically convert percentage into number 949 if (processPercent) { 950 n = parseInt(n * max, 10) / 100; 951 } 952 953 // Handle floating point rounding errors 954 if ((math.abs(n - max) < 0.000001)) { 955 return 1; 956 } 957 958 // Convert into [0, 1] range if it isn't already 959 return (n % max) / parseFloat(max); 960} 961 962// Force a number between 0 and 1 963function clamp01(val) { 964 return mathMin(1, mathMax(0, val)); 965} 966 967// Parse a base-16 hex value into a base-10 integer 968function parseIntFromHex(val) { 969 return parseInt(val, 16); 970} 971 972// Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1 973// <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0> 974function isOnePointZero(n) { 975 return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1; 976} 977 978// Check to see if string passed in is a percentage 979function isPercentage(n) { 980 return typeof n === "string" && n.indexOf('%') != -1; 981} 982 983// Force a hex value to have 2 characters 984function pad2(c) { 985 return c.length == 1 ? '0' + c : '' + c; 986} 987 988// Replace a decimal with it's percentage value 989function convertToPercentage(n) { 990 if (n <= 1) { 991 n = (n * 100) + "%"; 992 } 993 994 return n; 995} 996 997// Converts a decimal to a hex value 998function convertDecimalToHex(d) { 999 return Math.round(parseFloat(d) * 255).toString(16); 1000} 1001// Converts a hex value to a decimal 1002function convertHexToDecimal(h) { 1003 return (parseIntFromHex(h) / 255); 1004} 1005 1006var matchers = (function() { 1007 1008 // <http://www.w3.org/TR/css3-values/#integers> 1009 var CSS_INTEGER = "[-\\+]?\\d+%?"; 1010 1011 // <http://www.w3.org/TR/css3-values/#number-value> 1012 var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?"; 1013 1014 // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome. 1015 var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")"; 1016 1017 // Actual matching. 1018 // Parentheses and commas are optional, but not required. 1019 // Whitespace can take the place of commas or opening paren 1020 var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; 1021 var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; 1022 1023 return { 1024 rgb: new RegExp("rgb" + PERMISSIVE_MATCH3), 1025 rgba: new RegExp("rgba" + PERMISSIVE_MATCH4), 1026 hsl: new RegExp("hsl" + PERMISSIVE_MATCH3), 1027 hsla: new RegExp("hsla" + PERMISSIVE_MATCH4), 1028 hsv: new RegExp("hsv" + PERMISSIVE_MATCH3), 1029 hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, 1030 hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/, 1031 hex8: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/ 1032 }; 1033})(); 1034 1035// `stringInputToObject` 1036// Permissive string parsing. Take in a number of formats, and output an object 1037// based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}` 1038function stringInputToObject(color) { 1039 1040 color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase(); 1041 var named = false;
vendor: 2,326 bytes, lines 1042-1112
1042 if (names[color]) { 1043 color = names[color]; 1044 named = true; 1045 } 1046 else if (color == 'transparent') { 1047 return { r: 0, g: 0, b: 0, a: 0, format: "name" }; 1048 } 1049 1050 // Try to match string input using regular expressions. 1051 // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360] 1052 // Just return an object and let the conversion functions handle that. 1053 // This way the result will be the same whether the tinycolor is initialized with string or object. 1054 var match; 1055 if ((match = matchers.rgb.exec(color))) { 1056 return { r: match[1], g: match[2], b: match[3] }; 1057 } 1058 if ((match = matchers.rgba.exec(color))) { 1059 return { r: match[1], g: match[2], b: match[3], a: match[4] }; 1060 } 1061 if ((match = matchers.hsl.exec(color))) { 1062 return { h: match[1], s: match[2], l: match[3] }; 1063 } 1064 if ((match = matchers.hsla.exec(color))) { 1065 return { h: match[1], s: match[2], l: match[3], a: match[4] }; 1066 } 1067 if ((match = matchers.hsv.exec(color))) { 1068 return { h: match[1], s: match[2], v: match[3] }; 1069 } 1070 if ((match = matchers.hex8.exec(color))) { 1071 return { 1072 a: convertHexToDecimal(match[1]), 1073 r: parseIntFromHex(match[2]), 1074 g: parseIntFromHex(match[3]), 1075 b: parseIntFromHex(match[4]), 1076 format: named ? "name" : "hex8" 1077 }; 1078 } 1079 if ((match = matchers.hex6.exec(color))) { 1080 return { 1081 r: parseIntFromHex(match[1]), 1082 g: parseIntFromHex(match[2]), 1083 b: parseIntFromHex(match[3]), 1084 format: named ? "name" : "hex" 1085 }; 1086 } 1087 if ((match = matchers.hex3.exec(color))) { 1088 return { 1089 r: parseIntFromHex(match[1] + '' + match[1]), 1090 g: parseIntFromHex(match[2] + '' + match[2]), 1091 b: parseIntFromHex(match[3] + '' + match[3]), 1092 format: named ? "name" : "hex" 1093 }; 1094 } 1095 1096 return false; 1097} 1098 1099// Node: Export function 1100if (typeof module !== "undefined" && module.exports) { 1101 module.exports = tinycolor; 1102} 1103// AMD/requirejs: Define the module 1104else if (typeof define === 'function' && define.amd) { 1105 define(function () {return tinycolor;}); 1106} 1107// Browser: Expose to window 1108else { 1109 window.tinycolor = tinycolor; 1110} 1111 1112})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.