1// TinyColor v1.4.1 2// https://github.com/bgrins/TinyColor 3// Brian Grinstead, MIT License 4// reformatted code by ThemeComplete 5( function( Math ) { 6 'use strict'; 7 8 var trimLeft = /^\s+/, 9 trimRight = /\s+$/, 10 tinyCounter = 0, 11 mathRound = Math.round, 12 mathMin = Math.min, 13 mathMax = Math.max, 14 mathRandom = Math.random; 15 16 var names = { 17 aliceblue: 'f0f8ff', 18 antiquewhite: 'faebd7', 19 aqua: '0ff', 20 aquamarine: '7fffd4', 21 azure: 'f0ffff', 22 beige: 'f5f5dc', 23 bisque: 'ffe4c4', 24 black: '000', 25 blanchedalmond: 'ffebcd', 26 blue: '00f', 27 blueviolet: '8a2be2', 28 brown: 'a52a2a', 29 burlywood: 'deb887', 30 burntsienna: 'ea7e5d', 31 cadetblue: '5f9ea0', 32 chartreuse: '7fff00', 33 chocolate: 'd2691e', 34 coral: 'ff7f50', 35 cornflowerblue: '6495ed', 36 cornsilk: 'fff8dc', 37 crimson: 'dc143c', 38 cyan: '0ff', 39 darkblue: '00008b', 40 darkcyan: '008b8b', 41 darkgoldenrod: 'b8860b', 42 darkgray: 'a9a9a9', 43 darkgreen: '006400', 44 darkgrey: 'a9a9a9', 45 darkkhaki: 'bdb76b', 46 darkmagenta: '8b008b', 47 darkolivegreen: '556b2f', 48 darkorange: 'ff8c00', 49 darkorchid: '9932cc', 50 darkred: '8b0000', 51 darksalmon: 'e9967a', 52 darkseagreen: '8fbc8f', 53 darkslateblue: '483d8b', 54 darkslategray: '2f4f4f', 55 darkslategrey: '2f4f4f', 56 darkturquoise: '00ced1', 57 darkviolet: '9400d3', 58 deeppink: 'ff1493', 59 deepskyblue: '00bfff', 60 dimgray: '696969', 61 dimgrey: '696969', 62 dodgerblue: '1e90ff', 63 firebrick: 'b22222', 64 floralwhite: 'fffaf0', 65 forestgreen: '228b22', 66 fuchsia: 'f0f', 67 gainsboro: 'dcdcdc', 68 ghostwhite: 'f8f8ff', 69 gold: 'ffd700', 70 goldenrod: 'daa520', 71 gray: '808080', 72 green: '008000', 73 greenyellow: 'adff2f', 74 grey: '808080', 75 honeydew: 'f0fff0', 76 hotpink: 'ff69b4', 77 indianred: 'cd5c5c', 78 indigo: '4b0082', 79 ivory: 'fffff0', 80 khaki: 'f0e68c', 81 lavender: 'e6e6fa', 82 lavenderblush: 'fff0f5', 83 lawngreen: '7cfc00', 84 lemonchiffon: 'fffacd', 85 lightblue: 'add8e6', 86 lightcoral: 'f08080', 87 lightcyan: 'e0ffff', 88 lightgoldenrodyellow: 'fafad2', 89 lightgray: 'd3d3d3', 90 lightgreen: '90ee90', 91 lightgrey: 'd3d3d3', 92 lightpink: 'ffb6c1', 93 lightsalmon: 'ffa07a', 94 lightseagreen: '20b2aa', 95 lightskyblue: '87cefa', 96 lightslategray: '789', 97 lightslategrey: '789', 98 lightsteelblue: 'b0c4de', 99 lightyellow: 'ffffe0', 100 lime: '0f0', 101 limegreen: '32cd32', 102 linen: 'faf0e6', 103 magenta: 'f0f', 104 maroon: '800000', 105 mediumaquamarine: '66cdaa', 106 mediumblue: '0000cd', 107 mediumorchid: 'ba55d3', 108 mediumpurple: '9370db', 109 mediumseagreen: '3cb371', 110 mediumslateblue: '7b68ee', 111 mediumspringgreen: '00fa9a', 112 mediumturquoise: '48d1cc', 113 mediumvioletred: 'c71585', 114 midnightblue: '191970', 115 mintcream: 'f5fffa', 116 mistyrose: 'ffe4e1', 117 moccasin: 'ffe4b5', 118 navajowhite: 'ffdead', 119 navy: '000080', 120 oldlace: 'fdf5e6', 121 olive: '808000', 122 olivedrab: '6b8e23', 123 orange: 'ffa500', 124 orangered: 'ff4500', 125 orchid: 'da70d6', 126 palegoldenrod: 'eee8aa', 127 palegreen: '98fb98', 128 paleturquoise: 'afeeee', 129 palevioletred: 'db7093', 130 papayawhip: 'ffefd5', 131 peachpuff: 'ffdab9', 132 peru: 'cd853f', 133 pink: 'ffc0cb', 134 plum: 'dda0dd', 135 powderblue: 'b0e0e6', 136 purple: '800080', 137 rebeccapurple: '663399', 138 red: 'f00', 139 rosybrown: 'bc8f8f', 140 royalblue: '4169e1', 141 saddlebrown: '8b4513', 142 salmon: 'fa8072', 143 sandybrown: 'f4a460', 144 seagreen: '2e8b57', 145 seashell: 'fff5ee', 146 sienna: 'a0522d', 147 silver: 'c0c0c0', 148 skyblue: '87ceeb', 149 slateblue: '6a5acd', 150 slategray: '708090', 151 slategrey: '708090', 152 snow: 'fffafa', 153 springgreen: '00ff7f', 154 steelblue: '4682b4', 155 tan: 'd2b48c', 156 teal: '008080', 157 thistle: 'd8bfd8', 158 tomato: 'ff6347', 159 turquoise: '40e0d0', 160 violet: 'ee82ee', 161 wheat: 'f5deb3', 162 white: 'fff', 163 whitesmoke: 'f5f5f5', 164 yellow: 'ff0', 165 yellowgreen: '9acd32' 166 }; 167 168 // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }` 169 var flip = function( o ) { 170 var flipped = {}; 171 var i; 172 for ( i in o ) { 173 if ( Object.prototype.hasOwnProperty.call( o, i ) ) { 174 flipped[ o[ i ] ] = i; 175 } 176 } 177 return flipped; 178 }; 179 180 var hexNames = flip( names ); 181 182 var matchers = ( function() { 183 // <http://www.w3.org/TR/css3-values/#integers> 184 var CSS_INTEGER = '[-\\+]?\\d+%?'; 185 186 // <http://www.w3.org/TR/css3-values/#number-value> 187 var CSS_NUMBER = '[-\\+]?\\d*\\.\\d+%?'; 188 189 // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome. 190 var CSS_UNIT = '(?:' + CSS_NUMBER + ')|(?:' + CSS_INTEGER + ')'; 191 192 // Actual matching. 193 // Parentheses and commas are optional, but not required. 194 // Whitespace can take the place of commas or opening paren 195 var PERMISSIVE_MATCH3 = '[\\s|\\(]+(' + CSS_UNIT + ')[,|\\s]+(' + CSS_UNIT + ')[,|\\s]+(' + CSS_UNIT + ')\\s*\\)?'; 196 var PERMISSIVE_MATCH4 = '[\\s|\\(]+(' + CSS_UNIT + ')[,|\\s]+(' + CSS_UNIT + ')[,|\\s]+(' + CSS_UNIT + ')[,|\\s]+(' + CSS_UNIT + ')\\s*\\)?'; 197 198 return { 199 CSS_UNIT: new RegExp( CSS_UNIT ), 200 rgb: new RegExp( 'rgb' + PERMISSIVE_MATCH3 ), 201 rgba: new RegExp( 'rgba' + PERMISSIVE_MATCH4 ), 202 hsl: new RegExp( 'hsl' + PERMISSIVE_MATCH3 ), 203 hsla: new RegExp( 'hsla' + PERMISSIVE_MATCH4 ), 204 hsv: new RegExp( 'hsv' + PERMISSIVE_MATCH3 ), 205 hsva: new RegExp( 'hsva' + PERMISSIVE_MATCH4 ), 206 hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, 207 hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/, 208 hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, 209 hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/ 210 }; 211 }() ); 212 213 // `isValidCSSUnit`
214 // Take in a single string / number and check to see if it looks like a CSS unit 215 // (see `matchers` above for definition). 216 function isValidCSSUnit( color ) { 217 return !! matchers.CSS_UNIT.exec( color ); 218 } 219 220 // Parse a base-16 hex value into a base-10 integer 221 function parseIntFromHex( val ) { 222 return parseInt( val, 16 ); 223 } 224 225 // Converts a hex value to a decimal 226 function convertHexToDecimal( h ) { 227 return parseIntFromHex( h ) / 255; 228 } 229 230 // `stringInputToObject` 231 // Permissive string parsing. Take in a number of formats, and output an object 232 // based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}` 233 function stringInputToObject( color ) { 234 var named = false; 235 var match; 236 color = color.replace( trimLeft, '' ).replace( trimRight, '' ).toLowerCase(); 237 238 if ( names[ color ] ) { 239 color = names[ color ]; 240 named = true; 241 } else if ( color === 'transparent' ) { 242 return { r: 0, g: 0, b: 0, a: 0, format: 'name' }; 243 } 244 245 // Try to match string input using regular expressions. 246 // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360] 247 // Just return an object and let the conversion functions handle that. 248 // This way the result will be the same whether the TinyColor is initialized with string or object. 249 250 if ( ( match = matchers.rgb.exec( color ) ) ) { 251 return { r: match[ 1 ], g: match[ 2 ], b: match[ 3 ] }; 252 } 253 if ( ( match = matchers.rgba.exec( color ) ) ) { 254 return { r: match[ 1 ], g: match[ 2 ], b: match[ 3 ], a: match[ 4 ] }; 255 } 256 if ( ( match = matchers.hsl.exec( color ) ) ) { 257 return { h: match[ 1 ], s: match[ 2 ], l: match[ 3 ] }; 258 } 259 if ( ( match = matchers.hsla.exec( color ) ) ) { 260 return { h: match[ 1 ], s: match[ 2 ], l: match[ 3 ], a: match[ 4 ] }; 261 } 262 if ( ( match = matchers.hsv.exec( color ) ) ) { 263 return { h: match[ 1 ], s: match[ 2 ], v: match[ 3 ] }; 264 } 265 if ( ( match = matchers.hsva.exec( color ) ) ) { 266 return { h: match[ 1 ], s: match[ 2 ], v: match[ 3 ], a: match[ 4 ] }; 267 } 268 if ( ( match = matchers.hex8.exec( color ) ) ) { 269 return { 270 r: parseIntFromHex( match[ 1 ] ), 271 g: parseIntFromHex( match[ 2 ] ), 272 b: parseIntFromHex( match[ 3 ] ), 273 a: convertHexToDecimal( match[ 4 ] ), 274 format: named ? 'name' : 'hex8' 275 }; 276 } 277 if ( ( match = matchers.hex6.exec( color ) ) ) { 278 return { 279 r: parseIntFromHex( match[ 1 ] ), 280 g: parseIntFromHex( match[ 2 ] ), 281 b: parseIntFromHex( match[ 3 ] ), 282 format: named ? 'name' : 'hex' 283 }; 284 } 285 if ( ( match = matchers.hex4.exec( color ) ) ) { 286 return { 287 r: parseIntFromHex( match[ 1 ] + '' + match[ 1 ] ), 288 g: parseIntFromHex( match[ 2 ] + '' + match[ 2 ] ), 289 b: parseIntFromHex( match[ 3 ] + '' + match[ 3 ] ), 290 a: convertHexToDecimal( match[ 4 ] + '' + match[ 4 ] ), 291 format: named ? 'name' : 'hex8' 292 }; 293 } 294 if ( ( match = matchers.hex3.exec( color ) ) ) { 295 return { 296 r: parseIntFromHex( match[ 1 ] + '' + match[ 1 ] ), 297 g: parseIntFromHex( match[ 2 ] + '' + match[ 2 ] ), 298 b: parseIntFromHex( match[ 3 ] + '' + match[ 3 ] ), 299 format: named ? 'name' : 'hex' 300 }; 301 } 302 303 return false; 304 } 305 306 function validateWCAG2Parms( parms ) { 307 // return valid WCAG2 parms for isReadable. 308 // If input parms are invalid, return {"level":"AA", "size":"small"} 309 var level, size; 310 parms = parms || { level: 'AA', size: 'small' }; 311 level = ( parms.level || 'AA' ).toUpperCase(); 312 size = ( parms.size || 'small' ).toLowerCase(); 313 if ( level !== 'AA' && level !== 'AAA' ) { 314 level = 'AA'; 315 } 316 if ( size !== 'small' && size !== 'large' ) { 317 size = 'small'; 318 } 319 return { level: level, size: size }; 320 } 321 322 // Utilities 323 // --------- 324 325 // Return a valid alpha value [0,1] with all invalid values being set to 1 326 function boundAlpha( a ) { 327 a = parseFloat( a ); 328 329 if ( isNaN( a ) || a < 0 || a > 1 ) { 330 a = 1; 331 } 332 333 return a; 334 } 335 336 // Check to see if string passed in is a percentage 337 function isPercentage( n ) { 338 return typeof n === 'string' && n.indexOf( '%' ) !== -1; 339 } 340 341 // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1 342 // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0> 343 function isOnePointZero( n ) { 344 return typeof n === 'string' && n.indexOf( '.' ) !== -1 && parseFloat( n ) === 1; 345 } 346 347 // Take input from [0, n] and return it as [0, 1] 348 function bound01( n, max ) { 349 var processPercent; 350 if ( isOnePointZero( n ) ) { 351 n = '100%'; 352 } 353 354 processPercent = isPercentage( n ); 355 n = mathMin( max, mathMax( 0, parseFloat( n ) ) ); 356 357 // Automatically convert percentage into number 358 if ( processPercent ) { 359 n = parseInt( n * max, 10 ) / 100; 360 } 361 362 // Handle floating point rounding errors 363 if ( Math.abs( n - max ) < 0.000001 ) { 364 return 1; 365 } 366 367 // Convert into [0, 1] range if it isn't already 368 return ( n % max ) / parseFloat( max ); 369 } 370 371 // Force a number between 0 and 1 372 function clamp01( val ) { 373 return mathMin( 1, mathMax( 0, val ) ); 374 } 375 376 // Force a hex value to have 2 characters 377 function pad2( c ) { 378 return c.length === 1 ? '0' + c : '' + c; 379 } 380 381 // Replace a decimal with it's percentage value 382 function convertToPercentage( n ) { 383 if ( n <= 1 ) { 384 n = ( n * 100 ) + '%'; 385 } 386 387 return n; 388 } 389 390 // Converts a decimal to a hex value 391 function convertDecimalToHex( d ) { 392 return Math.round( parseFloat( d ) * 255 ).toString( 16 ); 393 } 394 395 // Conversion Functions 396 // -------------------- 397 398 // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
399 // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript> 400 401 // `rgbToRgb` 402 // Handle bounds / percentage checking to conform to CSS color spec 403 // <http://www.w3.org/TR/css3-color/> 404 // *Assumes:* r, g, b in [0, 255] or [0, 1] 405 // *Returns:* { r, g, b } in [0, 255] 406 function rgbToRgb( r, g, b ) { 407 return { 408 r: bound01( r, 255 ) * 255, 409 g: bound01( g, 255 ) * 255, 410 b: bound01( b, 255 ) * 255 411 }; 412 } 413 414 // `rgbToHsl` 415 // Converts an RGB color value to HSL. 416 // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1] 417 // *Returns:* { h, s, l } in [0,1] 418 function rgbToHsl( r, g, b ) { 419 var max; 420 var min; 421 var h; 422 var s; 423 var l; 424 var d; 425 426 r = bound01( r, 255 ); 427 g = bound01( g, 255 ); 428 b = bound01( b, 255 ); 429 430 max = mathMax( r, g, b ); 431 min = mathMin( r, g, b ); 432 l = ( max + min ) / 2; 433 434 if ( max === min ) { 435 h = s = 0; // achromatic 436 } else { 437 d = max - min; 438 s = l > 0.5 ? d / ( 2 - max - min ) : d / ( max + min ); 439 switch ( max ) { 440 case r: 441 h = ( ( g - b ) / d ) + ( g < b ? 6 : 0 ); 442 break; 443 case g: 444 h = ( ( b - r ) / d ) + 2; 445 break; 446 case b: 447 h = ( ( r - g ) / d ) + 4; 448 break; 449 } 450 451 h /= 6; 452 } 453 454 return { h: h, s: s, l: l }; 455 } 456 457 // `hslToRgb` 458 // Converts an HSL color value to RGB. 459 // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100] 460 // *Returns:* { r, g, b } in the set [0, 255] 461 function hslToRgb( h, s, l ) { 462 var r; 463 var g; 464 var b; 465 var q; 466 var p; 467 468 h = bound01( h, 360 ); 469 s = bound01( s, 100 ); 470 l = bound01( l, 100 ); 471 472 function hue2rgb( pp, qq, t ) { 473 if ( t < 0 ) { 474 t += 1; 475 } 476 if ( t > 1 ) { 477 t -= 1; 478 } 479 if ( t < 1 / 6 ) { 480 return pp + ( ( qq - pp ) * 6 * t ); 481 } 482 if ( t < 1 / 2 ) { 483 return qq; 484 } 485 if ( t < 2 / 3 ) { 486 return pp + ( ( qq - pp ) * ( ( 2 / 3 ) - t ) * 6 ); 487 } 488 return pp; 489 } 490 491 if ( s === 0 ) { 492 r = g = b = l; // achromatic 493 } else { 494 q = l < 0.5 ? l * ( 1 + s ) : l + s - ( l * s ); 495 p = ( 2 * l ) - q; 496 r = hue2rgb( p, q, h + ( 1 / 3 ) ); 497 g = hue2rgb( p, q, h ); 498 b = hue2rgb( p, q, h - ( 1 / 3 ) ); 499 } 500 501 return { r: r * 255, g: g * 255, b: b * 255 }; 502 } 503 504 // `rgbToHsv` 505 // Converts an RGB color value to HSV 506 // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1] 507 // *Returns:* { h, s, v } in [0,1] 508 function rgbToHsv( r, g, b ) { 509 var max; 510 var min; 511 var h; 512 var s; 513 var v; 514 var d; 515 516 r = bound01( r, 255 ); 517 g = bound01( g, 255 ); 518 b = bound01( b, 255 ); 519 520 max = mathMax( r, g, b ); 521 min = mathMin( r, g, b ); 522 v = max; 523 524 d = max - min; 525 s = max === 0 ? 0 : d / max; 526 527 if ( max === min ) { 528 h = 0; // achromatic 529 } else { 530 switch ( max ) { 531 case r: 532 h = ( ( g - b ) / d ) + ( g < b ? 6 : 0 ); 533 break; 534 case g: 535 h = ( ( b - r ) / d ) + 2; 536 break; 537 case b: 538 h = ( ( r - g ) / d ) + 4; 539 break; 540 } 541 h /= 6; 542 } 543 return { h: h, s: s, v: v }; 544 } 545 546 // `hsvToRgb` 547 // Converts an HSV color value to RGB. 548 // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100] 549 // *Returns:* { r, g, b } in the set [0, 255] 550 function hsvToRgb( h, s, v ) { 551 var i; 552 var f; 553 var p; 554 var q; 555 var t; 556 var mod; 557 var r; 558 var g; 559 var b; 560 561 h = bound01( h, 360 ) * 6; 562 s = bound01( s, 100 ); 563 v = bound01( v, 100 ); 564 565 i = Math.floor( h ); 566 f = h - i; 567 p = v * ( 1 - s ); 568 q = v * ( 1 - ( f * s ) ); 569 t = v * ( 1 - ( ( 1 - f ) * s ) ); 570 mod = i % 6; 571 r = [ v, q, p, p, t, v ][ mod ]; 572 g = [ t, v, v, q, p, p ][ mod ]; 573 b = [ p, p, t, v, v, q ][ mod ]; 574 575 return { r: r * 255, g: g * 255, b: b * 255 }; 576 } 577 578 // `rgbToHex` 579 // Converts an RGB color to hex 580 // Assumes r, g, and b are contained in the set [0, 255] 581 // Returns a 3 or 6 character hex 582 function rgbToHex( r, g, b, allow3Char ) { 583 var hex = [ pad2( mathRound( r ).toString( 16 ) ), pad2( mathRound( g ).toString( 16 ) ), pad2( mathRound( b ).toString( 16 ) ) ]; 584 585 // Return a 3 character hex if possible 586 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 ) ) { 587 return hex[ 0 ].charAt( 0 ) + hex[ 1 ].charAt( 0 ) + hex[ 2 ].charAt( 0 ); 588 } 589 590 return hex.join( '' ); 591 } 592 593 // `rgbaToHex` 594 // Converts an RGBA color plus alpha transparency to hex 595 // Assumes r, g, b are contained in the set [0, 255] and 596 // a in [0, 1]. Returns a 4 or 8 character rgba hex 597 function rgbaToHex( r, g, b, a, allow4Char ) { 598 var hex = [ pad2( mathRound( r ).toString( 16 ) ), pad2( mathRound( g ).toString( 16 ) ), pad2( mathRound( b ).toString( 16 ) ), pad2( convertDecimalToHex( a ) ) ]; 599 600 // Return a 4 character hex if possible 601 if ( allow4Char && 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[ 3 ].charAt( 0 ) === hex[ 3 ].charAt( 1 ) ) { 602 return hex[ 0 ].charAt( 0 ) + hex[ 1 ].charAt( 0 ) + hex[ 2 ].charAt( 0 ) + hex[ 3 ].charAt( 0 ); 603 } 604 605 return hex.join( '' ); 606 } 607 608 // `rgbaToArgbHex` 609 // Converts an RGBA color to an ARGB Hex8 string 610 // Rarely used, but required for "toFilter()" 611 function rgbaToArgbHex( r, g, b, a ) { 612 var hex = [ pad2( convertDecimalToHex( a ) ), pad2( mathRound( r ).toString( 16 ) ), pad2( mathRound( g ).toString( 16 ) ), pad2( mathRound( b ).toString( 16 ) ) ]; 613 614 return hex.join( '' ); 615 } 616 617 // Given a string or object, convert that input to RGB
618 // Possible string inputs: 619 // 620 // "red" 621 // "#f00" or "f00" 622 // "#ff0000" or "ff0000" 623 // "#ff000000" or "ff000000" 624 // "rgb 255 0 0" or "rgb (255, 0, 0)" 625 // "rgb 1.0 0 0" or "rgb (1, 0, 0)" 626 // "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1" 627 // "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1" 628 // "hsl(0, 100%, 50%)" or "hsl 0 100% 50%" 629 // "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1" 630 // "hsv(0, 100%, 100%)" or "hsv 0 100% 100%" 631 // 632 function inputToRGB( color ) { 633 var rgb = { r: 0, g: 0, b: 0 }; 634 var a = 1; 635 var s = null; 636 var v = null; 637 var l = null; 638 var ok = false; 639 var format = false; 640 641 if ( typeof color === 'string' ) { 642 color = stringInputToObject( color ); 643 } 644 645 if ( typeof color === 'object' ) { 646 if ( isValidCSSUnit( color.r ) && isValidCSSUnit( color.g ) && isValidCSSUnit( color.b ) ) { 647 rgb = rgbToRgb( color.r, color.g, color.b ); 648 ok = true; 649 format = String( color.r ).substring( String( color.r ).length - 1 ) === '%' ? 'prgb' : 'rgb'; 650 } else if ( isValidCSSUnit( color.h ) && isValidCSSUnit( color.s ) && isValidCSSUnit( color.v ) ) { 651 s = convertToPercentage( color.s ); 652 v = convertToPercentage( color.v ); 653 rgb = hsvToRgb( color.h, s, v ); 654 ok = true; 655 format = 'hsv'; 656 } else if ( isValidCSSUnit( color.h ) && isValidCSSUnit( color.s ) && isValidCSSUnit( color.l ) ) { 657 s = convertToPercentage( color.s ); 658 l = convertToPercentage( color.l ); 659 rgb = hslToRgb( color.h, s, l ); 660 ok = true; 661 format = 'hsl'; 662 } 663 664 if ( Object.prototype.hasOwnProperty.call( color, 'a' ) ) { 665 a = color.a; 666 } 667 } 668 669 a = boundAlpha( a ); 670 671 return { 672 ok: ok, 673 format: color.format || format, 674 r: mathMin( 255, mathMax( rgb.r, 0 ) ), 675 g: mathMin( 255, mathMax( rgb.g, 0 ) ), 676 b: mathMin( 255, mathMax( rgb.b, 0 ) ), 677 a: a 678 }; 679 } 680 681 function TinyColor( color, opts ) { 682 var rgb; 683 color = color ? color : ''; 684 opts = opts || {}; 685 686 // If input is already a TinyColor, return itself 687 if ( color instanceof TinyColor ) { 688 return color; 689 } 690 // If we are called as a function, call using new instead 691 if ( ! ( this instanceof TinyColor ) ) { 692 return new TinyColor( color, opts ); 693 } 694 695 rgb = inputToRGB( color ); 696 this._originalInput = color; 697 this._r = rgb.r; 698 this._g = rgb.g; 699 this._b = rgb.b; 700 this._a = rgb.a; 701 this._roundA = mathRound( 100 * this._a ) / 100; 702 if ( opts.format ) { 703 this._format = opts.format; 704 } else { 705 this._format = rgb.format; 706 } 707 708 this._gradientType = opts.gradientType; 709 710 // Don't let the range of [0,255] come back in [0,1]. 711 // Potentially lose a little bit of precision here, but will fix issues where 712 // .5 gets interpreted as half of the total, instead of half of 1 713 // If it was supposed to be 128, this was already taken care of by `inputToRgb` 714 if ( this._r < 1 ) { 715 this._r = mathRound( this._r ); 716 } 717 if ( this._g < 1 ) { 718 this._g = mathRound( this._g ); 719 } 720 if ( this._b < 1 ) { 721 this._b = mathRound( this._b ); 722 } 723 724 this._ok = rgb.ok; 725 tinyCounter = tinyCounter + 1; 726 this._tc_id = tinyCounter; 727 } 728 729 function newTinyColor( color, opts ) { 730 return new TinyColor( color, opts ); 731 } 732 733 // Modification Functions 734 // ---------------------- 735 // Thanks to less.js for some of the basics here 736 // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js> 737 738 function desaturate( color, amount ) { 739 var hsl; 740 amount = amount === 0 ? 0 : amount || 10; 741 hsl = newTinyColor( color ).toHsl(); 742 hsl.s -= amount / 100; 743 hsl.s = clamp01( hsl.s ); 744 return newTinyColor( hsl ); 745 } 746 747 function saturate( color, amount ) { 748 var hsl; 749 amount = amount === 0 ? 0 : amount || 10; 750 hsl = newTinyColor( color ).toHsl(); 751 hsl.s += amount / 100; 752 hsl.s = clamp01( hsl.s ); 753 return newTinyColor( hsl ); 754 } 755 756 function greyscale( color ) { 757 return newTinyColor( color ).desaturate( 100 ); 758 } 759 760 function lighten( color, amount ) { 761 var hsl; 762 amount = amount === 0 ? 0 : amount || 10; 763 hsl = newTinyColor( color ).toHsl(); 764 hsl.l += amount / 100; 765 hsl.l = clamp01( hsl.l ); 766 return newTinyColor( hsl ); 767 } 768 769 function brighten( color, amount ) { 770 var rgb; 771 amount = amount === 0 ? 0 : amount || 10; 772 rgb = newTinyColor( color ).toRgb(); 773 rgb.r = mathMax( 0, mathMin( 255, rgb.r - mathRound( 255 * -( amount / 100 ) ) ) ); 774 rgb.g = mathMax( 0, mathMin( 255, rgb.g - mathRound( 255 * -( amount / 100 ) ) ) ); 775 rgb.b = mathMax( 0, mathMin( 255, rgb.b - mathRound( 255 * -( amount / 100 ) ) ) ); 776 return newTinyColor( rgb ); 777 } 778 779 function darken( color, amount ) { 780 var hsl; 781 amount = amount === 0 ? 0 : amount || 10; 782 hsl = newTinyColor( color ).toHsl(); 783 hsl.l -= amount / 100; 784 hsl.l = clamp01( hsl.l ); 785 return newTinyColor( hsl ); 786 } 787 788 // Spin takes a positive or negative amount within [-360, 360] indicating the change of hue. 789 // Values outside of this range will be wrapped into this range. 790 function spin( color, amount ) { 791 var hsl = newTinyColor( color ).toHsl(); 792 var hue = ( hsl.h + amount ) % 360; 793 hsl.h = hue < 0 ? 360 + hue : hue; 794 return newTinyColor( hsl ); 795 } 796 797 // Combination Functions 798 // --------------------- 799 // Thanks to jQuery xColor for some of the ideas behind these 800 // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js> 801 802 function complement( color ) { 803 var hsl = newTinyColor( color ).toHsl(); 804 hsl.h = ( hsl.h + 180 ) % 360; 805 return newTinyColor( hsl ); 806 } 807 808 function triad( color ) { 809 var hsl = newTinyColor( color ).toHsl();
vendor: 9,882 bytes, lines 810-1125
810 var h = hsl.h; 811 return [ newTinyColor( color ), newTinyColor( { h: ( h + 120 ) % 360, s: hsl.s, l: hsl.l } ), newTinyColor( { h: ( h + 240 ) % 360, s: hsl.s, l: hsl.l } ) ]; 812 } 813 814 function tetrad( color ) { 815 var hsl = newTinyColor( color ).toHsl(); 816 var h = hsl.h; 817 return [ newTinyColor( color ), newTinyColor( { h: ( h + 90 ) % 360, s: hsl.s, l: hsl.l } ), newTinyColor( { h: ( h + 180 ) % 360, s: hsl.s, l: hsl.l } ), newTinyColor( { h: ( h + 270 ) % 360, s: hsl.s, l: hsl.l } ) ]; 818 } 819 820 function splitcomplement( color ) { 821 var hsl = newTinyColor( color ).toHsl(); 822 var h = hsl.h; 823 return [ newTinyColor( color ), newTinyColor( { h: ( h + 72 ) % 360, s: hsl.s, l: hsl.l } ), newTinyColor( { h: ( h + 216 ) % 360, s: hsl.s, l: hsl.l } ) ]; 824 } 825 826 /*function analogous(color, results, slices) { 827 results = results || 6; 828 slices = slices || 30; 829 830 var hsl = newTinyColor(color).toHsl(); 831 var part = 360 / slices; 832 var ret = [newTinyColor(color)]; 833 834 for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results;) { 835 hsl.h = (hsl.h + part) % 360; 836 ret.push(newTinyColor(hsl)); 837 } 838 return ret; 839 } 840 841 function monochromatic(color, results) { 842 var hsv; 843 var h; 844 var s; 845 var v; 846 var ret; 847 var modification; 848 results = results || 6; 849 hsv = newTinyColor(color).toHsv(); 850 h = hsv.h; 851 s = hsv.s; 852 v = hsv.v; 853 ret = []; 854 modification = 1 / results; 855 856 while (results--) { 857 ret.push(newTinyColor({h: h, s: s, v: v})); 858 v = (v + modification) % 1; 859 } 860 861 return ret; 862 }*/ 863 864 TinyColor.prototype = { 865 isDark: function() { 866 return this.getBrightness() < 128; 867 }, 868 isLight: function() { 869 return ! this.isDark(); 870 }, 871 isValid: function() { 872 return this._ok; 873 }, 874 getOriginalInput: function() { 875 return this._originalInput; 876 }, 877 getFormat: function() { 878 return this._format; 879 }, 880 getAlpha: function() { 881 return this._a; 882 }, 883 getBrightness: function() { 884 //http://www.w3.org/TR/AERT#color-contrast 885 var rgb = this.toRgb(); 886 return ( ( rgb.r * 299 ) + ( rgb.g * 587 ) + ( rgb.b * 114 ) ) / 1000; 887 }, 888 getLuminance: function() { 889 //http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef 890 var rgb = this.toRgb(); 891 var RsRGB, GsRGB, BsRGB, R, G, B; 892 RsRGB = rgb.r / 255; 893 GsRGB = rgb.g / 255; 894 BsRGB = rgb.b / 255; 895 896 if ( RsRGB <= 0.03928 ) { 897 R = RsRGB / 12.92; 898 } else { 899 R = Math.pow( ( RsRGB + 0.055 ) / 1.055, 2.4 ); 900 } 901 if ( GsRGB <= 0.03928 ) { 902 G = GsRGB / 12.92; 903 } else { 904 G = Math.pow( ( GsRGB + 0.055 ) / 1.055, 2.4 ); 905 } 906 if ( BsRGB <= 0.03928 ) { 907 B = BsRGB / 12.92; 908 } else { 909 B = Math.pow( ( BsRGB + 0.055 ) / 1.055, 2.4 ); 910 } 911 return ( 0.2126 * R ) + ( 0.7152 * G ) + ( 0.0722 * B ); 912 }, 913 setAlpha: function( value ) { 914 this._a = boundAlpha( value ); 915 this._roundA = mathRound( 100 * this._a ) / 100; 916 return this; 917 }, 918 toHsv: function() { 919 var hsv = rgbToHsv( this._r, this._g, this._b ); 920 return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a }; 921 }, 922 toHsvString: function() { 923 var hsv = rgbToHsv( this._r, this._g, this._b ); 924 var h = mathRound( hsv.h * 360 ), 925 s = mathRound( hsv.s * 100 ), 926 v = mathRound( hsv.v * 100 ); 927 return this._a === 1 ? 'hsv(' + h + ', ' + s + '%, ' + v + '%)' : 'hsva(' + h + ', ' + s + '%, ' + v + '%, ' + this._roundA + ')'; 928 }, 929 toHsl: function() { 930 var hsl = rgbToHsl( this._r, this._g, this._b ); 931 return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a }; 932 }, 933 toHslString: function() { 934 var hsl = rgbToHsl( this._r, this._g, this._b ); 935 var h = mathRound( hsl.h * 360 ), 936 s = mathRound( hsl.s * 100 ), 937 l = mathRound( hsl.l * 100 ); 938 return this._a === 1 ? 'hsl(' + h + ', ' + s + '%, ' + l + '%)' : 'hsla(' + h + ', ' + s + '%, ' + l + '%, ' + this._roundA + ')'; 939 }, 940 toHex: function( allow3Char ) { 941 return rgbToHex( this._r, this._g, this._b, allow3Char ); 942 }, 943 toHexString: function( allow3Char ) { 944 return '#' + this.toHex( allow3Char ); 945 }, 946 toHex8: function( allow4Char ) { 947 return rgbaToHex( this._r, this._g, this._b, this._a, allow4Char ); 948 }, 949 toHex8String: function( allow4Char ) { 950 return '#' + this.toHex8( allow4Char ); 951 }, 952 toRgb: function() { 953 return { r: mathRound( this._r ), g: mathRound( this._g ), b: mathRound( this._b ), a: this._a }; 954 }, 955 toRgbString: function() { 956 return this._a === 1 ? 'rgb(' + mathRound( this._r ) + ', ' + mathRound( this._g ) + ', ' + mathRound( this._b ) + ')' : 'rgba(' + mathRound( this._r ) + ', ' + mathRound( this._g ) + ', ' + mathRound( this._b ) + ', ' + this._roundA + ')'; 957 }, 958 toPercentageRgb: function() { 959 return { 960 r: mathRound( bound01( this._r, 255 ) * 100 ) + '%', 961 g: mathRound( bound01( this._g, 255 ) * 100 ) + '%', 962 b: mathRound( bound01( this._b, 255 ) * 100 ) + '%', 963 a: this._a 964 }; 965 }, 966 toPercentageRgbString: function() { 967 return this._a === 1 ? 'rgb(' + mathRound( bound01( this._r, 255 ) * 100 ) + '%, ' + mathRound( bound01( this._g, 255 ) * 100 ) + '%, ' + mathRound( bound01( this._b, 255 ) * 100 ) + '%)' 968 : 'rgba(' + mathRound( bound01( this._r, 255 ) * 100 ) + '%, ' + mathRound( bound01( this._g, 255 ) * 100 ) + '%, ' + mathRound( bound01( this._b, 255 ) * 100 ) + '%, ' + this._roundA + ')'; 969 }, 970 toName: function() { 971 if ( this._a === 0 ) { 972 return 'transparent'; 973 } 974 975 if ( this._a < 1 ) { 976 return false; 977 } 978 979 return hexNames[ rgbToHex( this._r, this._g, this._b, true ) ] || false; 980 }, 981 toFilter: function( secondColor ) { 982 var hex8String = '#' + rgbaToArgbHex( this._r, this._g, this._b, this._a ); 983 var secondHex8String = hex8String; 984 var gradientType = this._gradientType ? 'GradientType = 1, ' : ''; 985 var s; 986 if ( secondColor ) { 987 s = newTinyColor( secondColor ); 988 secondHex8String = '#' + rgbaToArgbHex( s._r, s._g, s._b, s._a ); 989 } 990 991 return 'progid:DXImageTransform.Microsoft.gradient(' + gradientType + 'startColorstr=' + hex8String + ',endColorstr=' + secondHex8String + ')'; 992 }, 993 toString: function( format ) { 994 var formatSet = !! format; 995 var formattedString; 996 var hasAlpha; 997 var needsAlphaFormat; 998 format = format || this._format; 999 1000 formattedString = false; 1001 hasAlpha = this._a < 1 && this._a >= 0; 1002 needsAlphaFormat = ! formatSet && hasAlpha && ( format === 'hex' || format === 'hex6' || format === 'hex3' || format === 'hex4' || format === 'hex8' || format === 'name' ); 1003 1004 if ( needsAlphaFormat ) { 1005 // Special case for "transparent", all other non-alpha formats 1006 // will return rgba when there is transparency. 1007 if ( format === 'name' && this._a === 0 ) { 1008 return this.toName(); 1009 } 1010 return this.toRgbString(); 1011 } 1012 if ( format === 'rgb' ) { 1013 formattedString = this.toRgbString(); 1014 } 1015 if ( format === 'prgb' ) { 1016 formattedString = this.toPercentageRgbString(); 1017 } 1018 if ( format === 'hex' || format === 'hex6' ) { 1019 formattedString = this.toHexString(); 1020 } 1021 if ( format === 'hex3' ) { 1022 formattedString = this.toHexString( true ); 1023 } 1024 if ( format === 'hex4' ) { 1025 formattedString = this.toHex8String( true ); 1026 } 1027 if ( format === 'hex8' ) { 1028 formattedString = this.toHex8String(); 1029 } 1030 if ( format === 'name' ) { 1031 formattedString = this.toName(); 1032 } 1033 if ( format === 'hsl' ) { 1034 formattedString = this.toHslString(); 1035 } 1036 if ( format === 'hsv' ) { 1037 formattedString = this.toHsvString(); 1038 } 1039 1040 return formattedString || this.toHexString(); 1041 }, 1042 clone: function() { 1043 return newTinyColor( this.toString() ); 1044 }, 1045 1046 _applyModification: function( fn, args ) { 1047 var color = fn.apply( null, [ this ].concat( [].slice.call( args ) ) ); 1048 this._r = color._r; 1049 this._g = color._g; 1050 this._b = color._b; 1051 this.setAlpha( color._a ); 1052 return this; 1053 }, 1054 lighten: function() { 1055 return this._applyModification( lighten, arguments ); 1056 }, 1057 brighten: function() { 1058 return this._applyModification( brighten, arguments ); 1059 }, 1060 darken: function() { 1061 return this._applyModification( darken, arguments ); 1062 }, 1063 desaturate: function() { 1064 return this._applyModification( desaturate, arguments ); 1065 }, 1066 saturate: function() { 1067 return this._applyModification( saturate, arguments ); 1068 }, 1069 greyscale: function() { 1070 return this._applyModification( greyscale, arguments ); 1071 }, 1072 spin: function() { 1073 return this._applyModification( spin, arguments ); 1074 }, 1075 1076 _applyCombination: function( fn, args ) { 1077 return fn.apply( null, [ this ].concat( [].slice.call( args ) ) ); 1078 }, 1079 /*analogous: function () { 1080 return this._applyCombination(analogous, arguments); 1081 },*/ 1082 complement: function() { 1083 return this._applyCombination( complement, arguments ); 1084 }, 1085 /*monochromatic: function () { 1086 return this._applyCombination(monochromatic, arguments); 1087 },*/ 1088 splitcomplement: function() { 1089 return this._applyCombination( splitcomplement, arguments ); 1090 }, 1091 triad: function() { 1092 return this._applyCombination( triad, arguments ); 1093 }, 1094 tetrad: function() { 1095 return this._applyCombination( tetrad, arguments ); 1096 } 1097 }; 1098 1099 // If input is an object, force 1 into "1.0" to handle ratios properly 1100 // String input requires "1.0" as input, so 1 will be treated as 1 1101 TinyColor.fromRatio = function( color, opts ) { 1102 var newColor; 1103 var i; 1104 if ( typeof color === 'object' ) { 1105 newColor = {}; 1106 for ( i in color ) { 1107 if ( Object.prototype.hasOwnProperty.call( color, i ) ) { 1108 if ( i === 'a' ) { 1109 newColor[ i ] = color[ i ]; 1110 } else { 1111 newColor[ i ] = convertToPercentage( color[ i ] ); 1112 } 1113 } 1114 } 1115 color = newColor; 1116 } 1117 1118 return newTinyColor( color, opts ); 1119 }; 1120 1121 // `equals` 1122 // Can be called with any TinyColor input 1123 TinyColor.equals = function( color1, color2 ) { 1124 if ( ! color1 || ! color2 ) { 1125 return false;
1126 } 1127 return newTinyColor( color1 ).toRgbString() === newTinyColor( color2 ).toRgbString(); 1128 }; 1129 1130 TinyColor.random = function() { 1131 return TinyColor.fromRatio( { 1132 r: mathRandom(), 1133 g: mathRandom(), 1134 b: mathRandom() 1135 } ); 1136 }; 1137 1138 // Utility Functions 1139 // --------------------- 1140 1141 TinyColor.mix = function( color1, color2, amount ) { 1142 var rgb1; 1143 var rgb2; 1144 var p; 1145 var rgba; 1146 1147 amount = amount === 0 ? 0 : amount || 50; 1148 1149 rgb1 = newTinyColor( color1 ).toRgb(); 1150 rgb2 = newTinyColor( color2 ).toRgb(); 1151 1152 p = amount / 100; 1153 1154 rgba = { 1155 r: ( ( rgb2.r - rgb1.r ) * p ) + rgb1.r, 1156 g: ( ( rgb2.g - rgb1.g ) * p ) + rgb1.g, 1157 b: ( ( rgb2.b - rgb1.b ) * p ) + rgb1.b, 1158 a: ( ( rgb2.a - rgb1.a ) * p ) + rgb1.a 1159 }; 1160 1161 return newTinyColor( rgba ); 1162 }; 1163 1164 // Readability Functions 1165 // --------------------- 1166 // <http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef (WCAG Version 2) 1167 1168 // `contrast` 1169 // Analyze the 2 colors and returns the color contrast defined by (WCAG Version 2) 1170 TinyColor.readability = function( color1, color2 ) { 1171 var c1 = newTinyColor( color1 ); 1172 var c2 = newTinyColor( color2 ); 1173 return ( Math.max( c1.getLuminance(), c2.getLuminance() ) + 0.05 ) / ( Math.min( c1.getLuminance(), c2.getLuminance() ) + 0.05 ); 1174 }; 1175 1176 // `isReadable` 1177 // Ensure that foreground and background color combinations meet WCAG2 guidelines. 1178 // The third argument is an optional Object. 1179 // the 'level' property states 'AA' or 'AAA' - if missing or invalid, it defaults to 'AA'; 1180 // the 'size' property states 'large' or 'small' - if missing or invalid, it defaults to 'small'. 1181 // If the entire object is absent, isReadable defaults to {level:"AA",size:"small"}. 1182 1183 // *Example* 1184 // TinyColor.isReadable("#000", "#111") => false 1185 // TinyColor.isReadable("#000", "#111",{level:"AA",size:"large"}) => false 1186 TinyColor.isReadable = function( color1, color2, wcag2 ) { 1187 var readability = TinyColor.readability( color1, color2 ); 1188 var wcag2Parms, out; 1189 1190 out = false; 1191 1192 wcag2Parms = validateWCAG2Parms( wcag2 ); 1193 switch ( wcag2Parms.level + wcag2Parms.size ) { 1194 case 'AAsmall': 1195 case 'AAAlarge': 1196 out = readability >= 4.5; 1197 break; 1198 case 'AAlarge': 1199 out = readability >= 3; 1200 break; 1201 case 'AAAsmall': 1202 out = readability >= 7; 1203 break; 1204 } 1205 return out; 1206 }; 1207 1208 // `mostReadable` 1209 // Given a base color and a list of possible foreground or background 1210 // colors for that base, returns the most readable color. 1211 // Optionally returns Black or White if the most readable color is unreadable. 1212 // *Example* 1213 // TinyColor.mostReadable(TinyColor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:false}).toHexString(); // "#112255" 1214 // TinyColor.mostReadable(TinyColor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:true}).toHexString(); // "#ffffff" 1215 // TinyColor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"large"}).toHexString(); // "#faf3f3" 1216 // TinyColor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"small"}).toHexString(); // "#ffffff" 1217 TinyColor.mostReadable = function( baseColor, colorList, args ) { 1218 var bestColor = null; 1219 var bestScore = 0; 1220 var readability; 1221 var includeFallbackColors; 1222 var level; 1223 var size; 1224 var i; 1225 args = args || {}; 1226 includeFallbackColors = args.includeFallbackColors; 1227 level = args.level; 1228 size = args.size; 1229 1230 for ( i = 0; i < colorList.length; i += 1 ) { 1231 readability = TinyColor.readability( baseColor, colorList[ i ] ); 1232 if ( readability > bestScore ) { 1233 bestScore = readability; 1234 bestColor = newTinyColor( colorList[ i ] ); 1235 } 1236 } 1237 1238 if ( TinyColor.isReadable( baseColor, bestColor, { level: level, size: size } ) || ! includeFallbackColors ) { 1239 return bestColor; 1240 } 1241 args.includeFallbackColors = false; 1242 return TinyColor.mostReadable( baseColor, [ '#fff', '#000' ], args ); 1243 }; 1244 1245 // Big List of Colors 1246 // ------------------ 1247 // <http://www.w3.org/TR/css3-color/#svg-color> 1248 TinyColor.names = names; 1249 1250 // Make it easy to access colors via `hexNames[hex]` 1251 TinyColor.hexNames = hexNames; 1252 1253 // Node: Export function 1254 if ( typeof window.module !== 'undefined' && window.module.exports ) { 1255 window.module.exports = TinyColor; 1256 } else if ( typeof window.define === 'function' && window.define.amd ) { // AMD/requirejs: Define the module 1257 window.define( function() { 1258 return TinyColor; 1259 } ); 1260 } else { // Browser: Expose to window 1261 window.tinycolor = TinyColor; 1262 } 1263}( Math ) ); 1264 1265// Spectrum Colorpicker v2.0.10 1266// https://github.com/seballot/spectrum 1267// Author: Brian Grinstead 1268// License: MIT 1269 1270( function( factory ) { 1271 'use strict'; 1272 1273 if ( typeof window.define === 'function' && window.define.amd ) { 1274 // AMD 1275 window.define( [ 'jquery' ], factory ); 1276 } else if ( typeof exports === 'object' && typeof module === 'object' ) { 1277 // CommonJS 1278 window.module.exports = factory( window.require( 'jquery' ) ); 1279 } else { 1280 // Browser 1281 factory( window.jQuery ); 1282 } 1283}( function( $ ) { 1284 'use strict'; 1285 1286 var dataID = 'spectrum.id'; 1287 var tinycolor = window.tinycolor; 1288 var defaultOpts = { 1289 // Callbacks 1290 beforeShow: noop, 1291 move: noop, 1292 change: noop, 1293 show: noop, 1294 hide: noop, 1295 1296 // Options 1297 color: false, 1298 flat: false, // Deprecated - use type instead 1299 type: 'color', // text, color, component or flat 1300 showInput: false, 1301 allowEmpty: false, 1302 showButtons: true, 1303 clickoutFiresChange: true, 1304 showInitial: false, 1305 showPalette: false, 1306 showPaletteOnly: false, 1307 hideAfterPaletteSelect: false, 1308 togglePaletteOnly: false, 1309 showSelectionPalette: true, 1310 localStorageKey: false, 1311 appendTo: 'body', 1312 maxSelectionSize: 8, 1313 locale: 'en', 1314 cancelText: 'cancel', 1315 chooseText: 'choose', 1316 togglePaletteMoreText: 'more', 1317 togglePaletteLessText: 'less',
1318 clearText: 'Clear Color Selection', 1319 preferredFormat: 'hex', 1320 className: '', // Deprecated - use containerClassName and replacerClassName instead. 1321 containerClassName: '', 1322 replacerClassName: '', 1323 showAlpha: false, 1324 theme: 'epo', 1325 palette: [ 1326 [ '#000000', '#444444', '#5b5b5b', '#999999', '#bcbcbc', '#eeeeee', '#f3f6f4', '#ffffff' ], 1327 [ '#f44336', '#744700', '#ce7e00', '#8fce00', '#2986cc', '#16537e', '#6a329f', '#c90076' ], 1328 [ '#f4cccc', '#fce5cd', '#fff2cc', '#d9ead3', '#d0e0e3', '#cfe2f3', '#d9d2e9', '#ead1dc' ], 1329 [ '#ea9999', '#f9cb9c', '#ffe599', '#b6d7a8', '#a2c4c9', '#9fc5e8', '#b4a7d6', '#d5a6bd' ], 1330 [ '#e06666', '#f6b26b', '#ffd966', '#93c47d', '#76a5af', '#6fa8dc', '#8e7cc3', '#c27ba0' ], 1331 [ '#cc0000', '#e69138', '#f1c232', '#6aa84f', '#45818e', '#3d85c6', '#674ea7', '#a64d79' ], 1332 [ '#990000', '#b45f06', '#bf9000', '#38761d', '#134f5c', '#0b5394', '#351c75', '#741b47' ], 1333 [ '#660000', '#783f04', '#7f6000', '#274e13', '#0c343d', '#073763', '#20124d', '#4c1130' ] 1334 ], 1335 selectionPalette: [], 1336 disabled: false, 1337 offset: null 1338 }, 1339 spectrums = [], 1340 IE = !! /msie/i.exec( window.navigator.userAgent ), 1341 rgbaSupport = ( function() { 1342 var contains = function( str, substr ) { 1343 return ( '' + str ).indexOf( substr ) !== 1; 1344 }; 1345 var elem = document.createElement( 'div' ); 1346 var style = elem.style; 1347 style.cssText = 'background-color:rgba(0,0,0,.5)'; 1348 return contains( style.backgroundColor, 'rgba' ) || contains( style.backgroundColor, 'hsla' ); 1349 }() ), 1350 replaceInput = [ 1351 '<button type="button" class="sp-replacer">', 1352 '<span class="sp-preview"><span class="sp-preview-inner"></span></span>', 1353 '<span class="sp-dd">▼</span>', 1354 '</button>' 1355 ].join( '' ), 1356 markup = ( function() { 1357 var i; 1358 // IE does not support gradients with multiple stops, so we need to simulate 1359 // that for the rainbow slider with 8 divs that each have a single gradient 1360 var gradientFix = ''; 1361 if ( IE ) { 1362 for ( i = 1; i <= 6; i++ ) { 1363 gradientFix += "<div class='sp-" + i + "'></div>"; 1364 } 1365 } 1366 1367 return [ 1368 "<div class='sp-container sp-hidden'>", 1369 "<div class='sp-palette-container'>", 1370 "<div class='sp-palette sp-thumb sp-cf'></div>", 1371 "<div class='sp-palette-button-container sp-cf'>", 1372 "<button type='button' class='sp-palette-toggle'></button>", 1373 '</div>', 1374 '</div>', 1375 "<div class='sp-picker-container'>", 1376 "<div class='sp-top sp-cf'>", 1377 "<div class='sp-fill'></div>", 1378 "<div class='sp-top-inner'>", 1379 "<div class='sp-color'>", 1380 "<div class='sp-sat'>", 1381 "<div class='sp-val'>", 1382 "<div class='sp-dragger' tabindex='0'></div>", 1383 '</div>', 1384 '</div>', 1385 '</div>', 1386 "<div class='sp-clear sp-clear-display'>", 1387 '</div>', 1388 "<div class='sp-hue'>", 1389 "<div class='sp-slider' tabindex='0'></div>", 1390 gradientFix, 1391 '</div>', 1392 '</div>', 1393 "<div class='sp-alpha'><div class='sp-alpha-inner'><div class='sp-alpha-handle' tabindex='0'></div></div></div>", 1394 '</div>', 1395 "<div class='sp-input-container sp-cf'>", 1396 "<input class='sp-input' type='text' spellcheck='false'>", 1397 '</div>', 1398 "<div class='sp-initial sp-thumb sp-cf'></div>", 1399 "<div class='sp-button-container sp-cf'>", 1400 "<button type='button' class='sp-cancel'></button>", 1401 "<button type='button' class='sp-choose'></button>", 1402 '</div>', 1403 '</div>', 1404 '</div>' 1405 ].join( '' ); 1406 }() ); 1407 1408 function paletteTemplate( p, color, className, opts ) { 1409 var html = []; 1410 var i; 1411 var current; 1412 var tiny; 1413 var c; 1414 var formattedString; 1415 var swatchStyle; 1416 for ( i = 0; i < p.length; i++ ) { 1417 current = p[ i ]; 1418 if ( current ) { 1419 tiny = tinycolor( current ); 1420 c = tiny.toHsl().l < 0.5 ? 'sp-thumb-el sp-thumb-dark' : 'sp-thumb-el sp-thumb-light'; 1421 c += tinycolor.equals( color, current ) ? ' sp-thumb-active' : ''; 1422 formattedString = tiny.toString( opts.preferredFormat || 'rgb' ); 1423 swatchStyle = rgbaSupport ? 'background-color:' + tiny.toRgbString() : 'filter:' + tiny.toFilter(); 1424 html.push( '<span title="' + formattedString + '" data-color="' + tiny.toRgbString() + '" class="' + c + '" role="button" tabindex="0"><span class="sp-thumb-inner" style="' + swatchStyle + ';"></span></span>' ); 1425 } else { 1426 html.push( '<span class="sp-thumb-el sp-clear-display" role="button" tabindex="0"><span class="sp-clear-palette-only" style="background-color: transparent;"></span></span>' ); 1427 } 1428 } 1429 return "<div class='sp-cf " + className + "'>" + html.join( '' ) + '</div>'; 1430 } 1431 1432 function hideAll() { 1433 var i; 1434 for ( i = 0; i < spectrums.length; i++ ) { 1435 if ( spectrums[ i ] ) { 1436 spectrums[ i ].hide(); 1437 } 1438 } 1439 } 1440 1441 function instanceOptions( o, callbackContext ) { 1442 var opts; 1443 o.locale = o.locale || window.navigator.language; 1444 if ( o.locale ) { 1445 o.locale = o.locale.split( '-' )[ 0 ].toLowerCase(); 1446 } // handle locale like "fr-FR" 1447 if ( o.locale !== 'en' && $.spectrum.localization[ o.locale ] ) { 1448 o = $.extend( {}, $.spectrum.localization[ o.locale ], o ); 1449 } 1450 opts = $.extend( {}, defaultOpts, o ); 1451 1452 opts.callbacks = { 1453 move: bind( opts.move, callbackContext ), 1454 change: bind( opts.change, callbackContext ), 1455 show: bind( opts.show, callbackContext ), 1456 hide: bind( opts.hide, callbackContext ), 1457 beforeShow: bind( opts.beforeShow, callbackContext ) 1458 }; 1459 1460 return opts; 1461 } 1462 1463 function spectrum( element, o ) { 1464 var spect; 1465 1466 var opts = instanceOptions( o, element ), 1467 type = opts.type, 1468 flat = type === 'flat', 1469 showSelectionPalette = opts.showSelectionPalette, 1470 localStorageKey = opts.localStorageKey, 1471 theme = opts.theme, 1472 callbacks = opts.callbacks, 1473 resize = throttle( reflow, 10 ), 1474 visible = false, 1475 isDragging = false, 1476 dragWidth = 0, 1477 dragHeight = 0,
1478 dragHelperHeight = 0, 1479 slideHeight = 0, 1480 alphaWidth = 0, 1481 alphaSlideHelperWidth = 0, 1482 slideHelperHeight = 0, 1483 currentHue = 0, 1484 currentSaturation = 0, 1485 currentValue = 0, 1486 currentAlpha = 1, 1487 palette = [], 1488 paletteArray = [], 1489 paletteLookup = {}, 1490 selectionPalette = opts.selectionPalette.slice( 0 ), 1491 maxSelectionSize = opts.maxSelectionSize, 1492 draggingClass = 'sp-dragging', 1493 abortNextInputChange = false, 1494 shiftMovementDirection = null; 1495 1496 var doc = element.ownerDocument, 1497 boundElement = $( element ), 1498 disabled = false, 1499 container = $( markup, doc ).addClass( theme ), 1500 pickerContainer = container.find( '.sp-picker-container' ), 1501 dragger = container.find( '.sp-color' ), 1502 dragHelper = container.find( '.sp-dragger' ), 1503 slider = container.find( '.sp-hue' ), 1504 slideHelper = container.find( '.sp-slider' ), 1505 alphaSliderInner = container.find( '.sp-alpha-inner' ), 1506 alphaSlider = container.find( '.sp-alpha' ), 1507 alphaSlideHelper = container.find( '.sp-alpha-handle' ), 1508 textInput = container.find( '.sp-input' ), 1509 paletteContainer = container.find( '.sp-palette' ), 1510 initialColorContainer = container.find( '.sp-initial' ), 1511 cancelButton = container.find( '.sp-cancel' ), 1512 clearButton = container.find( '.sp-clear' ), 1513 chooseButton = container.find( '.sp-choose' ), 1514 toggleButton = container.find( '.sp-palette-toggle' ), 1515 isInput = boundElement.is( 'input' ), 1516 shouldReplace = isInput && type === 'color', 1517 replacer = shouldReplace ? $( replaceInput ).addClass( theme ).addClass( opts.className ).addClass( opts.replacerClassName ) : $( [] ), 1518 offsetElement = shouldReplace ? replacer : boundElement, 1519 previewElement = replacer.find( '.sp-preview-inner' ), 1520 initialColor = opts.color || ( isInput && boundElement.val() ), 1521 colorOnShow = false, 1522 currentPreferredFormat = opts.preferredFormat, 1523 clickoutFiresChange = ! opts.showButtons || opts.clickoutFiresChange, 1524 isEmpty = ! initialColor, 1525 allowEmpty = opts.allowEmpty; 1526 1527 // Element to be updated with the input color. Populated in initialize method 1528 var originalInputContainer = null, 1529 colorizeElement = null, 1530 colorizeElementInitialColor = null, 1531 colorizeElementInitialBackground = null; 1532 1533 //If there is a label for this element, when clicked on, show the colour picker 1534 var thisId = boundElement.attr( 'id' ); 1535 var label; 1536 1537 if ( thisId !== undefined && thisId.length > 0 ) { 1538 label = $( 'label[for="' + thisId + '"]' ); 1539 if ( label.length ) { 1540 label.on( 'click', function( e ) { 1541 e.preventDefault(); 1542 boundElement.spectrum( 'show' ); 1543 return false; 1544 } ); 1545 } 1546 } 1547 1548 function applyOptions() { 1549 var i; 1550 var j; 1551 var rgb; 1552 1553 if ( opts.showPaletteOnly ) { 1554 opts.showPalette = true; 1555 } 1556 1557 toggleButton.text( opts.showPaletteOnly ? opts.togglePaletteMoreText : opts.togglePaletteLessText ); 1558 1559 if ( opts.palette ) { 1560 palette = opts.palette.slice( 0 ); 1561 paletteArray = Array.isArray( palette[ 0 ] ) ? palette : [ palette ]; 1562 paletteLookup = {}; 1563 for ( i = 0; i < paletteArray.length; i++ ) { 1564 for ( j = 0; j < paletteArray[ i ].length; j++ ) { 1565 rgb = tinycolor( paletteArray[ i ][ j ] ).toRgbString(); 1566 paletteLookup[ rgb ] = true; 1567 } 1568 } 1569 1570 // if showPaletteOnly and didn't set initialcolor 1571 // set initialcolor to first palette 1572 if ( opts.showPaletteOnly && ! initialColor ) { 1573 initialColor = palette[ 0 ][ 0 ] === '' ? palette[ 0 ][ 0 ] : Object.keys( paletteLookup )[ 0 ]; 1574 } 1575 } 1576 1577 container.toggleClass( 'sp-flat', flat ); 1578 container.toggleClass( 'sp-input-disabled', ! opts.showInput ); 1579 container.toggleClass( 'sp-alpha-enabled', opts.showAlpha ); 1580 container.toggleClass( 'sp-clear-enabled', allowEmpty ); 1581 container.toggleClass( 'sp-buttons-disabled', ! opts.showButtons ); 1582 container.toggleClass( 'sp-palette-buttons-disabled', ! opts.togglePaletteOnly ); 1583 container.toggleClass( 'sp-palette-disabled', ! opts.showPalette ); 1584 container.toggleClass( 'sp-palette-only', opts.showPaletteOnly ); 1585 container.toggleClass( 'sp-initial-disabled', ! opts.showInitial );
vendor: 4,842 bytes, lines 1586-1752
1586 container.addClass( opts.className ).addClass( opts.containerClassName ); 1587 1588 reflow(); 1589 } 1590 1591 function initialize() { 1592 var addOn; 1593 var appendTo; 1594 var paletteEvent; 1595 1596 if ( IE ) { 1597 container.find( '*:not(input)' ).attr( 'unselectable', 'on' ); 1598 } 1599 1600 applyOptions(); 1601 1602 originalInputContainer = $( '<span class="sp-original-input-container"></span>' ); 1603 [ 'margin' ].forEach( function( cssProp ) { 1604 originalInputContainer.css( cssProp, boundElement.css( cssProp ) ); 1605 } ); 1606 // inline-flex by default, switching to flex if needed 1607 if ( boundElement.css( 'display' ) === 'block' ) { 1608 originalInputContainer.css( 'display', 'flex' ); 1609 } 1610 1611 if ( shouldReplace ) { 1612 boundElement.after( replacer ).hide(); 1613 } else if ( type === 'text' ) { 1614 originalInputContainer.addClass( 'sp-colorize-container' ); 1615 boundElement.addClass( 'spectrum sp-colorize' ).wrap( originalInputContainer ); 1616 } else if ( type === 'component' ) { 1617 boundElement.addClass( 'spectrum' ).wrap( originalInputContainer ); 1618 addOn = $( [ "<div class='sp-colorize-container sp-add-on'>", "<div class='sp-colorize'></div> ", '</div>' ].join( '' ) ); 1619 addOn 1620 .width( boundElement.outerHeight() + 'px' ) 1621 .css( 'border-radius', boundElement.css( 'border-radius' ) ) 1622 .css( 'border', boundElement.css( 'border' ) ); 1623 boundElement.addClass( 'with-add-on' ).before( addOn ); 1624 } 1625 1626 colorizeElement = boundElement.parent().find( '.sp-colorize' ); 1627 colorizeElementInitialColor = colorizeElement.css( 'color' ); 1628 colorizeElementInitialBackground = colorizeElement.css( 'background-color' ); 1629 1630 if ( ! allowEmpty ) { 1631 clearButton.hide(); 1632 } 1633 1634 if ( flat ) { 1635 boundElement.after( container ).hide(); 1636 } else { 1637 appendTo = opts.appendTo === 'parent' ? boundElement.parent() : $( opts.appendTo ); 1638 if ( appendTo.length !== 1 ) { 1639 appendTo = $( 'body' ); 1640 } 1641 1642 appendTo.append( container ); 1643 } 1644 1645 updateSelectionPaletteFromStorage(); 1646 1647 offsetElement.on( 'click.spectrum touchstart.spectrum', function( e ) { 1648 if ( ! disabled ) { 1649 show(); 1650 } 1651 1652 e.stopPropagation(); 1653 1654 if ( ! $( e.target ).is( 'input' ) ) { 1655 e.preventDefault(); 1656 } 1657 } ); 1658 1659 if ( boundElement.is( ':disabled' ) || opts.disabled === true ) { 1660 disable(); 1661 } 1662 1663 // Prevent clicks from bubbling up to document. This would cause it to be hidden. 1664 container.on( 'click', stopPropagation ); 1665 1666 container.on( 'keydown', 'div[role="button"]', function( e ) { 1667 if ( e.keyCode === 13 ) { 1668 e.preventDefault(); 1669 $( this ).click(); 1670 } 1671 } ); 1672 1673 // Handle user typed input 1674 [ textInput, boundElement ].forEach( function( input ) { 1675 input.on( 'change', function() { 1676 setFromTextInput( input.val() ); 1677 } ); 1678 input.on( 'paste', function() { 1679 setTimeout( function() { 1680 setFromTextInput( input.val() ); 1681 }, 1 ); 1682 } ); 1683 input.on( 'keydown', function( e ) { 1684 if ( e.keyCode === 13 ) { 1685 setFromTextInput( $( input ).val() ); 1686 // eslint-disable-next-line eqeqeq 1687 if ( input == boundElement ) { 1688 hide(); 1689 } 1690 } 1691 } ); 1692 } ); 1693 1694 cancelButton.text( opts.cancelText ); 1695 cancelButton.on( 'click.spectrum', function( e ) { 1696 e.stopPropagation(); 1697 e.preventDefault(); 1698 revert(); 1699 hide(); 1700 } ); 1701 1702 clearButton.attr( 'title', opts.clearText ); 1703 clearButton.on( 'click.spectrum', function( e ) { 1704 e.stopPropagation(); 1705 e.preventDefault(); 1706 isEmpty = true; 1707 move(); 1708 1709 if ( flat ) { 1710 //for the flat style, this is a change event 1711 updateOriginalInput( true ); 1712 } 1713 } ); 1714 1715 chooseButton.text( opts.chooseText ); 1716 chooseButton.on( 'click.spectrum', function( e ) { 1717 e.stopPropagation(); 1718 e.preventDefault(); 1719 1720 if ( IE && textInput.is( ':focus' ) ) { 1721 textInput.trigger( 'change' ); 1722 } 1723 1724 if ( isValid() ) { 1725 updateOriginalInput( true ); 1726 hide(); 1727 } 1728 } ); 1729 1730 toggleButton.text( opts.showPaletteOnly ? opts.togglePaletteMoreText : opts.togglePaletteLessText ); 1731 toggleButton.on( 'click.spectrum', function( e ) { 1732 e.stopPropagation(); 1733 e.preventDefault(); 1734 1735 opts.showPaletteOnly = ! opts.showPaletteOnly; 1736 1737 // To make sure the Picker area is drawn on the right, next to the 1738 // Palette area (and not below the palette), first move the Palette 1739 // to the left to make space for the picker, plus 5px extra. 1740 // The 'applyOptions' function puts the whole container back into place 1741 // and takes care of the button-text and the sp-palette-only CSS class. 1742 if ( ! opts.showPaletteOnly && ! flat ) { 1743 container.css( 'left', '-=' + ( pickerContainer.outerWidth( true ) + 5 ) ); 1744 } 1745 applyOptions(); 1746 } ); 1747 1748 draggable( 1749 alphaSlider, 1750 function( dragX, dragY, e ) { 1751 currentAlpha = dragX / alphaWidth; 1752 isEmpty = false;
1753 if ( e.shiftKey ) { 1754 currentAlpha = Math.round( currentAlpha * 10 ) / 10; 1755 } 1756 1757 move(); 1758 }, 1759 dragStart, 1760 dragStop 1761 ); 1762 1763 draggable( 1764 slider, 1765 function( dragX, dragY ) { 1766 currentHue = parseFloat( dragY / slideHeight ); 1767 isEmpty = false; 1768 if ( ! opts.showAlpha ) { 1769 currentAlpha = 1; 1770 } 1771 move(); 1772 }, 1773 dragStart, 1774 dragStop 1775 ); 1776 1777 draggable( 1778 dragger, 1779 function( dragX, dragY, e ) { 1780 var oldDragX; 1781 var oldDragY; 1782 var furtherFromX; 1783 var setSaturation; 1784 var setValue; 1785 // shift+drag should snap the movement to either the x or y axis. 1786 if ( ! e.shiftKey ) { 1787 shiftMovementDirection = null; 1788 } else if ( ! shiftMovementDirection ) { 1789 oldDragX = currentSaturation * dragWidth; 1790 oldDragY = dragHeight - ( currentValue * dragHeight ); 1791 furtherFromX = Math.abs( dragX - oldDragX ) > Math.abs( dragY - oldDragY ); 1792 1793 shiftMovementDirection = furtherFromX ? 'x' : 'y'; 1794 } 1795 1796 setSaturation = ! shiftMovementDirection || shiftMovementDirection === 'x'; 1797 setValue = ! shiftMovementDirection || shiftMovementDirection === 'y'; 1798 1799 if ( setSaturation ) { 1800 currentSaturation = parseFloat( dragX / dragWidth ); 1801 } 1802 if ( setValue ) { 1803 currentValue = parseFloat( ( dragHeight - dragY ) / dragHeight ); 1804 } 1805 1806 isEmpty = false; 1807 if ( ! opts.showAlpha ) { 1808 currentAlpha = 1; 1809 } 1810 1811 move(); 1812 }, 1813 dragStart, 1814 dragStop 1815 ); 1816 1817 if ( initialColor !== false && initialColor !== '' ) { 1818 set( initialColor ); 1819 1820 // In case color was black - update the preview UI and set the format 1821 // since the set function will not run (default color is black). 1822 updateUI(); 1823 currentPreferredFormat = tinycolor( initialColor ).format || opts.preferredFormat; 1824 addColorToSelectionPalette( initialColor ); 1825 } else if ( initialColor === '' ) { 1826 set( initialColor ); 1827 updateUI(); 1828 } else { 1829 updateUI(); 1830 } 1831 1832 if ( flat ) { 1833 show(); 1834 } 1835 1836 function paletteElementClick( e ) { 1837 if ( e.data && e.data.ignore ) { 1838 set( $( e.target ).closest( '.sp-thumb-el' ).data( 'color' ) ); 1839 move(); 1840 } else { 1841 set( $( e.target ).closest( '.sp-thumb-el' ).data( 'color' ) ); 1842 move(); 1843 1844 // If the picker is going to close immediately, a palette selection 1845 // is a change. Otherwise, it's a move only. 1846 if ( opts.hideAfterPaletteSelect ) { 1847 updateOriginalInput( true ); 1848 hide(); 1849 } else { 1850 updateOriginalInput(); 1851 } 1852 } 1853 1854 return false; 1855 } 1856 1857 paletteEvent = IE ? 'mousedown.spectrum' : 'click.spectrum touchstart.spectrum'; 1858 paletteContainer.on( paletteEvent, '.sp-thumb-el', paletteElementClick ); 1859 initialColorContainer.on( paletteEvent, '.sp-thumb-el:nth-child(1)', { ignore: true }, paletteElementClick ); 1860 } 1861 1862 function updateSelectionPaletteFromStorage() { 1863 var localStorage; 1864 var oldPalette; 1865 1866 if ( localStorageKey ) { 1867 // Migrate old palettes over to new format. May want to remove this eventually. 1868 try { 1869 localStorage = window.localStorage; 1870 oldPalette = localStorage[ localStorageKey ].split( ',#' ); 1871 if ( oldPalette.length > 1 ) { 1872 delete localStorage[ localStorageKey ]; 1873 $.each( oldPalette, function( i, c ) { 1874 addColorToSelectionPalette( c ); 1875 } ); 1876 } 1877 } catch ( e ) { 1878 window.console.log( e ); 1879 } 1880 1881 try { 1882 selectionPalette = window.localStorage[ localStorageKey ].split( ';' ); 1883 } catch ( e ) { 1884 window.console.log( e ); 1885 } 1886 } 1887 } 1888 1889 function addColorToSelectionPalette( color ) { 1890 var rgb; 1891 if ( showSelectionPalette ) { 1892 rgb = tinycolor( color ).toRgbString(); 1893 if ( ! paletteLookup[ rgb ] && $.inArray( rgb, selectionPalette ) === -1 ) { 1894 selectionPalette.push( rgb ); 1895 while ( selectionPalette.length > maxSelectionSize ) { 1896 selectionPalette.shift(); 1897 } 1898 } 1899 1900 if ( localStorageKey ) { 1901 try { 1902 window.localStorage[ localStorageKey ] = selectionPalette.join( ';' ); 1903 } catch ( e ) { 1904 window.console.log( e ); 1905 } 1906 } 1907 } 1908 } 1909 1910 function getUniqueSelectionPalette() { 1911 var unique = []; 1912 var i; 1913 var rgb; 1914 if ( opts.showPalette ) { 1915 for ( i = 0; i < selectionPalette.length; i++ ) { 1916 rgb = tinycolor( selectionPalette[ i ] ).toRgbString(); 1917 1918 if ( ! paletteLookup[ rgb ] ) { 1919 unique.push( selectionPalette[ i ] ); 1920 } 1921 } 1922 } 1923 1924 return unique.reverse().slice( 0, opts.maxSelectionSize ); 1925 } 1926 1927 function drawPalette() { 1928 var currentColor = get(); 1929 1930 var html = $.map( paletteArray, function( thispalette, i ) { 1931 return paletteTemplate( thispalette, currentColor, 'sp-palette-row sp-palette-row-' + i, opts ); 1932 } ); 1933 1934 updateSelectionPaletteFromStorage(); 1935 1936 if ( selectionPalette ) { 1937 html.push( paletteTemplate( getUniqueSelectionPalette(), currentColor, 'sp-palette-row sp-palette-row-selection', opts ) ); 1938 } 1939 1940 paletteContainer.html( html.join( '' ) ); 1941 } 1942 1943 function drawInitial() { 1944 var initial; 1945 var current; 1946 if ( opts.showInitial ) { 1947 initial = colorOnShow; 1948 current = get(); 1949 initialColorContainer.html( paletteTemplate( [ initial, current ], current, 'sp-palette-row-initial', opts ) ); 1950 } 1951 } 1952 1953 function dragStart() { 1954 if ( dragHeight <= 0 || dragWidth <= 0 || slideHeight <= 0 ) { 1955 reflow(); 1956 } 1957 isDragging = true; 1958 container.addClass( draggingClass ); 1959 shiftMovementDirection = null; 1960 boundElement.trigger( 'dragstart.spectrum', [ get() ] ); 1961 } 1962 1963 function dragStop() { 1964 isDragging = false;
vendor: 5,558 bytes, lines 1965-2199
1965 container.removeClass( draggingClass ); 1966 boundElement.trigger( 'dragstop.spectrum', [ get() ] ); 1967 } 1968 1969 function setFromTextInput( value ) { 1970 var tiny; 1971 if ( abortNextInputChange ) { 1972 abortNextInputChange = false; 1973 return; 1974 } 1975 if ( ( value === null || value === '' ) && allowEmpty ) { 1976 set( null ); 1977 move(); 1978 updateOriginalInput(); 1979 } else { 1980 tiny = tinycolor( value ); 1981 if ( tiny.isValid() ) { 1982 set( tiny ); 1983 move(); 1984 updateOriginalInput(); 1985 } else { 1986 textInput.addClass( 'sp-validation-error' ); 1987 } 1988 } 1989 } 1990 1991 function toggle() { 1992 if ( visible ) { 1993 hide(); 1994 } else { 1995 show(); 1996 } 1997 } 1998 1999 function show() { 2000 // debugger; 2001 var event = $.Event( 'beforeShow.spectrum' ); 2002 2003 if ( visible ) { 2004 reflow(); 2005 return; 2006 } 2007 2008 boundElement.trigger( event, [ get() ] ); 2009 2010 if ( callbacks.beforeShow( get() ) === false || event.isDefaultPrevented() ) { 2011 return; 2012 } 2013 2014 hideAll(); 2015 visible = true; 2016 2017 $( doc ).on( 'keydown.spectrum', onkeydown ); 2018 $( doc ).on( 'click.spectrum', clickout ); 2019 $( window ).on( 'resize.spectrum', resize ); 2020 replacer.attr( 'aria-expanded', true ); 2021 replacer.addClass( 'sp-active' ); 2022 container.removeClass( 'sp-hidden' ); 2023 2024 reflow(); 2025 updateUI(); 2026 2027 colorOnShow = get(); 2028 2029 drawInitial(); 2030 callbacks.show( colorOnShow ); 2031 boundElement.trigger( 'show.spectrum', [ colorOnShow ] ); 2032 } 2033 2034 function onkeydown( e ) { 2035 // Close on ESC 2036 if ( e.keyCode === 27 ) { 2037 hide(); 2038 } 2039 } 2040 2041 function clickout( e ) { 2042 // Return on right click. 2043 if ( e.button === 2 ) { 2044 return; 2045 } 2046 2047 // If a drag event was happening during the mouseup, don't hide 2048 // on click. 2049 if ( isDragging ) { 2050 return; 2051 } 2052 2053 if ( clickoutFiresChange ) { 2054 updateOriginalInput( true ); 2055 } else { 2056 revert(); 2057 } 2058 hide(); 2059 } 2060 2061 function hide() { 2062 // Return if hiding is unnecessary 2063 if ( ! visible || flat ) { 2064 return; 2065 } 2066 visible = false; 2067 2068 $( doc ).off( 'keydown.spectrum', onkeydown ); 2069 $( doc ).off( 'click.spectrum', clickout ); 2070 $( window ).off( 'resize.spectrum', resize ); 2071 2072 replacer.attr( 'aria-expanded', false ); 2073 replacer.removeClass( 'sp-active' ); 2074 container.addClass( 'sp-hidden' ); 2075 2076 callbacks.hide( get() ); 2077 boundElement.trigger( 'hide.spectrum', [ get() ] ); 2078 } 2079 2080 function revert() { 2081 set( colorOnShow, true ); 2082 updateOriginalInput( true ); 2083 } 2084 2085 function set( color, ignoreFormatChange ) { 2086 var newColor, newHsv; 2087 if ( tinycolor.equals( color, get() ) ) { 2088 // Update UI just in case a validation error needs 2089 // to be cleared. 2090 updateUI(); 2091 return; 2092 } 2093 2094 if ( ( ! color || color === undefined ) && allowEmpty ) { 2095 isEmpty = true; 2096 } else { 2097 isEmpty = false; 2098 newColor = tinycolor( color ); 2099 newHsv = newColor.toHsv(); 2100 2101 currentHue = ( newHsv.h % 360 ) / 360; 2102 currentSaturation = newHsv.s; 2103 currentValue = newHsv.v; 2104 currentAlpha = newHsv.a; 2105 } 2106 updateUI(); 2107 2108 if ( newColor && newColor.isValid() && ! ignoreFormatChange ) { 2109 currentPreferredFormat = opts.preferredFormat || newColor.getFormat(); 2110 } 2111 } 2112 2113 function get( thisopts ) { 2114 thisopts = thisopts || {}; 2115 2116 if ( allowEmpty && isEmpty ) { 2117 return null; 2118 } 2119 2120 return tinycolor.fromRatio( 2121 { 2122 h: currentHue, 2123 s: currentSaturation, 2124 v: currentValue, 2125 a: Math.round( currentAlpha * 1000 ) / 1000 2126 }, 2127 { format: thisopts.format || currentPreferredFormat } 2128 ); 2129 } 2130 2131 function isValid() { 2132 return ! textInput.hasClass( 'sp-validation-error' ); 2133 } 2134 2135 function move() { 2136 updateUI(); 2137 2138 callbacks.move( get() ); 2139 boundElement.trigger( 'move.spectrum', [ get() ] ); 2140 } 2141 2142 function updateUI() { 2143 var flatColor; 2144 var format; 2145 var realColor; 2146 var displayColor; 2147 var realHex; 2148 var realRgb; 2149 var rgb; 2150 var realAlpha; 2151 var gradient; 2152 var color; 2153 var textColor; 2154 2155 textInput.removeClass( 'sp-validation-error' ); 2156 2157 updateHelperLocations(); 2158 2159 // Update dragger background color (gradients take care of saturation and value). 2160 flatColor = tinycolor.fromRatio( { h: currentHue, s: 1, v: 1 } ); 2161 dragger.css( 'background-color', flatColor.toHexString() ); 2162 2163 // Get a format that alpha will be included in (hex and names ignore alpha) 2164 format = currentPreferredFormat; 2165 if ( currentAlpha < 1 && ! ( currentAlpha === 0 && format === 'name' ) ) { 2166 if ( format === 'hex' || format === 'hex3' || format === 'hex6' || format === 'name' ) { 2167 format = 'rgb'; 2168 } 2169 } 2170 2171 realColor = get( { format: format } ); 2172 displayColor = ''; 2173 2174 //reset background info for preview element 2175 previewElement.removeClass( 'sp-clear-display' ); 2176 previewElement.css( 'background-color', 'transparent' ); 2177 2178 if ( ! realColor && allowEmpty ) { 2179 // Update the replaced elements background with icon indicating no color selection 2180 previewElement.addClass( 'sp-clear-display' ); 2181 } else { 2182 realHex = realColor.toHexString(); 2183 realRgb = realColor.toRgbString(); 2184 2185 // Update the replaced elements background color (with actual selected color) 2186 if ( rgbaSupport || realColor.alpha === 1 ) { 2187 previewElement.css( 'background-color', realRgb ); 2188 } else { 2189 previewElement.css( 'background-color', 'transparent' ); 2190 previewElement.css( 'filter', realColor.toFilter() ); 2191 } 2192 2193 if ( opts.showAlpha ) { 2194 rgb = realColor.toRgb(); 2195 rgb.a = 0; 2196 realAlpha = tinycolor( rgb ).toRgbString(); 2197 gradient = 'linear-gradient(left, ' + realAlpha + ', ' + realHex + ')'; 2198 2199 if ( IE ) {
2200 alphaSliderInner.css( 'filter', tinycolor( realAlpha ).toFilter( { gradientType: 1 }, realHex ) ); 2201 } else { 2202 alphaSliderInner.css( 'background', '-webkit-' + gradient ); 2203 alphaSliderInner.css( 'background', '-moz-' + gradient ); 2204 alphaSliderInner.css( 'background', '-ms-' + gradient ); 2205 // Use current syntax gradient on unprefixed property. 2206 alphaSliderInner.css( 'background', 'linear-gradient(to right, ' + realAlpha + ', ' + realHex + ')' ); 2207 } 2208 } 2209 2210 displayColor = realColor.toString( format ); 2211 } 2212 2213 // Update the text entry input as it changes happen 2214 if ( opts.showInput ) { 2215 textInput.val( displayColor ); 2216 } 2217 boundElement.val( displayColor ); 2218 if ( opts.type === 'text' || opts.type === 'component' ) { 2219 color = realColor; 2220 if ( color && colorizeElement ) { 2221 textColor = color.isLight() || color.getAlpha() < 0.4 ? 'black' : 'white'; 2222 colorizeElement.css( 'background-color', color.toRgbString() ).css( 'color', textColor ); 2223 } else { 2224 colorizeElement.css( 'background-color', colorizeElementInitialBackground ).css( 'color', colorizeElementInitialColor ); 2225 } 2226 } 2227 2228 if ( opts.showPalette ) { 2229 drawPalette(); 2230 } 2231 2232 drawInitial(); 2233 } 2234 2235 function updateHelperLocations() { 2236 var s = currentSaturation; 2237 var v = currentValue; 2238 var dragX; 2239 var dragY; 2240 var alphaX; 2241 var slideY; 2242 2243 if ( allowEmpty && isEmpty ) { 2244 //if selected color is empty, hide the helpers 2245 alphaSlideHelper.hide(); 2246 slideHelper.hide(); 2247 dragHelper.hide(); 2248 } else { 2249 //make sure helpers are visible 2250 alphaSlideHelper.show(); 2251 slideHelper.show(); 2252 dragHelper.show(); 2253 2254 // Where to show the little circle in that displays your current selected color 2255 dragX = s * dragWidth; 2256 dragY = dragHeight - ( v * dragHeight ); 2257 dragX = Math.max( -dragHelperHeight, Math.min( dragWidth - dragHelperHeight, dragX - dragHelperHeight ) ); 2258 dragY = Math.max( -dragHelperHeight, Math.min( dragHeight - dragHelperHeight, dragY - dragHelperHeight ) ); 2259 dragHelper.css( { 2260 top: dragY + 'px', 2261 left: dragX + 'px' 2262 } ); 2263 2264 alphaX = currentAlpha * alphaWidth; 2265 alphaSlideHelper.css( { 2266 left: alphaX - ( alphaSlideHelperWidth / 2 ) + 'px' 2267 } ); 2268 2269 // Where to show the bar that displays your current selected hue 2270 slideY = currentHue * slideHeight; 2271 slideHelper.css( { 2272 top: slideY - slideHelperHeight + 'px' 2273 } ); 2274 } 2275 } 2276 2277 function updateOriginalInput( fireCallback ) { 2278 var color = get(), 2279 hasChanged = ! tinycolor.equals( color, colorOnShow ); 2280 2281 if ( color ) { 2282 // Update the selection palette with the current color 2283 addColorToSelectionPalette( color ); 2284 } 2285 2286 if ( fireCallback && hasChanged ) { 2287 callbacks.change( color ); 2288 // we trigger the change event or input, but the input change event is also binded 2289 // to some spectrum processing, that we do no need 2290 abortNextInputChange = true; 2291 boundElement.trigger( 'change', [ color ] ); 2292 } 2293 } 2294 2295 function reflow() { 2296 if ( ! visible ) { 2297 return; // Calculations would be useless and wouldn't be reliable anyways 2298 } 2299 dragWidth = dragger.width(); 2300 dragHeight = dragger.height(); 2301 dragHelperHeight = dragHelper.height(); 2302 slideHeight = slider.height(); 2303 slideHelperHeight = slideHelper.height(); 2304 alphaWidth = alphaSlider.width(); 2305 alphaSlideHelperWidth = alphaSlideHelper.width(); 2306 2307 if ( ! flat ) { 2308 container.attr( 'aria-haspopup', true ); 2309 container.css( 'position', 'absolute' ); 2310 if ( opts.offset ) { 2311 container.offset( opts.offset ); 2312 } else { 2313 container.offset( getOffset( container, offsetElement ) ); 2314 } 2315 } 2316 2317 updateHelperLocations(); 2318 2319 if ( opts.showPalette ) { 2320 drawPalette(); 2321 } 2322 2323 boundElement.trigger( 'reflow.spectrum' ); 2324 } 2325 2326 function destroy() { 2327 var oInputContainer; 2328 boundElement.show().removeClass( 'spectrum with-add-on sp-colorize' ); 2329 offsetElement.off( 'click.spectrum touchstart.spectrum' ); 2330 container.remove(); 2331 replacer.remove(); 2332 if ( colorizeElement ) { 2333 colorizeElement.css( 'background-color', colorizeElementInitialBackgroun
2333d ).css( 'color', colorizeElementInitialColor ); 2334 } 2335 oInputContainer = boundElement.closest( '.sp-original-input-container' ); 2336 if ( oInputContainer.length > 0 ) { 2337 oInputContainer.after( boundElement ).remove(); 2338 } 2339 spectrums[ spect.id ] = null; 2340 } 2341 2342 function option( optionName, optionValue ) { 2343 if ( optionName === undefined ) { 2344 return $.extend( {}, opts ); 2345 } 2346 if ( optionValue === undefined ) { 2347 return opts[ optionName ]; 2348 } 2349 2350 opts[ optionName ] = optionValue; 2351 2352 if ( optionName === 'preferredFormat' ) { 2353 currentPreferredFormat = opts.preferredFormat; 2354 } 2355 applyOptions(); 2356 } 2357 2358 function enable() { 2359 disabled = false; 2360 boundElement.attr( 'disabled', false ); 2361 offsetElement.removeClass( 'sp-disabled' ); 2362 } 2363 2364 function disable() { 2365 hide(); 2366 disabled = true; 2367 boundElement.attr( 'disabled', true ); 2368 offsetElement.addClass( 'sp-disabled' ); 2369 } 2370 2371 function setOffset( coord ) { 2372 opts.offset = coord; 2373 reflow(); 2374 } 2375 2376 initialize(); 2377 2378 spect = { 2379 show: show, 2380 hide: hide, 2381 toggle: toggle, 2382 reflow: reflow, 2383 option: option, 2384 enable: enable, 2385 disable: disable, 2386 offset: setOffset, 2387 set: function( c ) { 2388 set( c ); 2389 updateOriginalInput(); 2390 }, 2391 get: get, 2392 destroy: destroy, 2393 container: container 2394 }; 2395 2396 spect.id = spectrums.push( spect ) - 1; 2397 2398 return spect; 2399 } 2400 2401 // checkOffset - get the offset below/above and left/right element depending on screen position 2402 // Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js 2403 function getOffset( picker, input ) { 2404 var extraY = 0; 2405 var dpWidth = picker.outerWidth(); 2406 var dpHeight = picker.outerHeight(); 2407 var inputHeight = input.outerHeight(); 2408 var doc = picker[ 0 ].ownerDocument; 2409 var docElem = doc.documentElement; 2410 var viewWidth = docElem.clientWidth + $( doc ).scrollLeft(); 2411 var viewHeight = docElem.clientHeight + $( doc ).scrollTop(); 2412 var offset = input.offset(); 2413 var offsetLeft = offset.left; 2414 var offsetTop = offset.top; 2415 2416 offsetTop += inputHeight; 2417 2418 offsetLeft -= Math.min( offsetLeft, offsetLeft + dpWidth > viewWidth && viewWidth > dpWidth ? Math.abs( offsetLeft + dpWidth - viewWidth ) : 0 ); 2419 2420 offsetTop -= Math.min( offsetTop, offsetTop + dpHeight > viewHeight && viewHeight > dpHeight ? Math.abs( dpHeight + inputHeight - extraY ) : extraY ); 2421 2422 return { 2423 top: offsetTop, 2424 bottom: offset.bottom, 2425 left: offsetLeft, 2426 right: offset.right, 2427 width: offset.width, 2428 height: offset.height 2429 }; 2430 } 2431 2432 // noop - do nothing 2433 function noop() {} 2434 2435 // stopPropagation - makes the code only doing this a little easier to read in line 2436 function stopPropagation( e ) { 2437 e.stopPropagation(); 2438 } 2439 2440 // Create a function bound to a given object 2441 // Thanks to underscore.js 2442 function bind( func, obj ) { 2443 var slice = Array.prototype.slice; 2444 var args = slice.call( arguments, 2 ); 2445 return function() { 2446 return func.apply( obj, args.concat( slice.call( arguments ) ) ); 2447 }; 2448 } 2449 2450 // Lightweight drag helper. Handles containment within the element, so that 2451 // when dragging, the x is within [0,element.width] and y is within [0,element.height] 2452 function draggable( element, onmove, onstart, onstop ) { 2453 var doc = document; 2454 var dragging = false; 2455 var offset = {}; 2456 var maxHeight = 0; 2457 var maxWidth = 0; 2458 var hasTouch = 'ontouchstart' in window; 2459 var duringDragEvents = {}; 2460 2461 onmove = onmove || function() {}; 2462 onstart = onstart || function() {}; 2463 onstop = onstop || function() {}; 2464 2465 duringDragEvents.selectstart = prevent; 2466 duringDragEvents.dragstart = prevent; 2467 duringDragEvents[ 'touchmove mousemove' ] = move; 2468 duringDragEvents[ 'touchend mouseup' ] = stop; 2469 2470 function prevent( e ) { 2471 if ( e.stopPropagation ) { 2472 e.stopPropagation(); 2473 } 2474 if ( e.preventDefault ) { 2475 e.preventDefault(); 2476 } 2477 e.returnValue = false; 2478 } 2479 2480 function move( e ) { 2481 var t0; 2482 var pageX; 2483 var pageY; 2484 var dragX; 2485 var dragY; 2486 if ( dragging ) { 2487 // Mouseup happened outside of window 2488 if ( IE && doc.documentMode < 9 && ! e.button ) { 2489 return stop(); 2490 } 2491 2492 t0 = e.originalEvent && e.originalEvent.touches && e.originalEvent.touches[ 0 ]; 2493 pageX = ( t0 && t0.pageX ) || e.pageX; 2494 pageY = ( t0 && t0.pageY ) || e.pageY; 2495 2496 dragX = Math.max( 0, Math.min( pageX - offset.left, maxWidth ) ); 2497 dragY = Math.max( 0, Math.min( pageY - offset.top, maxHeight ) ); 2498 2499 if ( hasTouch ) { 2500 // Stop scrolling in iOS 2501 prevent( e ); 2502 } 2503 2504 onmove.apply( element, [ dragX, dragY, e ] ); 2505 } 2506 } 2507 2508 function start( e ) { 2509 var rightclick = e.which ? e.which === 3 : e.button === 2; 2510 2511 if ( ! rightclick && ! dragging ) { 2512 if ( onstart.apply( element, arguments ) !== false ) { 2513 dragging = true; 2514 maxHeight = $( element ).height(); 2515 maxWidth = $( element ).width(); 2516 offset = $( element ).offset(); 2517 2518 $( doc ).on( duringDragEvents ); 2519 $( doc.body ).addClass( 'sp-dragging' ); 2520 2521 move( e ); 2522 2523 prevent( e ); 2524 } 2525 } 2526 } 2527 2528 function stop() { 2529 if ( dragging ) { 2530 $( doc ).off( duringDragEvents ); 2531 $( doc.body ).removeClass( 'sp-dragging' ); 2532 2533 // Wait a tick before notifying observers to allow the click event 2534 // to fire in Chrome. 2535 setTimeout( function() { 2536 onstop.apply( element, arguments ); 2537 }, 0 ); 2538 } 2539 dragging = false;
2540 } 2541 2542 $( element ).on( 'touchstart mousedown', start ); 2543 } 2544 2545 function throttle( func, wait, debounce ) { 2546 var timeout; 2547 return function() { 2548 var context = this, 2549 args = arguments; 2550 var throttler = function() { 2551 timeout = null; 2552 func.apply( context, args ); 2553 }; 2554 if ( debounce ) { 2555 clearTimeout( timeout ); 2556 } 2557 if ( debounce || ! timeout ) { 2558 timeout = setTimeout( throttler, wait ); 2559 } 2560 }; 2561 } 2562 2563 function inputTypeColorSupport() { 2564 return $.fn.spectrum.inputTypeColorSupport(); 2565 } 2566 2567 // Define a jQuery plugin 2568 $.fn.spectrum = function( opts ) { 2569 var returnValue; 2570 var args; 2571 var spect; 2572 var method; 2573 2574 if ( typeof opts === 'string' ) { 2575 returnValue = this; 2576 args = Array.prototype.slice.call( arguments, 1 ); 2577 2578 this.each( function() { 2579 spect = spectrums[ $( this ).data( dataID ) ]; 2580 if ( spect ) { 2581 method = spect[ opts ]; 2582 if ( ! method ) { 2583 throw new Error( "Spectrum: no such method: '" + opts + "'" ); 2584 } 2585 2586 if ( opts === 'get' ) { 2587 returnValue = spect.get(); 2588 } else if ( opts === 'container' ) { 2589 returnValue = spect.container; 2590 } else if ( opts === 'option' ) { 2591 returnValue = spect.option.apply( spect, args ); 2592 } else if ( opts === 'destroy' ) { 2593 spect.destroy(); 2594 $( this ).removeData( dataID ); 2595 } else { 2596 method.apply( spect, args ); 2597 } 2598 } 2599 } ); 2600 2601 return returnValue; 2602 } 2603 2604 // Initializing a new instance of spectrum 2605 return this.spectrum( 'destroy' ).each( function() { 2606 var options = $.extend( {}, $( this ).data(), opts ); 2607 var thisspect; 2608 // Infer default type from input params and deprecated options 2609 if ( ! $( this ).is( 'input' ) ) { 2610 options.type = 'noInput'; 2611 } else if ( options.flat || options.type === 'flat' ) { 2612 options.type = 'flat'; 2613 } else if ( $( this ).attr( 'type' ) === 'color' ) { 2614 options.type = 'color'; 2615 } 2616 2617 thisspect = spectrum( this, options ); 2618 $( this ).data( dataID, thisspect.id ); 2619 } ); 2620 }; 2621 2622 $.fn.spectrum.load = true; 2623 $.fn.spectrum.loadOpts = {}; 2624 $.fn.spectrum.draggable = draggable; 2625 $.fn.spectrum.defaults = defaultOpts; 2626 $.fn.spectrum.inputTypeColorSupport = function() { 2627 var colorInput; 2628 if ( typeof inputTypeColorSupport._cachedResult === 'undefined' ) { 2629 colorInput = $( "<input type='color'>" )[ 0 ]; // if color element is supported, value will default to not null 2630 inputTypeColorSupport._cachedResult = colorInput.type === 'color' && colorInput.value !== ''; 2631 } 2632 return inputTypeColorSupport._cachedResult; 2633 }; 2634 2635 $.spectrum = {}; 2636 $.spectrum.localization = {}; 2637 $.spectrum.palettes = {}; 2638 2639 $.fn.spectrum.processNativeColorInputs = function() { 2640 var colorInputs = $( 'input[type=color]' ); 2641 if ( colorInputs.length && ! inputTypeColorSupport() ) { 2642 colorInputs.spectrum( { 2643 preferredFormat: 'hex6' 2644 } ); 2645 } 2646 }; 2647 2648 $( function() { 2649 if ( $.fn.spectrum.load ) { 2650 $.fn.spectrum.processNativeColorInputs(); 2651 } 2652 } ); 2653} ) );
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.