1 | /*! |
---|
2 | * Bootstrap Colorpicker |
---|
3 | * http://mjolnic.github.io/bootstrap-colorpicker/ |
---|
4 | * |
---|
5 | * Originally written by (c) 2012 Stefan Petre |
---|
6 | * Licensed under the Apache License v2.0 |
---|
7 | * http://www.apache.org/licenses/LICENSE-2.0.txt |
---|
8 | * |
---|
9 | * @todo Update DOCS |
---|
10 | */ |
---|
11 | |
---|
12 | (function(factory) { |
---|
13 | "use strict"; |
---|
14 | if (typeof exports === 'object') { |
---|
15 | module.exports = factory(window.jQuery); |
---|
16 | } else if (typeof define === 'function' && define.amd) { |
---|
17 | define(['jquery'], factory); |
---|
18 | } else if (window.jQuery && !window.jQuery.fn.colorpicker) { |
---|
19 | factory(window.jQuery); |
---|
20 | } |
---|
21 | } |
---|
22 | (function($) { |
---|
23 | 'use strict'; |
---|
24 | |
---|
25 | // Color object |
---|
26 | var Color = function(val, customColors) { |
---|
27 | this.value = { |
---|
28 | h: 0, |
---|
29 | s: 0, |
---|
30 | b: 0, |
---|
31 | a: 1 |
---|
32 | }; |
---|
33 | this.origFormat = null; // original string format |
---|
34 | if (customColors) { |
---|
35 | $.extend(this.colors, customColors); |
---|
36 | } |
---|
37 | if (val) { |
---|
38 | if (val.toLowerCase !== undefined) { |
---|
39 | // cast to string |
---|
40 | val = val + ''; |
---|
41 | this.setColor(val); |
---|
42 | } else if (val.h !== undefined) { |
---|
43 | this.value = val; |
---|
44 | } |
---|
45 | } |
---|
46 | }; |
---|
47 | |
---|
48 | Color.prototype = { |
---|
49 | constructor: Color, |
---|
50 | // 140 predefined colors from the HTML Colors spec |
---|
51 | colors: { |
---|
52 | "aliceblue": "#f0f8ff", |
---|
53 | "antiquewhite": "#faebd7", |
---|
54 | "aqua": "#00ffff", |
---|
55 | "aquamarine": "#7fffd4", |
---|
56 | "azure": "#f0ffff", |
---|
57 | "beige": "#f5f5dc", |
---|
58 | "bisque": "#ffe4c4", |
---|
59 | "black": "#000000", |
---|
60 | "blanchedalmond": "#ffebcd", |
---|
61 | "blue": "#0000ff", |
---|
62 | "blueviolet": "#8a2be2", |
---|
63 | "brown": "#a52a2a", |
---|
64 | "burlywood": "#deb887", |
---|
65 | "cadetblue": "#5f9ea0", |
---|
66 | "chartreuse": "#7fff00", |
---|
67 | "chocolate": "#d2691e", |
---|
68 | "coral": "#ff7f50", |
---|
69 | "cornflowerblue": "#6495ed", |
---|
70 | "cornsilk": "#fff8dc", |
---|
71 | "crimson": "#dc143c", |
---|
72 | "cyan": "#00ffff", |
---|
73 | "darkblue": "#00008b", |
---|
74 | "darkcyan": "#008b8b", |
---|
75 | "darkgoldenrod": "#b8860b", |
---|
76 | "darkgray": "#a9a9a9", |
---|
77 | "darkgreen": "#006400", |
---|
78 | "darkkhaki": "#bdb76b", |
---|
79 | "darkmagenta": "#8b008b", |
---|
80 | "darkolivegreen": "#556b2f", |
---|
81 | "darkorange": "#ff8c00", |
---|
82 | "darkorchid": "#9932cc", |
---|
83 | "darkred": "#8b0000", |
---|
84 | "darksalmon": "#e9967a", |
---|
85 | "darkseagreen": "#8fbc8f", |
---|
86 | "darkslateblue": "#483d8b", |
---|
87 | "darkslategray": "#2f4f4f", |
---|
88 | "darkturquoise": "#00ced1", |
---|
89 | "darkviolet": "#9400d3", |
---|
90 | "deeppink": "#ff1493", |
---|
91 | "deepskyblue": "#00bfff", |
---|
92 | "dimgray": "#696969", |
---|
93 | "dodgerblue": "#1e90ff", |
---|
94 | "firebrick": "#b22222", |
---|
95 | "floralwhite": "#fffaf0", |
---|
96 | "forestgreen": "#228b22", |
---|
97 | "fuchsia": "#ff00ff", |
---|
98 | "gainsboro": "#dcdcdc", |
---|
99 | "ghostwhite": "#f8f8ff", |
---|
100 | "gold": "#ffd700", |
---|
101 | "goldenrod": "#daa520", |
---|
102 | "gray": "#808080", |
---|
103 | "green": "#008000", |
---|
104 | "greenyellow": "#adff2f", |
---|
105 | "honeydew": "#f0fff0", |
---|
106 | "hotpink": "#ff69b4", |
---|
107 | "indianred": "#cd5c5c", |
---|
108 | "indigo": "#4b0082", |
---|
109 | "ivory": "#fffff0", |
---|
110 | "khaki": "#f0e68c", |
---|
111 | "lavender": "#e6e6fa", |
---|
112 | "lavenderblush": "#fff0f5", |
---|
113 | "lawngreen": "#7cfc00", |
---|
114 | "lemonchiffon": "#fffacd", |
---|
115 | "lightblue": "#add8e6", |
---|
116 | "lightcoral": "#f08080", |
---|
117 | "lightcyan": "#e0ffff", |
---|
118 | "lightgoldenrodyellow": "#fafad2", |
---|
119 | "lightgrey": "#d3d3d3", |
---|
120 | "lightgreen": "#90ee90", |
---|
121 | "lightpink": "#ffb6c1", |
---|
122 | "lightsalmon": "#ffa07a", |
---|
123 | "lightseagreen": "#20b2aa", |
---|
124 | "lightskyblue": "#87cefa", |
---|
125 | "lightslategray": "#778899", |
---|
126 | "lightsteelblue": "#b0c4de", |
---|
127 | "lightyellow": "#ffffe0", |
---|
128 | "lime": "#00ff00", |
---|
129 | "limegreen": "#32cd32", |
---|
130 | "linen": "#faf0e6", |
---|
131 | "magenta": "#ff00ff", |
---|
132 | "maroon": "#800000", |
---|
133 | "mediumaquamarine": "#66cdaa", |
---|
134 | "mediumblue": "#0000cd", |
---|
135 | "mediumorchid": "#ba55d3", |
---|
136 | "mediumpurple": "#9370d8", |
---|
137 | "mediumseagreen": "#3cb371", |
---|
138 | "mediumslateblue": "#7b68ee", |
---|
139 | "mediumspringgreen": "#00fa9a", |
---|
140 | "mediumturquoise": "#48d1cc", |
---|
141 | "mediumvioletred": "#c71585", |
---|
142 | "midnightblue": "#191970", |
---|
143 | "mintcream": "#f5fffa", |
---|
144 | "mistyrose": "#ffe4e1", |
---|
145 | "moccasin": "#ffe4b5", |
---|
146 | "navajowhite": "#ffdead", |
---|
147 | "navy": "#000080", |
---|
148 | "oldlace": "#fdf5e6", |
---|
149 | "olive": "#808000", |
---|
150 | "olivedrab": "#6b8e23", |
---|
151 | "orange": "#ffa500", |
---|
152 | "orangered": "#ff4500", |
---|
153 | "orchid": "#da70d6", |
---|
154 | "palegoldenrod": "#eee8aa", |
---|
155 | "palegreen": "#98fb98", |
---|
156 | "paleturquoise": "#afeeee", |
---|
157 | "palevioletred": "#d87093", |
---|
158 | "papayawhip": "#ffefd5", |
---|
159 | "peachpuff": "#ffdab9", |
---|
160 | "peru": "#cd853f", |
---|
161 | "pink": "#ffc0cb", |
---|
162 | "plum": "#dda0dd", |
---|
163 | "powderblue": "#b0e0e6", |
---|
164 | "purple": "#800080", |
---|
165 | "red": "#ff0000", |
---|
166 | "rosybrown": "#bc8f8f", |
---|
167 | "royalblue": "#4169e1", |
---|
168 | "saddlebrown": "#8b4513", |
---|
169 | "salmon": "#fa8072", |
---|
170 | "sandybrown": "#f4a460", |
---|
171 | "seagreen": "#2e8b57", |
---|
172 | "seashell": "#fff5ee", |
---|
173 | "sienna": "#a0522d", |
---|
174 | "silver": "#c0c0c0", |
---|
175 | "skyblue": "#87ceeb", |
---|
176 | "slateblue": "#6a5acd", |
---|
177 | "slategray": "#708090", |
---|
178 | "snow": "#fffafa", |
---|
179 | "springgreen": "#00ff7f", |
---|
180 | "steelblue": "#4682b4", |
---|
181 | "tan": "#d2b48c", |
---|
182 | "teal": "#008080", |
---|
183 | "thistle": "#d8bfd8", |
---|
184 | "tomato": "#ff6347", |
---|
185 | "turquoise": "#40e0d0", |
---|
186 | "violet": "#ee82ee", |
---|
187 | "wheat": "#f5deb3", |
---|
188 | "white": "#ffffff", |
---|
189 | "whitesmoke": "#f5f5f5", |
---|
190 | "yellow": "#ffff00", |
---|
191 | "yellowgreen": "#9acd32", |
---|
192 | "transparent": "transparent" |
---|
193 | }, |
---|
194 | _sanitizeNumber: function(val) { |
---|
195 | if (typeof val === 'number') { |
---|
196 | return val; |
---|
197 | } |
---|
198 | if (isNaN(val) || (val === null) || (val === '') || (val === undefined)) { |
---|
199 | return 1; |
---|
200 | } |
---|
201 | if (val.toLowerCase !== undefined) { |
---|
202 | return parseFloat(val); |
---|
203 | } |
---|
204 | return 1; |
---|
205 | }, |
---|
206 | isTransparent: function(strVal) { |
---|
207 | if (!strVal) { |
---|
208 | return false; |
---|
209 | } |
---|
210 | strVal = strVal.toLowerCase().trim(); |
---|
211 | return (strVal === 'transparent') || (strVal.match(/#?00000000/)) || (strVal.match(/(rgba|hsla)\(0,0,0,0?\.?0\)/)); |
---|
212 | }, |
---|
213 | rgbaIsTransparent: function(rgba) { |
---|
214 | return ((rgba.r === 0) && (rgba.g === 0) && (rgba.b === 0) && (rgba.a === 0)); |
---|
215 | }, |
---|
216 | //parse a string to HSB |
---|
217 | setColor: function(strVal) { |
---|
218 | strVal = strVal.toLowerCase().trim(); |
---|
219 | if (strVal) { |
---|
220 | if (this.isTransparent(strVal)) { |
---|
221 | this.value = { |
---|
222 | h: 0, |
---|
223 | s: 0, |
---|
224 | b: 0, |
---|
225 | a: 0 |
---|
226 | }; |
---|
227 | } else { |
---|
228 | this.value = this.stringToHSB(strVal) || { |
---|
229 | h: 0, |
---|
230 | s: 0, |
---|
231 | b: 0, |
---|
232 | a: 1 |
---|
233 | }; // if parser fails, defaults to black |
---|
234 | } |
---|
235 | } |
---|
236 | }, |
---|
237 | stringToHSB: function(strVal) { |
---|
238 | strVal = strVal.toLowerCase(); |
---|
239 | var alias; |
---|
240 | if (typeof this.colors[strVal] !== 'undefined') { |
---|
241 | strVal = this.colors[strVal]; |
---|
242 | alias = 'alias'; |
---|
243 | } |
---|
244 | var that = this, |
---|
245 | result = false; |
---|
246 | $.each(this.stringParsers, function(i, parser) { |
---|
247 | var match = parser.re.exec(strVal), |
---|
248 | values = match && parser.parse.apply(that, [match]), |
---|
249 | format = alias || parser.format || 'rgba'; |
---|
250 | if (values) { |
---|
251 | if (format.match(/hsla?/)) { |
---|
252 | result = that.RGBtoHSB.apply(that, that.HSLtoRGB.apply(that, values)); |
---|
253 | } else { |
---|
254 | result = that.RGBtoHSB.apply(that, values); |
---|
255 | } |
---|
256 | that.origFormat = format; |
---|
257 | return false; |
---|
258 | } |
---|
259 | return true; |
---|
260 | }); |
---|
261 | return result; |
---|
262 | }, |
---|
263 | setHue: function(h) { |
---|
264 | this.value.h = 1 - h; |
---|
265 | }, |
---|
266 | setSaturation: function(s) { |
---|
267 | this.value.s = s; |
---|
268 | }, |
---|
269 | setBrightness: function(b) { |
---|
270 | this.value.b = 1 - b; |
---|
271 | }, |
---|
272 | setAlpha: function(a) { |
---|
273 | this.value.a = parseInt((1 - a) * 100, 10) / 100; |
---|
274 | }, |
---|
275 | toRGB: function(h, s, b, a) { |
---|
276 | if (!h) { |
---|
277 | h = this.value.h; |
---|
278 | s = this.value.s; |
---|
279 | b = this.value.b; |
---|
280 | } |
---|
281 | h *= 360; |
---|
282 | var R, G, B, X, C; |
---|
283 | h = (h % 360) / 60; |
---|
284 | C = b * s; |
---|
285 | X = C * (1 - Math.abs(h % 2 - 1)); |
---|
286 | R = G = B = b - C; |
---|
287 | |
---|
288 | h = ~~h; |
---|
289 | R += [C, X, 0, 0, X, C][h]; |
---|
290 | G += [X, C, C, X, 0, 0][h]; |
---|
291 | B += [0, 0, X, C, C, X][h]; |
---|
292 | return { |
---|
293 | r: Math.round(R * 255), |
---|
294 | g: Math.round(G * 255), |
---|
295 | b: Math.round(B * 255), |
---|
296 | a: a || this.value.a |
---|
297 | }; |
---|
298 | }, |
---|
299 | toHex: function(h, s, b, a) { |
---|
300 | var rgb = this.toRGB(h, s, b, a); |
---|
301 | if (this.rgbaIsTransparent(rgb)) { |
---|
302 | return 'transparent'; |
---|
303 | } |
---|
304 | return '#' + ((1 << 24) | (parseInt(rgb.r) << 16) | (parseInt(rgb.g) << 8) | parseInt(rgb.b)).toString(16).substr(1); |
---|
305 | }, |
---|
306 | toHSL: function(h, s, b, a) { |
---|
307 | h = h || this.value.h; |
---|
308 | s = s || this.value.s; |
---|
309 | b = b || this.value.b; |
---|
310 | a = a || this.value.a; |
---|
311 | |
---|
312 | var H = h, |
---|
313 | L = (2 - s) * b, |
---|
314 | S = s * b; |
---|
315 | if (L > 0 && L <= 1) { |
---|
316 | S /= L; |
---|
317 | } else { |
---|
318 | S /= 2 - L; |
---|
319 | } |
---|
320 | L /= 2; |
---|
321 | if (S > 1) { |
---|
322 | S = 1; |
---|
323 | } |
---|
324 | return { |
---|
325 | h: isNaN(H) ? 0 : H, |
---|
326 | s: isNaN(S) ? 0 : S, |
---|
327 | l: isNaN(L) ? 0 : L, |
---|
328 | a: isNaN(a) ? 0 : a |
---|
329 | }; |
---|
330 | }, |
---|
331 | toAlias: function(r, g, b, a) { |
---|
332 | var rgb = this.toHex(r, g, b, a); |
---|
333 | for (var alias in this.colors) { |
---|
334 | if (this.colors[alias] === rgb) { |
---|
335 | return alias; |
---|
336 | } |
---|
337 | } |
---|
338 | return false; |
---|
339 | }, |
---|
340 | RGBtoHSB: function(r, g, b, a) { |
---|
341 | r /= 255; |
---|
342 | g /= 255; |
---|
343 | b /= 255; |
---|
344 | |
---|
345 | var H, S, V, C; |
---|
346 | V = Math.max(r, g, b); |
---|
347 | C = V - Math.min(r, g, b); |
---|
348 | H = (C === 0 ? null : |
---|
349 | V === r ? (g - b) / C : |
---|
350 | V === g ? (b - r) / C + 2 : |
---|
351 | (r - g) / C + 4 |
---|
352 | ); |
---|
353 | H = ((H + 360) % 6) * 60 / 360; |
---|
354 | S = C === 0 ? 0 : C / V; |
---|
355 | return { |
---|
356 | h: this._sanitizeNumber(H), |
---|
357 | s: S, |
---|
358 | b: V, |
---|
359 | a: this._sanitizeNumber(a) |
---|
360 | }; |
---|
361 | }, |
---|
362 | HueToRGB: function(p, q, h) { |
---|
363 | if (h < 0) { |
---|
364 | h += 1; |
---|
365 | } else if (h > 1) { |
---|
366 | h -= 1; |
---|
367 | } |
---|
368 | if ((h * 6) < 1) { |
---|
369 | return p + (q - p) * h * 6; |
---|
370 | } else if ((h * 2) < 1) { |
---|
371 | return q; |
---|
372 | } else if ((h * 3) < 2) { |
---|
373 | return p + (q - p) * ((2 / 3) - h) * 6; |
---|
374 | } else { |
---|
375 | return p; |
---|
376 | } |
---|
377 | }, |
---|
378 | HSLtoRGB: function(h, s, l, a) { |
---|
379 | if (s < 0) { |
---|
380 | s = 0; |
---|
381 | } |
---|
382 | var q; |
---|
383 | if (l <= 0.5) { |
---|
384 | q = l * (1 + s); |
---|
385 | } else { |
---|
386 | q = l + s - (l * s); |
---|
387 | } |
---|
388 | |
---|
389 | var p = 2 * l - q; |
---|
390 | |
---|
391 | var tr = h + (1 / 3); |
---|
392 | var tg = h; |
---|
393 | var tb = h - (1 / 3); |
---|
394 | |
---|
395 | var r = Math.round(this.HueToRGB(p, q, tr) * 255); |
---|
396 | var g = Math.round(this.HueToRGB(p, q, tg) * 255); |
---|
397 | var b = Math.round(this.HueToRGB(p, q, tb) * 255); |
---|
398 | return [r, g, b, this._sanitizeNumber(a)]; |
---|
399 | }, |
---|
400 | toString: function(format) { |
---|
401 | format = format || 'rgba'; |
---|
402 | var c = false; |
---|
403 | switch (format) { |
---|
404 | case 'rgb': |
---|
405 | { |
---|
406 | c = this.toRGB(); |
---|
407 | if (this.rgbaIsTransparent(c)) { |
---|
408 | return 'transparent'; |
---|
409 | } |
---|
410 | return 'rgb(' + c.r + ',' + c.g + ',' + c.b + ')'; |
---|
411 | } |
---|
412 | break; |
---|
413 | case 'rgba': |
---|
414 | { |
---|
415 | c = this.toRGB(); |
---|
416 | return 'rgba(' + c.r + ',' + c.g + ',' + c.b + ',' + c.a + ')'; |
---|
417 | } |
---|
418 | break; |
---|
419 | case 'hsl': |
---|
420 | { |
---|
421 | c = this.toHSL(); |
---|
422 | return 'hsl(' + Math.round(c.h * 360) + ',' + Math.round(c.s * 100) + '%,' + Math.round(c.l * 100) + '%)'; |
---|
423 | } |
---|
424 | break; |
---|
425 | case 'hsla': |
---|
426 | { |
---|
427 | c = this.toHSL(); |
---|
428 | return 'hsla(' + Math.round(c.h * 360) + ',' + Math.round(c.s * 100) + '%,' + Math.round(c.l * 100) + '%,' + c.a + ')'; |
---|
429 | } |
---|
430 | break; |
---|
431 | case 'hex': |
---|
432 | { |
---|
433 | return this.toHex(); |
---|
434 | } |
---|
435 | break; |
---|
436 | case 'alias': |
---|
437 | return this.toAlias() || this.toHex(); |
---|
438 | default: |
---|
439 | { |
---|
440 | return c; |
---|
441 | } |
---|
442 | break; |
---|
443 | } |
---|
444 | }, |
---|
445 | // a set of RE's that can match strings and generate color tuples. |
---|
446 | // from John Resig color plugin |
---|
447 | // https://github.com/jquery/jquery-color/ |
---|
448 | stringParsers: [{ |
---|
449 | re: /rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*?\)/, |
---|
450 | format: 'rgb', |
---|
451 | parse: function(execResult) { |
---|
452 | return [ |
---|
453 | execResult[1], |
---|
454 | execResult[2], |
---|
455 | execResult[3], |
---|
456 | 1 |
---|
457 | ]; |
---|
458 | } |
---|
459 | }, { |
---|
460 | re: /rgb\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*?\)/, |
---|
461 | format: 'rgb', |
---|
462 | parse: function(execResult) { |
---|
463 | return [ |
---|
464 | 2.55 * execResult[1], |
---|
465 | 2.55 * execResult[2], |
---|
466 | 2.55 * execResult[3], |
---|
467 | 1 |
---|
468 | ]; |
---|
469 | } |
---|
470 | }, { |
---|
471 | re: /rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/, |
---|
472 | format: 'rgba', |
---|
473 | parse: function(execResult) { |
---|
474 | return [ |
---|
475 | execResult[1], |
---|
476 | execResult[2], |
---|
477 | execResult[3], |
---|
478 | execResult[4] |
---|
479 | ]; |
---|
480 | } |
---|
481 | }, { |
---|
482 | re: /rgba\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/, |
---|
483 | format: 'rgba', |
---|
484 | parse: function(execResult) { |
---|
485 | return [ |
---|
486 | 2.55 * execResult[1], |
---|
487 | 2.55 * execResult[2], |
---|
488 | 2.55 * execResult[3], |
---|
489 | execResult[4] |
---|
490 | ]; |
---|
491 | } |
---|
492 | }, { |
---|
493 | re: /hsl\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*?\)/, |
---|
494 | format: 'hsl', |
---|
495 | parse: function(execResult) { |
---|
496 | return [ |
---|
497 | execResult[1] / 360, |
---|
498 | execResult[2] / 100, |
---|
499 | execResult[3] / 100, |
---|
500 | execResult[4] |
---|
501 | ]; |
---|
502 | } |
---|
503 | }, { |
---|
504 | re: /hsla\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/, |
---|
505 | format: 'hsla', |
---|
506 | parse: function(execResult) { |
---|
507 | return [ |
---|
508 | execResult[1] / 360, |
---|
509 | execResult[2] / 100, |
---|
510 | execResult[3] / 100, |
---|
511 | execResult[4] |
---|
512 | ]; |
---|
513 | } |
---|
514 | }, { |
---|
515 | re: /#?([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/, |
---|
516 | format: 'hex', |
---|
517 | parse: function(execResult) { |
---|
518 | return [ |
---|
519 | parseInt(execResult[1], 16), |
---|
520 | parseInt(execResult[2], 16), |
---|
521 | parseInt(execResult[3], 16), |
---|
522 | 1 |
---|
523 | ]; |
---|
524 | } |
---|
525 | }, { |
---|
526 | re: /#?([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/, |
---|
527 | format: 'hex', |
---|
528 | parse: function(execResult) { |
---|
529 | return [ |
---|
530 | parseInt(execResult[1] + execResult[1], 16), |
---|
531 | parseInt(execResult[2] + execResult[2], 16), |
---|
532 | parseInt(execResult[3] + execResult[3], 16), |
---|
533 | 1 |
---|
534 | ]; |
---|
535 | } |
---|
536 | }], |
---|
537 | colorNameToHex: function(name) { |
---|
538 | if (typeof this.colors[name.toLowerCase()] !== 'undefined') { |
---|
539 | return this.colors[name.toLowerCase()]; |
---|
540 | } |
---|
541 | return false; |
---|
542 | } |
---|
543 | }; |
---|
544 | |
---|
545 | |
---|
546 | var defaults = { |
---|
547 | horizontal: false, // horizontal mode layout ? |
---|
548 | inline: false, //forces to show the colorpicker as an inline element |
---|
549 | color: false, //forces a color |
---|
550 | format: false, //forces a format |
---|
551 | input: 'input', // children input selector |
---|
552 | container: false, // container selector |
---|
553 | component: '.add-on, .input-group-addon', // children component selector |
---|
554 | sliders: { |
---|
555 | saturation: { |
---|
556 | maxLeft: 100, |
---|
557 | maxTop: 100, |
---|
558 | callLeft: 'setSaturation', |
---|
559 | callTop: 'setBrightness' |
---|
560 | }, |
---|
561 | hue: { |
---|
562 | maxLeft: 0, |
---|
563 | maxTop: 100, |
---|
564 | callLeft: false, |
---|
565 | callTop: 'setHue' |
---|
566 | }, |
---|
567 | alpha: { |
---|
568 | maxLeft: 0, |
---|
569 | maxTop: 100, |
---|
570 | callLeft: false, |
---|
571 | callTop: 'setAlpha' |
---|
572 | } |
---|
573 | }, |
---|
574 | slidersHorz: { |
---|
575 | saturation: { |
---|
576 | maxLeft: 100, |
---|
577 | maxTop: 100, |
---|
578 | callLeft: 'setSaturation', |
---|
579 | callTop: 'setBrightness' |
---|
580 | }, |
---|
581 | hue: { |
---|
582 | maxLeft: 100, |
---|
583 | maxTop: 0, |
---|
584 | callLeft: 'setHue', |
---|
585 | callTop: false |
---|
586 | }, |
---|
587 | alpha: { |
---|
588 | maxLeft: 100, |
---|
589 | maxTop: 0, |
---|
590 | callLeft: 'setAlpha', |
---|
591 | callTop: false |
---|
592 | } |
---|
593 | }, |
---|
594 | template: '<div class="colorpicker dropdown-menu">' + |
---|
595 | '<div class="colorpicker-saturation"><i><b></b></i></div>' + |
---|
596 | '<div class="colorpicker-hue"><i></i></div>' + |
---|
597 | '<div class="colorpicker-alpha"><i></i></div>' + |
---|
598 | '<div class="colorpicker-color"><div /></div>' + |
---|
599 | '<div class="colorpicker-selectors"></div>' + |
---|
600 | '</div>', |
---|
601 | align: 'right', |
---|
602 | customClass: null, |
---|
603 | colorSelectors: null |
---|
604 | }; |
---|
605 | |
---|
606 | var Colorpicker = function(element, options) { |
---|
607 | this.element = $(element).addClass('colorpicker-element'); |
---|
608 | this.options = $.extend(true, {}, defaults, this.element.data(), options); |
---|
609 | this.component = this.options.component; |
---|
610 | this.component = (this.component !== false) ? this.element.find(this.component) : false; |
---|
611 | if (this.component && (this.component.length === 0)) { |
---|
612 | this.component = false; |
---|
613 | } |
---|
614 | this.container = (this.options.container === true) ? this.element : this.options.container; |
---|
615 | this.container = (this.container !== false) ? $(this.container) : false; |
---|
616 | |
---|
617 | // Is the element an input? Should we search inside for any input? |
---|
618 | this.input = this.element.is('input') ? this.element : (this.options.input ? |
---|
619 | this.element.find(this.options.input) : false); |
---|
620 | if (this.input && (this.input.length === 0)) { |
---|
621 | this.input = false; |
---|
622 | } |
---|
623 | // Set HSB color |
---|
624 | this.color = new Color(this.options.color !== false ? this.options.color : this.getValue(), this.options.colorSelectors); |
---|
625 | this.format = this.options.format !== false ? this.options.format : this.color.origFormat; |
---|
626 | |
---|
627 | // Setup picker |
---|
628 | this.picker = $(this.options.template); |
---|
629 | if (this.options.customClass) { |
---|
630 | this.picker.addClass(this.options.customClass); |
---|
631 | } |
---|
632 | if (this.options.inline) { |
---|
633 | this.picker.addClass('colorpicker-inline colorpicker-visible'); |
---|
634 | } else { |
---|
635 | this.picker.addClass('colorpicker-hidden'); |
---|
636 | } |
---|
637 | if (this.options.horizontal) { |
---|
638 | this.picker.addClass('colorpicker-horizontal'); |
---|
639 | } |
---|
640 | if (this.format === 'rgba' || this.format === 'hsla' || this.options.format === false) { |
---|
641 | this.picker.addClass('colorpicker-with-alpha'); |
---|
642 | } |
---|
643 | if (this.options.align === 'right') { |
---|
644 | this.picker.addClass('colorpicker-right'); |
---|
645 | } |
---|
646 | if (this.options.colorSelectors) { |
---|
647 | var colorpicker = this; |
---|
648 | $.each(this.options.colorSelectors, function(name, color) { |
---|
649 | var $btn = $('<i />').css('background-color', color).data('class', name); |
---|
650 | $btn.click(function() { |
---|
651 | colorpicker.setValue($(this).css('background-color')); |
---|
652 | }); |
---|
653 | colorpicker.picker.find('.colorpicker-selectors').append($btn); |
---|
654 | }); |
---|
655 | this.picker.find('.colorpicker-selectors').show(); |
---|
656 | } |
---|
657 | this.picker.on('mousedown.colorpicker touchstart.colorpicker', $.proxy(this.mousedown, this)); |
---|
658 | this.picker.appendTo(this.container ? this.container : $('body')); |
---|
659 | |
---|
660 | // Bind events |
---|
661 | if (this.input !== false) { |
---|
662 | this.input.on({ |
---|
663 | 'keyup.colorpicker': $.proxy(this.keyup, this) |
---|
664 | }); |
---|
665 | this.input.on({ |
---|
666 | 'change.colorpicker': $.proxy(this.change, this) |
---|
667 | }); |
---|
668 | if (this.component === false) { |
---|
669 | this.element.on({ |
---|
670 | 'focus.colorpicker': $.proxy(this.show, this) |
---|
671 | }); |
---|
672 | } |
---|
673 | if (this.options.inline === false) { |
---|
674 | this.element.on({ |
---|
675 | 'focusout.colorpicker': $.proxy(this.hide, this) |
---|
676 | }); |
---|
677 | } |
---|
678 | } |
---|
679 | |
---|
680 | if (this.component !== false) { |
---|
681 | this.component.on({ |
---|
682 | 'click.colorpicker': $.proxy(this.show, this) |
---|
683 | }); |
---|
684 | } |
---|
685 | |
---|
686 | if ((this.input === false) && (this.component === false)) { |
---|
687 | this.element.on({ |
---|
688 | 'click.colorpicker': $.proxy(this.show, this) |
---|
689 | }); |
---|
690 | } |
---|
691 | |
---|
692 | // for HTML5 input[type='color'] |
---|
693 | if ((this.input !== false) && (this.component !== false) && (this.input.attr('type') === 'color')) { |
---|
694 | |
---|
695 | this.input.on({ |
---|
696 | 'click.colorpicker': $.proxy(this.show, this), |
---|
697 | 'focus.colorpicker': $.proxy(this.show, this) |
---|
698 | }); |
---|
699 | } |
---|
700 | this.update(); |
---|
701 | |
---|
702 | $($.proxy(function() { |
---|
703 | this.element.trigger('create'); |
---|
704 | }, this)); |
---|
705 | }; |
---|
706 | |
---|
707 | Colorpicker.Color = Color; |
---|
708 | |
---|
709 | Colorpicker.prototype = { |
---|
710 | constructor: Colorpicker, |
---|
711 | destroy: function() { |
---|
712 | this.picker.remove(); |
---|
713 | this.element.removeData('colorpicker').off('.colorpicker'); |
---|
714 | if (this.input !== false) { |
---|
715 | this.input.off('.colorpicker'); |
---|
716 | } |
---|
717 | if (this.component !== false) { |
---|
718 | this.component.off('.colorpicker'); |
---|
719 | } |
---|
720 | this.element.removeClass('colorpicker-element'); |
---|
721 | this.element.trigger({ |
---|
722 | type: 'destroy' |
---|
723 | }); |
---|
724 | }, |
---|
725 | reposition: function() { |
---|
726 | if (this.options.inline !== false || this.options.container) { |
---|
727 | return false; |
---|
728 | } |
---|
729 | var type = this.container && this.container[0] !== document.body ? 'position' : 'offset'; |
---|
730 | var element = this.component || this.element; |
---|
731 | var offset = element[type](); |
---|
732 | if (this.options.align === 'right') { |
---|
733 | offset.left -= this.picker.outerWidth() - element.outerWidth(); |
---|
734 | } |
---|
735 | this.picker.css({ |
---|
736 | top: offset.top + element.outerHeight(), |
---|
737 | left: offset.left |
---|
738 | }); |
---|
739 | }, |
---|
740 | show: function(e) { |
---|
741 | if (this.isDisabled()) { |
---|
742 | return false; |
---|
743 | } |
---|
744 | this.picker.addClass('colorpicker-visible').removeClass('colorpicker-hidden'); |
---|
745 | this.reposition(); |
---|
746 | $(window).on('resize.colorpicker', $.proxy(this.reposition, this)); |
---|
747 | if (e && (!this.hasInput() || this.input.attr('type') === 'color')) { |
---|
748 | if (e.stopPropagation && e.preventDefault) { |
---|
749 | e.stopPropagation(); |
---|
750 | e.preventDefault(); |
---|
751 | } |
---|
752 | } |
---|
753 | if (this.options.inline === false) { |
---|
754 | $(window.document).on({ |
---|
755 | 'mousedown.colorpicker': $.proxy(this.hide, this) |
---|
756 | }); |
---|
757 | } |
---|
758 | this.element.trigger({ |
---|
759 | type: 'showPicker', |
---|
760 | color: this.color |
---|
761 | }); |
---|
762 | }, |
---|
763 | hide: function() { |
---|
764 | this.picker.addClass('colorpicker-hidden').removeClass('colorpicker-visible'); |
---|
765 | $(window).off('resize.colorpicker', this.reposition); |
---|
766 | $(document).off({ |
---|
767 | 'mousedown.colorpicker': this.hide |
---|
768 | }); |
---|
769 | this.update(); |
---|
770 | this.element.trigger({ |
---|
771 | type: 'hidePicker', |
---|
772 | color: this.color |
---|
773 | }); |
---|
774 | }, |
---|
775 | updateData: function(val) { |
---|
776 | val = val || this.color.toString(this.format); |
---|
777 | this.element.data('color', val); |
---|
778 | return val; |
---|
779 | }, |
---|
780 | updateInput: function(val) { |
---|
781 | val = val || this.color.toString(this.format); |
---|
782 | if (this.input !== false) { |
---|
783 | if (this.options.colorSelectors) { |
---|
784 | var color = new Color(val, this.options.colorSelectors); |
---|
785 | var alias = color.toAlias(); |
---|
786 | if (typeof this.options.colorSelectors[alias] !== 'undefined') { |
---|
787 | val = alias; |
---|
788 | } |
---|
789 | } |
---|
790 | this.input.prop('value', val); |
---|
791 | } |
---|
792 | return val; |
---|
793 | }, |
---|
794 | updatePicker: function(val) { |
---|
795 | if (val !== undefined) { |
---|
796 | this.color = new Color(val, this.options.colorSelectors); |
---|
797 | } |
---|
798 | var sl = (this.options.horizontal === false) ? this.options.sliders : this.options.slidersHorz; |
---|
799 | var icns = this.picker.find('i'); |
---|
800 | if (icns.length === 0) { |
---|
801 | return; |
---|
802 | } |
---|
803 | if (this.options.horizontal === false) { |
---|
804 | sl = this.options.sliders; |
---|
805 | icns.eq(1).css('top', sl.hue.maxTop * (1 - this.color.value.h)).end() |
---|
806 | .eq(2).css('top', sl.alpha.maxTop * (1 - this.color.value.a)); |
---|
807 | } else { |
---|
808 | sl = this.options.slidersHorz; |
---|
809 | icns.eq(1).css('left', sl.hue.maxLeft * (1 - this.color.value.h)).end() |
---|
810 | .eq(2).css('left', sl.alpha.maxLeft * (1 - this.color.value.a)); |
---|
811 | } |
---|
812 | icns.eq(0).css({ |
---|
813 | 'top': sl.saturation.maxTop - this.color.value.b * sl.saturation.maxTop, |
---|
814 | 'left': this.color.value.s * sl.saturation.maxLeft |
---|
815 | }); |
---|
816 | this.picker.find('.colorpicker-saturation').css('backgroundColor', this.color.toHex(this.color.value.h, 1, 1, 1)); |
---|
817 | this.picker.find('.colorpicker-alpha').css('backgroundColor', this.color.toHex()); |
---|
818 | this.picker.find('.colorpicker-color, .colorpicker-color div').css('backgroundColor', this.color.toString(this.format)); |
---|
819 | return val; |
---|
820 | }, |
---|
821 | updateComponent: function(val) { |
---|
822 | val = val || this.color.toString(this.format); |
---|
823 | if (this.component !== false) { |
---|
824 | var icn = this.component.find('i').eq(0); |
---|
825 | if (icn.length > 0) { |
---|
826 | icn.css({ |
---|
827 | 'backgroundColor': val |
---|
828 | }); |
---|
829 | } else { |
---|
830 | this.component.css({ |
---|
831 | 'backgroundColor': val |
---|
832 | }); |
---|
833 | } |
---|
834 | } |
---|
835 | return val; |
---|
836 | }, |
---|
837 | update: function(force) { |
---|
838 | var val; |
---|
839 | if ((this.getValue(false) !== false) || (force === true)) { |
---|
840 | // Update input/data only if the current value is not empty |
---|
841 | val = this.updateComponent(); |
---|
842 | this.updateInput(val); |
---|
843 | this.updateData(val); |
---|
844 | this.updatePicker(); // only update picker if value is not empty |
---|
845 | } |
---|
846 | return val; |
---|
847 | |
---|
848 | }, |
---|
849 | setValue: function(val) { // set color manually |
---|
850 | this.color = new Color(val, this.options.colorSelectors); |
---|
851 | this.update(true); |
---|
852 | this.element.trigger({ |
---|
853 | type: 'changeColor', |
---|
854 | color: this.color, |
---|
855 | value: val |
---|
856 | }); |
---|
857 | }, |
---|
858 | getValue: function(defaultValue) { |
---|
859 | defaultValue = (defaultValue === undefined) ? '#000000' : defaultValue; |
---|
860 | var val; |
---|
861 | if (this.hasInput()) { |
---|
862 | val = this.input.val(); |
---|
863 | } else { |
---|
864 | val = this.element.data('color'); |
---|
865 | } |
---|
866 | if ((val === undefined) || (val === '') || (val === null)) { |
---|
867 | // if not defined or empty, return default |
---|
868 | val = defaultValue; |
---|
869 | } |
---|
870 | return val; |
---|
871 | }, |
---|
872 | hasInput: function() { |
---|
873 | return (this.input !== false); |
---|
874 | }, |
---|
875 | isDisabled: function() { |
---|
876 | if (this.hasInput()) { |
---|
877 | return (this.input.prop('disabled') === true); |
---|
878 | } |
---|
879 | return false; |
---|
880 | }, |
---|
881 | disable: function() { |
---|
882 | if (this.hasInput()) { |
---|
883 | this.input.prop('disabled', true); |
---|
884 | this.element.trigger({ |
---|
885 | type: 'disable', |
---|
886 | color: this.color, |
---|
887 | value: this.getValue() |
---|
888 | }); |
---|
889 | return true; |
---|
890 | } |
---|
891 | return false; |
---|
892 | }, |
---|
893 | enable: function() { |
---|
894 | if (this.hasInput()) { |
---|
895 | this.input.prop('disabled', false); |
---|
896 | this.element.trigger({ |
---|
897 | type: 'enable', |
---|
898 | color: this.color, |
---|
899 | value: this.getValue() |
---|
900 | }); |
---|
901 | return true; |
---|
902 | } |
---|
903 | return false; |
---|
904 | }, |
---|
905 | currentSlider: null, |
---|
906 | mousePointer: { |
---|
907 | left: 0, |
---|
908 | top: 0 |
---|
909 | }, |
---|
910 | mousedown: function(e) { |
---|
911 | if (!e.pageX && !e.pageY && e.originalEvent) { |
---|
912 | e.pageX = e.originalEvent.touches[0].pageX; |
---|
913 | e.pageY = e.originalEvent.touches[0].pageY; |
---|
914 | } |
---|
915 | e.stopPropagation(); |
---|
916 | e.preventDefault(); |
---|
917 | |
---|
918 | var target = $(e.target); |
---|
919 | |
---|
920 | //detect the slider and set the limits and callbacks |
---|
921 | var zone = target.closest('div'); |
---|
922 | var sl = this.options.horizontal ? this.options.slidersHorz : this.options.sliders; |
---|
923 | if (!zone.is('.colorpicker')) { |
---|
924 | if (zone.is('.colorpicker-saturation')) { |
---|
925 | this.currentSlider = $.extend({}, sl.saturation); |
---|
926 | } else if (zone.is('.colorpicker-hue')) { |
---|
927 | this.currentSlider = $.extend({}, sl.hue); |
---|
928 | } else if (zone.is('.colorpicker-alpha')) { |
---|
929 | this.currentSlider = $.extend({}, sl.alpha); |
---|
930 | } else { |
---|
931 | return false; |
---|
932 | } |
---|
933 | var offset = zone.offset(); |
---|
934 | //reference to guide's style |
---|
935 | this.currentSlider.guide = zone.find('i')[0].style; |
---|
936 | this.currentSlider.left = e.pageX - offset.left; |
---|
937 | this.currentSlider.top = e.pageY - offset.top; |
---|
938 | this.mousePointer = { |
---|
939 | left: e.pageX, |
---|
940 | top: e.pageY |
---|
941 | }; |
---|
942 | //trigger mousemove to move the guide to the current position |
---|
943 | $(document).on({ |
---|
944 | 'mousemove.colorpicker': $.proxy(this.mousemove, this), |
---|
945 | 'touchmove.colorpicker': $.proxy(this.mousemove, this), |
---|
946 | 'mouseup.colorpicker': $.proxy(this.mouseup, this), |
---|
947 | 'touchend.colorpicker': $.proxy(this.mouseup, this) |
---|
948 | }).trigger('mousemove'); |
---|
949 | } |
---|
950 | return false; |
---|
951 | }, |
---|
952 | mousemove: function(e) { |
---|
953 | if (!e.pageX && !e.pageY && e.originalEvent) { |
---|
954 | e.pageX = e.originalEvent.touches[0].pageX; |
---|
955 | e.pageY = e.originalEvent.touches[0].pageY; |
---|
956 | } |
---|
957 | e.stopPropagation(); |
---|
958 | e.preventDefault(); |
---|
959 | var left = Math.max( |
---|
960 | 0, |
---|
961 | Math.min( |
---|
962 | this.currentSlider.maxLeft, |
---|
963 | this.currentSlider.left + ((e.pageX || this.mousePointer.left) - this.mousePointer.left) |
---|
964 | ) |
---|
965 | ); |
---|
966 | var top = Math.max( |
---|
967 | 0, |
---|
968 | Math.min( |
---|
969 | this.currentSlider.maxTop, |
---|
970 | this.currentSlider.top + ((e.pageY || this.mousePointer.top) - this.mousePointer.top) |
---|
971 | ) |
---|
972 | ); |
---|
973 | this.currentSlider.guide.left = left + 'px'; |
---|
974 | this.currentSlider.guide.top = top + 'px'; |
---|
975 | if (this.currentSlider.callLeft) { |
---|
976 | this.color[this.currentSlider.callLeft].call(this.color, left / this.currentSlider.maxLeft); |
---|
977 | } |
---|
978 | if (this.currentSlider.callTop) { |
---|
979 | this.color[this.currentSlider.callTop].call(this.color, top / this.currentSlider.maxTop); |
---|
980 | } |
---|
981 | // Change format dynamically |
---|
982 | // Only occurs if user choose the dynamic format by |
---|
983 | // setting option format to false |
---|
984 | if (this.currentSlider.callTop === 'setAlpha' && this.options.format === false) { |
---|
985 | |
---|
986 | // Converting from hex / rgb to rgba |
---|
987 | if (this.color.value.a !== 1) { |
---|
988 | this.format = 'rgba'; |
---|
989 | this.color.origFormat = 'rgba'; |
---|
990 | } |
---|
991 | |
---|
992 | // Converting from rgba to hex |
---|
993 | else { |
---|
994 | this.format = 'hex'; |
---|
995 | this.color.origFormat = 'hex'; |
---|
996 | } |
---|
997 | } |
---|
998 | this.update(true); |
---|
999 | |
---|
1000 | this.element.trigger({ |
---|
1001 | type: 'changeColor', |
---|
1002 | color: this.color |
---|
1003 | }); |
---|
1004 | return false; |
---|
1005 | }, |
---|
1006 | mouseup: function(e) { |
---|
1007 | e.stopPropagation(); |
---|
1008 | e.preventDefault(); |
---|
1009 | $(document).off({ |
---|
1010 | 'mousemove.colorpicker': this.mousemove, |
---|
1011 | 'touchmove.colorpicker': this.mousemove, |
---|
1012 | 'mouseup.colorpicker': this.mouseup, |
---|
1013 | 'touchend.colorpicker': this.mouseup |
---|
1014 | }); |
---|
1015 | return false; |
---|
1016 | }, |
---|
1017 | change: function(e) { |
---|
1018 | this.keyup(e); |
---|
1019 | }, |
---|
1020 | keyup: function(e) { |
---|
1021 | if ((e.keyCode === 38)) { |
---|
1022 | if (this.color.value.a < 1) { |
---|
1023 | this.color.value.a = Math.round((this.color.value.a + 0.01) * 100) / 100; |
---|
1024 | } |
---|
1025 | this.update(true); |
---|
1026 | } else if ((e.keyCode === 40)) { |
---|
1027 | if (this.color.value.a > 0) { |
---|
1028 | this.color.value.a = Math.round((this.color.value.a - 0.01) * 100) / 100; |
---|
1029 | } |
---|
1030 | this.update(true); |
---|
1031 | } else { |
---|
1032 | this.color = new Color(this.input.val(), this.options.colorSelectors); |
---|
1033 | // Change format dynamically |
---|
1034 | // Only occurs if user choose the dynamic format by |
---|
1035 | // setting option format to false |
---|
1036 | if (this.color.origFormat && this.options.format === false) { |
---|
1037 | this.format = this.color.origFormat; |
---|
1038 | } |
---|
1039 | if (this.getValue(false) !== false) { |
---|
1040 | this.updateData(); |
---|
1041 | this.updateComponent(); |
---|
1042 | this.updatePicker(); |
---|
1043 | } |
---|
1044 | } |
---|
1045 | this.element.trigger({ |
---|
1046 | type: 'changeColor', |
---|
1047 | color: this.color, |
---|
1048 | value: this.input.val() |
---|
1049 | }); |
---|
1050 | } |
---|
1051 | }; |
---|
1052 | |
---|
1053 | $.colorpicker = Colorpicker; |
---|
1054 | |
---|
1055 | $.fn.colorpicker = function(option) { |
---|
1056 | var pickerArgs = arguments, |
---|
1057 | rv; |
---|
1058 | |
---|
1059 | var $returnValue = this.each(function() { |
---|
1060 | var $this = $(this), |
---|
1061 | inst = $this.data('colorpicker'), |
---|
1062 | options = ((typeof option === 'object') ? option : {}); |
---|
1063 | if ((!inst) && (typeof option !== 'string')) { |
---|
1064 | $this.data('colorpicker', new Colorpicker(this, options)); |
---|
1065 | } else { |
---|
1066 | if (typeof option === 'string') { |
---|
1067 | rv = inst[option].apply(inst, Array.prototype.slice.call(pickerArgs, 1)); |
---|
1068 | } |
---|
1069 | } |
---|
1070 | }); |
---|
1071 | if (option === 'getValue') { |
---|
1072 | return rv; |
---|
1073 | } |
---|
1074 | return $returnValue; |
---|
1075 | }; |
---|
1076 | |
---|
1077 | $.fn.colorpicker.constructor = Colorpicker; |
---|
1078 | |
---|
1079 | })); |
---|