PageSourceSearch

https://www.backsplash.com/wp-content/plugins/woocommerce-tm-extra…/assets/js/spectrum.js?ver=2.0

js backsplash.com collected 2026-09-25 23:41:03 UTC 76,088 bytes, 2,653 lines download raw bytes

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">&#9660;</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.