spectrum-rails 1.3.1 → 1.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  module Spectrum
2
2
  module Rails
3
- VERSION = "1.3.1"
3
+ VERSION = "1.3.4"
4
4
  end
5
5
  end
@@ -1,115 +1,120 @@
1
- // Spectrum Colorpicker v1.3.1
1
+ // Spectrum Colorpicker v1.3.4
2
2
  // https://github.com/bgrins/spectrum
3
3
  // Author: Brian Grinstead
4
4
  // License: MIT
5
5
 
6
6
  (function (window, $, undefined) {
7
+ "use strict";
8
+
7
9
  var defaultOpts = {
8
10
 
9
- // Callbacks
10
- beforeShow: noop,
11
- move: noop,
12
- change: noop,
13
- show: noop,
14
- hide: noop,
15
-
16
- // Options
17
- color: false,
18
- flat: false,
19
- showInput: false,
20
- allowEmpty: false,
21
- showButtons: true,
22
- clickoutFiresChange: false,
23
- showInitial: false,
24
- showPalette: false,
25
- showPaletteOnly: false,
26
- showSelectionPalette: true,
27
- localStorageKey: false,
28
- appendTo: "body",
29
- maxSelectionSize: 7,
30
- cancelText: "cancel",
31
- chooseText: "choose",
32
- clearText: "Clear Color Selection",
33
- preferredFormat: false,
34
- className: "",
35
- showAlpha: false,
36
- theme: "sp-light",
37
- palette: ['fff', '000'],
38
- selectionPalette: [],
39
- disabled: false
40
- },
41
- spectrums = [],
42
- IE = !!/msie/i.exec( window.navigator.userAgent ),
43
- rgbaSupport = (function() {
44
- function contains( str, substr ) {
45
- return !!~('' + str).indexOf(substr);
46
- }
47
-
48
- var elem = document.createElement('div');
49
- var style = elem.style;
50
- style.cssText = 'background-color:rgba(0,0,0,.5)';
51
- return contains(style.backgroundColor, 'rgba') || contains(style.backgroundColor, 'hsla');
52
- })(),
53
- inputTypeColorSupport = (function() {
54
- var colorInput = $("<input type='color' value='!' />")[0];
55
- return colorInput.type === "color" && colorInput.value !== "!";
56
- })(),
57
- replaceInput = [
58
- "<div class='sp-replacer'>",
11
+ // Callbacks
12
+ beforeShow: noop,
13
+ move: noop,
14
+ change: noop,
15
+ show: noop,
16
+ hide: noop,
17
+
18
+ // Options
19
+ color: false,
20
+ flat: false,
21
+ showInput: false,
22
+ allowEmpty: false,
23
+ showButtons: true,
24
+ clickoutFiresChange: false,
25
+ showInitial: false,
26
+ showPalette: false,
27
+ showPaletteOnly: false,
28
+ showSelectionPalette: true,
29
+ localStorageKey: false,
30
+ appendTo: "body",
31
+ maxSelectionSize: 7,
32
+ cancelText: "cancel",
33
+ chooseText: "choose",
34
+ clearText: "Clear Color Selection",
35
+ noColorSelectedText: "No Color Selected",
36
+ preferredFormat: false,
37
+ className: "", // Deprecated - use containerClassName and replacerClassName instead.
38
+ containerClassName: "",
39
+ replacerClassName: "",
40
+ showAlpha: false,
41
+ theme: "sp-light",
42
+ palette: [["#ffffff", "#000000", "#ff0000", "#ff8000", "#ffff00", "#008000", "#0000ff", "#4b0082", "#9400d3"]],
43
+ selectionPalette: [],
44
+ disabled: false
45
+ },
46
+ spectrums = [],
47
+ IE = !!/msie/i.exec( window.navigator.userAgent ),
48
+ rgbaSupport = (function() {
49
+ function contains( str, substr ) {
50
+ return !!~('' + str).indexOf(substr);
51
+ }
52
+
53
+ var elem = document.createElement('div');
54
+ var style = elem.style;
55
+ style.cssText = 'background-color:rgba(0,0,0,.5)';
56
+ return contains(style.backgroundColor, 'rgba') || contains(style.backgroundColor, 'hsla');
57
+ })(),
58
+ inputTypeColorSupport = (function() {
59
+ var colorInput = $("<input type='color' value='!' />")[0];
60
+ return colorInput.type === "color" && colorInput.value !== "!";
61
+ })(),
62
+ replaceInput = [
63
+ "<div class='sp-replacer'>",
59
64
  "<div class='sp-preview'><div class='sp-preview-inner'></div></div>",
60
65
  "<div class='sp-dd'>&#9660;</div>",
61
- "</div>"
62
- ].join(''),
63
- markup = (function () {
66
+ "</div>"
67
+ ].join(''),
68
+ markup = (function () {
64
69
 
65
- // IE does not support gradients with multiple stops, so we need to simulate
66
- // that for the rainbow slider with 8 divs that each have a single gradient
67
- var gradientFix = "";
68
- if (IE) {
69
- for (var i = 1; i <= 6; i++) {
70
- gradientFix += "<div class='sp-" + i + "'></div>";
71
- }
70
+ // IE does not support gradients with multiple stops, so we need to simulate
71
+ // that for the rainbow slider with 8 divs that each have a single gradient
72
+ var gradientFix = "";
73
+ if (IE) {
74
+ for (var i = 1; i <= 6; i++) {
75
+ gradientFix += "<div class='sp-" + i + "'></div>";
72
76
  }
77
+ }
73
78
 
74
- return [
75
- "<div class='sp-container sp-hidden'>",
79
+ return [
80
+ "<div class='sp-container sp-hidden'>",
76
81
  "<div class='sp-palette-container'>",
77
- "<div class='sp-palette sp-thumb sp-cf'></div>",
82
+ "<div class='sp-palette sp-thumb sp-cf'></div>",
78
83
  "</div>",
79
84
  "<div class='sp-picker-container'>",
80
- "<div class='sp-top sp-cf'>",
81
- "<div class='sp-fill'></div>",
82
- "<div class='sp-top-inner'>",
83
- "<div class='sp-color'>",
84
- "<div class='sp-sat'>",
85
- "<div class='sp-val'>",
86
- "<div class='sp-dragger'></div>",
87
- "</div>",
88
- "</div>",
85
+ "<div class='sp-top sp-cf'>",
86
+ "<div class='sp-fill'></div>",
87
+ "<div class='sp-top-inner'>",
88
+ "<div class='sp-color'>",
89
+ "<div class='sp-sat'>",
90
+ "<div class='sp-val'>",
91
+ "<div class='sp-dragger'></div>",
92
+ "</div>",
93
+ "</div>",
94
+ "</div>",
95
+ "<div class='sp-clear sp-clear-display'>",
96
+ "</div>",
97
+ "<div class='sp-hue'>",
98
+ "<div class='sp-slider'></div>",
99
+ gradientFix,
100
+ "</div>",
101
+ "</div>",
102
+ "<div class='sp-alpha'><div class='sp-alpha-inner'><div class='sp-alpha-handle'></div></div></div>",
103
+ "</div>",
104
+ "<div class='sp-input-container sp-cf'>",
105
+ "<input class='sp-input' type='text' spellcheck='false' />",
106
+ "</div>",
107
+ "<div class='sp-initial sp-thumb sp-cf'></div>",
108
+ "<div class='sp-button-container sp-cf'>",
109
+ "<a class='sp-cancel' href='#'></a>",
110
+ "<button type='button' class='sp-choose'></button>",
111
+ "</div>",
89
112
  "</div>",
90
- "<div class='sp-clear sp-clear-display'>",
91
- "</div>",
92
- "<div class='sp-hue'>",
93
- "<div class='sp-slider'></div>",
94
- gradientFix,
95
- "</div>",
96
- "</div>",
97
- "<div class='sp-alpha'><div class='sp-alpha-inner'><div class='sp-alpha-handle'></div></div></div>",
98
- "</div>",
99
- "<div class='sp-input-container sp-cf'>",
100
- "<input class='sp-input' type='text' spellcheck='false' />",
101
- "</div>",
102
- "<div class='sp-initial sp-thumb sp-cf'></div>",
103
- "<div class='sp-button-container sp-cf'>",
104
- "<a class='sp-cancel' href='#'></a>",
105
- "<button class='sp-choose'></button>",
106
- "</div>",
107
- "</div>",
108
- "</div>"
109
- ].join("");
110
- })();
113
+ "</div>"
114
+ ].join("");
115
+ })();
111
116
 
112
- function paletteTemplate (p, color, className) {
117
+ function paletteTemplate (p, color, className, opts) {
113
118
  var html = [];
114
119
  for (var i = 0; i < p.length; i++) {
115
120
  var current = p[i];
@@ -117,12 +122,17 @@
117
122
  var tiny = tinycolor(current);
118
123
  var c = tiny.toHsl().l < 0.5 ? "sp-thumb-el sp-thumb-dark" : "sp-thumb-el sp-thumb-light";
119
124
  c += (tinycolor.equals(color, current)) ? " sp-thumb-active" : "";
120
-
125
+ var formattedString = tiny.toString(opts.preferredFormat || "rgb");
121
126
  var swatchStyle = rgbaSupport ? ("background-color:" + tiny.toRgbString()) : "filter:" + tiny.toFilter();
122
- html.push('<span title="' + tiny.toRgbString() + '" data-color="' + tiny.toRgbString() + '" class="' + c + '"><span class="sp-thumb-inner" style="' + swatchStyle + ';" /></span>');
127
+ html.push('<span title="' + formattedString + '" data-color="' + tiny.toRgbString() + '" class="' + c + '"><span class="sp-thumb-inner" style="' + swatchStyle + ';" /></span>');
123
128
  } else {
124
129
  var cls = 'sp-clear-display';
125
- html.push('<span title="No Color Selected" data-color="" style="background-color:transparent;" class="' + cls + '"></span>');
130
+ html.push($('<div />')
131
+ .append($('<span data-color="" style="background-color:transparent;" class="' + cls + '"></span>')
132
+ .attr('title', opts.noColorSelectedText)
133
+ )
134
+ .html()
135
+ );
126
136
  }
127
137
  }
128
138
  return "<div class='sp-cf " + className + "'>" + html.join('') + "</div>";
@@ -173,6 +183,7 @@
173
183
  currentAlpha = 1,
174
184
  palette = [],
175
185
  paletteArray = [],
186
+ paletteLookup = {},
176
187
  selectionPalette = opts.selectionPalette.slice(0),
177
188
  maxSelectionSize = opts.maxSelectionSize,
178
189
  draggingClass = "sp-dragging",
@@ -199,7 +210,7 @@
199
210
  isInput = boundElement.is("input"),
200
211
  isInputTypeColor = isInput && inputTypeColorSupport && boundElement.attr("type") === "color",
201
212
  shouldReplace = isInput && !flat,
202
- replacer = (shouldReplace) ? $(replaceInput).addClass(theme).addClass(opts.className) : $([]),
213
+ replacer = (shouldReplace) ? $(replaceInput).addClass(theme).addClass(opts.className).addClass(opts.replacerClassName) : $([]),
203
214
  offsetElement = (shouldReplace) ? replacer : boundElement,
204
215
  previewElement = replacer.find(".sp-preview-inner"),
205
216
  initialColor = opts.color || (isInput && boundElement.val()),
@@ -219,6 +230,13 @@
219
230
  if (opts.palette) {
220
231
  palette = opts.palette.slice(0);
221
232
  paletteArray = $.isArray(palette[0]) ? palette : [palette];
233
+ paletteLookup = {};
234
+ for (var i = 0; i < paletteArray.length; i++) {
235
+ for (var j = 0; j < paletteArray[i].length; j++) {
236
+ var rgb = tinycolor(paletteArray[i][j]).toRgbString();
237
+ paletteLookup[rgb] = true;
238
+ }
239
+ }
222
240
  }
223
241
 
224
242
  container.toggleClass("sp-flat", flat);
@@ -229,7 +247,7 @@
229
247
  container.toggleClass("sp-palette-disabled", !opts.showPalette);
230
248
  container.toggleClass("sp-palette-only", opts.showPaletteOnly);
231
249
  container.toggleClass("sp-initial-disabled", !opts.showInitial);
232
- container.addClass(opts.className);
250
+ container.addClass(opts.className).addClass(opts.containerClassName);
233
251
 
234
252
  reflow();
235
253
  }
@@ -263,25 +281,7 @@
263
281
  appendTo.append(container);
264
282
  }
265
283
 
266
- if (localStorageKey && window.localStorage) {
267
-
268
- // Migrate old palettes over to new format. May want to remove this eventually.
269
- try {
270
- var oldPalette = window.localStorage[localStorageKey].split(",#");
271
- if (oldPalette.length > 1) {
272
- delete window.localStorage[localStorageKey];
273
- $.each(oldPalette, function(i, c) {
274
- addColorToSelectionPalette(c);
275
- });
276
- }
277
- }
278
- catch(e) { }
279
-
280
- try {
281
- selectionPalette = window.localStorage[localStorageKey].split(";");
282
- }
283
- catch (e) { }
284
- }
284
+ updateSelectionPaletteFromStorage();
285
285
 
286
286
  offsetElement.bind("click.spectrum touchstart.spectrum", function (e) {
287
287
  if (!disabled) {
@@ -412,11 +412,11 @@
412
412
 
413
413
  function palletElementClick(e) {
414
414
  if (e.data && e.data.ignore) {
415
- set($(this).data("color"));
415
+ set($(e.target).data("color"));
416
416
  move();
417
417
  }
418
418
  else {
419
- set($(this).data("color"));
419
+ set($(e.target).data("color"));
420
420
  move();
421
421
  updateOriginalInput(true);
422
422
  hide();
@@ -430,11 +430,34 @@
430
430
  initialColorContainer.delegate(".sp-thumb-el:nth-child(1)", paletteEvent, { ignore: true }, palletElementClick);
431
431
  }
432
432
 
433
+ function updateSelectionPaletteFromStorage() {
434
+
435
+ if (localStorageKey && window.localStorage) {
436
+
437
+ // Migrate old palettes over to new format. May want to remove this eventually.
438
+ try {
439
+ var oldPalette = window.localStorage[localStorageKey].split(",#");
440
+ if (oldPalette.length > 1) {
441
+ delete window.localStorage[localStorageKey];
442
+ $.each(oldPalette, function(i, c) {
443
+ addColorToSelectionPalette(c);
444
+ });
445
+ }
446
+ }
447
+ catch(e) { }
448
+
449
+ try {
450
+ selectionPalette = window.localStorage[localStorageKey].split(";");
451
+ }
452
+ catch (e) { }
453
+ }
454
+ }
455
+
433
456
  function addColorToSelectionPalette(color) {
434
457
  if (showSelectionPalette) {
435
- var colorRgb = tinycolor(color).toRgbString();
436
- if ($.inArray(colorRgb, selectionPalette) === -1) {
437
- selectionPalette.push(colorRgb);
458
+ var rgb = tinycolor(color).toRgbString();
459
+ if (!paletteLookup[rgb] && $.inArray(rgb, selectionPalette) === -1) {
460
+ selectionPalette.push(rgb);
438
461
  while(selectionPalette.length > maxSelectionSize) {
439
462
  selectionPalette.shift();
440
463
  }
@@ -451,25 +474,12 @@
451
474
 
452
475
  function getUniqueSelectionPalette() {
453
476
  var unique = [];
454
- var p = selectionPalette;
455
- var paletteLookup = {};
456
- var rgb;
457
-
458
477
  if (opts.showPalette) {
478
+ for (var i = 0; i < selectionPalette.length; i++) {
479
+ var rgb = tinycolor(selectionPalette[i]).toRgbString();
459
480
 
460
- for (var i = 0; i < paletteArray.length; i++) {
461
- for (var j = 0; j < paletteArray[i].length; j++) {
462
- rgb = tinycolor(paletteArray[i][j]).toRgbString();
463
- paletteLookup[rgb] = true;
464
- }
465
- }
466
-
467
- for (i = 0; i < p.length; i++) {
468
- rgb = tinycolor(p[i]).toRgbString();
469
-
470
- if (!paletteLookup.hasOwnProperty(rgb)) {
471
- unique.push(p[i]);
472
- paletteLookup[rgb] = true;
481
+ if (!paletteLookup[rgb]) {
482
+ unique.push(selectionPalette[i]);
473
483
  }
474
484
  }
475
485
  }
@@ -482,11 +492,13 @@
482
492
  var currentColor = get();
483
493
 
484
494
  var html = $.map(paletteArray, function (palette, i) {
485
- return paletteTemplate(palette, currentColor, "sp-palette-row sp-palette-row-" + i);
495
+ return paletteTemplate(palette, currentColor, "sp-palette-row sp-palette-row-" + i, opts);
486
496
  });
487
497
 
498
+ updateSelectionPaletteFromStorage();
499
+
488
500
  if (selectionPalette) {
489
- html.push(paletteTemplate(getUniqueSelectionPalette(), currentColor, "sp-palette-row sp-palette-row-selection"));
501
+ html.push(paletteTemplate(getUniqueSelectionPalette(), currentColor, "sp-palette-row sp-palette-row-selection", opts));
490
502
  }
491
503
 
492
504
  paletteContainer.html(html.join(""));
@@ -496,7 +508,7 @@
496
508
  if (opts.showInitial) {
497
509
  var initial = colorOnShow;
498
510
  var current = get();
499
- initialColorContainer.html(paletteTemplate([initial, current], current, "sp-palette-row-initial"));
511
+ initialColorContainer.html(paletteTemplate([initial, current], current, "sp-palette-row-initial", opts));
500
512
  }
501
513
  }
502
514
 
@@ -524,7 +536,7 @@
524
536
  }
525
537
  else {
526
538
  var tiny = tinycolor(value);
527
- if (tiny.ok) {
539
+ if (tiny.isValid()) {
528
540
  set(tiny);
529
541
  updateOriginalInput(true);
530
542
  }
@@ -632,8 +644,8 @@
632
644
  }
633
645
  updateUI();
634
646
 
635
- if (newColor && newColor.ok && !ignoreFormatChange) {
636
- currentPreferredFormat = preferredFormat || newColor.format;
647
+ if (newColor && newColor.isValid() && !ignoreFormatChange) {
648
+ currentPreferredFormat = preferredFormat || newColor.getFormat();
637
649
  }
638
650
  }
639
651
 
@@ -684,7 +696,7 @@
684
696
  var realColor = get({ format: format }),
685
697
  displayColor = '';
686
698
 
687
- //reset background info for preview element
699
+ //reset background info for preview element
688
700
  previewElement.removeClass("sp-clear-display");
689
701
  previewElement.css('background-color', 'transparent');
690
702
 
@@ -889,9 +901,9 @@
889
901
  }
890
902
 
891
903
  /**
892
- * checkOffset - get the offset below/above and left/right element depending on screen position
893
- * Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js
894
- */
904
+ * checkOffset - get the offset below/above and left/right element depending on screen position
905
+ * Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js
906
+ */
895
907
  function getOffset(picker, input) {
896
908
  var extraY = 0;
897
909
  var dpWidth = picker.outerWidth();
@@ -906,33 +918,33 @@
906
918
 
907
919
  offset.left -=
908
920
  Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
909
- Math.abs(offset.left + dpWidth - viewWidth) : 0);
921
+ Math.abs(offset.left + dpWidth - viewWidth) : 0);
910
922
 
911
923
  offset.top -=
912
924
  Math.min(offset.top, ((offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
913
- Math.abs(dpHeight + inputHeight - extraY) : extraY));
925
+ Math.abs(dpHeight + inputHeight - extraY) : extraY));
914
926
 
915
927
  return offset;
916
928
  }
917
929
 
918
930
  /**
919
- * noop - do nothing
920
- */
931
+ * noop - do nothing
932
+ */
921
933
  function noop() {
922
934
 
923
935
  }
924
936
 
925
937
  /**
926
- * stopPropagation - makes the code only doing this a little easier to read in line
927
- */
938
+ * stopPropagation - makes the code only doing this a little easier to read in line
939
+ */
928
940
  function stopPropagation(e) {
929
941
  e.stopPropagation();
930
942
  }
931
943
 
932
944
  /**
933
- * Create a function bound to a given object
934
- * Thanks to underscore.js
935
- */
945
+ * Create a function bound to a given object
946
+ * Thanks to underscore.js
947
+ */
936
948
  function bind(func, obj) {
937
949
  var slice = Array.prototype.slice;
938
950
  var args = slice.call(arguments, 2);
@@ -942,9 +954,9 @@
942
954
  }
943
955
 
944
956
  /**
945
- * Lightweight drag helper. Handles containment within the element, so that
946
- * when dragging, the x is within [0,element.width] and y is within [0,element.height]
947
- */
957
+ * Lightweight drag helper. Handles containment within the element, so that
958
+ * when dragging, the x is within [0,element.width] and y is within [0,element.height]
959
+ */
948
960
  function draggable(element, onmove, onstart, onstop) {
949
961
  onmove = onmove || function () { };
950
962
  onstart = onstart || function () { };
@@ -1043,11 +1055,9 @@
1043
1055
  };
1044
1056
  }
1045
1057
 
1046
- function log(){/* jshint -W021 */if(window.console){if(Function.prototype.bind)log=Function.prototype.bind.call(console.log,console);else log=function(){Function.prototype.apply.call(console.log,console,arguments);};log.apply(this,arguments);}}
1047
-
1048
1058
  /**
1049
- * Define a jQuery plugin
1050
- */
1059
+ * Define a jQuery plugin
1060
+ */
1051
1061
  var dataID = "spectrum.id";
1052
1062
  $.fn.spectrum = function (opts, extra) {
1053
1063
 
@@ -1111,412 +1121,430 @@
1111
1121
  }
1112
1122
  };
1113
1123
 
1114
- // TinyColor v0.9.17
1124
+ // TinyColor v0.10.0
1115
1125
  // https://github.com/bgrins/TinyColor
1116
1126
  // 2013-08-10, Brian Grinstead, MIT License
1117
1127
 
1118
1128
  (function() {
1119
1129
 
1120
- var trimLeft = /^[\s,#]+/,
1121
- trimRight = /\s+$/,
1122
- tinyCounter = 0,
1123
- math = Math,
1124
- mathRound = math.round,
1125
- mathMin = math.min,
1126
- mathMax = math.max,
1127
- mathRandom = math.random;
1128
-
1129
- function tinycolor (color, opts) {
1130
-
1131
- color = (color) ? color : '';
1132
- opts = opts || { };
1133
-
1134
- // If input is already a tinycolor, return itself
1135
- if (typeof color == "object" && color.hasOwnProperty("_tc_id")) {
1136
- return color;
1137
- }
1130
+ var trimLeft = /^[\s,#]+/,
1131
+ trimRight = /\s+$/,
1132
+ tinyCounter = 0,
1133
+ math = Math,
1134
+ mathRound = math.round,
1135
+ mathMin = math.min,
1136
+ mathMax = math.max,
1137
+ mathRandom = math.random;
1138
1138
 
1139
- var rgb = inputToRGB(color);
1140
- var r = rgb.r,
1141
- g = rgb.g,
1142
- b = rgb.b,
1143
- a = rgb.a,
1144
- roundA = mathRound(100*a) / 100,
1145
- format = opts.format || rgb.format;
1139
+ var tinycolor = function tinycolor (color, opts) {
1146
1140
 
1147
- // Don't let the range of [0,255] come back in [0,1].
1148
- // Potentially lose a little bit of precision here, but will fix issues where
1149
- // .5 gets interpreted as half of the total, instead of half of 1
1150
- // If it was supposed to be 128, this was already taken care of by `inputToRgb`
1151
- if (r < 1) { r = mathRound(r); }
1152
- if (g < 1) { g = mathRound(g); }
1153
- if (b < 1) { b = mathRound(b); }
1141
+ color = (color) ? color : '';
1142
+ opts = opts || { };
1154
1143
 
1155
- return {
1156
- ok: rgb.ok,
1157
- format: format,
1158
- _tc_id: tinyCounter++,
1159
- alpha: a,
1160
- getAlpha: function() {
1161
- return a;
1162
- },
1163
- setAlpha: function(value) {
1164
- a = boundAlpha(value);
1165
- roundA = mathRound(100*a) / 100;
1166
- },
1167
- toHsv: function() {
1168
- var hsv = rgbToHsv(r, g, b);
1169
- return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: a };
1170
- },
1171
- toHsvString: function() {
1172
- var hsv = rgbToHsv(r, g, b);
1173
- var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);
1174
- return (a == 1) ?
1175
- "hsv(" + h + ", " + s + "%, " + v + "%)" :
1176
- "hsva(" + h + ", " + s + "%, " + v + "%, "+ roundA + ")";
1177
- },
1178
- toHsl: function() {
1179
- var hsl = rgbToHsl(r, g, b);
1180
- return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: a };
1181
- },
1182
- toHslString: function() {
1183
- var hsl = rgbToHsl(r, g, b);
1184
- var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);
1185
- return (a == 1) ?
1186
- "hsl(" + h + ", " + s + "%, " + l + "%)" :
1187
- "hsla(" + h + ", " + s + "%, " + l + "%, "+ roundA + ")";
1188
- },
1189
- toHex: function(allow3Char) {
1190
- return rgbToHex(r, g, b, allow3Char);
1191
- },
1192
- toHexString: function(allow3Char) {
1193
- return '#' + this.toHex(allow3Char);
1194
- },
1195
- toHex8: function() {
1196
- return rgbaToHex(r, g, b, a);
1197
- },
1198
- toHex8String: function() {
1199
- return '#' + this.toHex8();
1200
- },
1201
- toRgb: function() {
1202
- return { r: mathRound(r), g: mathRound(g), b: mathRound(b), a: a };
1203
- },
1204
- toRgbString: function() {
1205
- return (a == 1) ?
1206
- "rgb(" + mathRound(r) + ", " + mathRound(g) + ", " + mathRound(b) + ")" :
1207
- "rgba(" + mathRound(r) + ", " + mathRound(g) + ", " + mathRound(b) + ", " + roundA + ")";
1208
- },
1209
- toPercentageRgb: function() {
1210
- return { r: mathRound(bound01(r, 255) * 100) + "%", g: mathRound(bound01(g, 255) * 100) + "%", b: mathRound(bound01(b, 255) * 100) + "%", a: a };
1211
- },
1212
- toPercentageRgbString: function() {
1213
- return (a == 1) ?
1214
- "rgb(" + mathRound(bound01(r, 255) * 100) + "%, " + mathRound(bound01(g, 255) * 100) + "%, " + mathRound(bound01(b, 255) * 100) + "%)" :
1215
- "rgba(" + mathRound(bound01(r, 255) * 100) + "%, " + mathRound(bound01(g, 255) * 100) + "%, " + mathRound(bound01(b, 255) * 100) + "%, " + roundA + ")";
1216
- },
1217
- toName: function() {
1218
- if (a === 0) {
1219
- return "transparent";
1220
- }
1221
-
1222
- return hexNames[rgbToHex(r, g, b, true)] || false;
1223
- },
1224
- toFilter: function(secondColor) {
1225
- var hex8String = '#' + rgbaToHex(r, g, b, a);
1226
- var secondHex8String = hex8String;
1227
- var gradientType = opts && opts.gradientType ? "GradientType = 1, " : "";
1144
+ // If input is already a tinycolor, return itself
1145
+ if (color instanceof tinycolor) {
1146
+ return color;
1147
+ }
1148
+ // If we are called as a function, call using new instead
1149
+ if (!(this instanceof tinycolor)) {
1150
+ return new tinycolor(color, opts);
1151
+ }
1228
1152
 
1229
- if (secondColor) {
1230
- var s = tinycolor(secondColor);
1231
- secondHex8String = s.toHex8String();
1232
- }
1153
+ var rgb = inputToRGB(color);
1154
+ this._r = rgb.r,
1155
+ this._g = rgb.g,
1156
+ this._b = rgb.b,
1157
+ this._a = rgb.a,
1158
+ this._roundA = mathRound(100*this._a) / 100,
1159
+ this._format = opts.format || rgb.format;
1160
+ this._gradientType = opts.gradientType;
1161
+
1162
+ // Don't let the range of [0,255] come back in [0,1].
1163
+ // Potentially lose a little bit of precision here, but will fix issues where
1164
+ // .5 gets interpreted as half of the total, instead of half of 1
1165
+ // If it was supposed to be 128, this was already taken care of by `inputToRgb`
1166
+ if (this._r < 1) { this._r = mathRound(this._r); }
1167
+ if (this._g < 1) { this._g = mathRound(this._g); }
1168
+ if (this._b < 1) { this._b = mathRound(this._b); }
1169
+
1170
+ this._ok = rgb.ok;
1171
+ this._tc_id = tinyCounter++;
1172
+ };
1233
1173
 
1234
- return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")";
1235
- },
1236
- toString: function(format) {
1237
- var formatSet = !!format;
1238
- format = format || this.format;
1174
+ tinycolor.prototype = {
1175
+ isValid: function() {
1176
+ return this._ok;
1177
+ },
1178
+ getFormat: function() {
1179
+ return this._format;
1180
+ },
1181
+ getAlpha: function() {
1182
+ return this._a;
1183
+ },
1184
+ setAlpha: function(value) {
1185
+ this._a = boundAlpha(value);
1186
+ this._roundA = mathRound(100*this._a) / 100;
1187
+ },
1188
+ toHsv: function() {
1189
+ var hsv = rgbToHsv(this._r, this._g, this._b);
1190
+ return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a };
1191
+ },
1192
+ toHsvString: function() {
1193
+ var hsv = rgbToHsv(this._r, this._g, this._b);
1194
+ var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);
1195
+ return (this._a == 1) ?
1196
+ "hsv(" + h + ", " + s + "%, " + v + "%)" :
1197
+ "hsva(" + h + ", " + s + "%, " + v + "%, "+ this._roundA + ")";
1198
+ },
1199
+ toHsl: function() {
1200
+ var hsl = rgbToHsl(this._r, this._g, this._b);
1201
+ return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a };
1202
+ },
1203
+ toHslString: function() {
1204
+ var hsl = rgbToHsl(this._r, this._g, this._b);
1205
+ var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);
1206
+ return (this._a == 1) ?
1207
+ "hsl(" + h + ", " + s + "%, " + l + "%)" :
1208
+ "hsla(" + h + ", " + s + "%, " + l + "%, "+ this._roundA + ")";
1209
+ },
1210
+ toHex: function(allow3Char) {
1211
+ return rgbToHex(this._r, this._g, this._b, allow3Char);
1212
+ },
1213
+ toHexString: function(allow3Char) {
1214
+ return '#' + this.toHex(allow3Char);
1215
+ },
1216
+ toHex8: function() {
1217
+ return rgbaToHex(this._r, this._g, this._b, this._a);
1218
+ },
1219
+ toHex8String: function() {
1220
+ return '#' + this.toHex8();
1221
+ },
1222
+ toRgb: function() {
1223
+ return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a };
1224
+ },
1225
+ toRgbString: function() {
1226
+ return (this._a == 1) ?
1227
+ "rgb(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ")" :
1228
+ "rgba(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ", " + this._roundA + ")";
1229
+ },
1230
+ toPercentageRgb: function() {
1231
+ return { r: mathRound(bound01(this._r, 255) * 100) + "%", g: mathRound(bound01(this._g, 255) * 100) + "%", b: mathRound(bound01(this._b, 255) * 100) + "%", a: this._a };
1232
+ },
1233
+ toPercentageRgbString: function() {
1234
+ return (this._a == 1) ?
1235
+ "rgb(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%)" :
1236
+ "rgba(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")";
1237
+ },
1238
+ toName: function() {
1239
+ if (this._a === 0) {
1240
+ return "transparent";
1241
+ }
1239
1242
 
1240
- var formattedString = false;
1241
- var hasAlphaAndFormatNotSet = !formatSet && a < 1 && a > 0;
1242
- var formatWithAlpha = hasAlphaAndFormatNotSet && (format === "hex" || format === "hex6" || format === "hex3" || format === "name");
1243
+ if (this._a < 1) {
1244
+ return false;
1245
+ }
1243
1246
 
1244
- if (format === "rgb") {
1245
- formattedString = this.toRgbString();
1246
- }
1247
- if (format === "prgb") {
1248
- formattedString = this.toPercentageRgbString();
1249
- }
1250
- if (format === "hex" || format === "hex6") {
1251
- formattedString = this.toHexString();
1252
- }
1253
- if (format === "hex3") {
1254
- formattedString = this.toHexString(true);
1255
- }
1256
- if (format === "hex8") {
1257
- formattedString = this.toHex8String();
1258
- }
1259
- if (format === "name") {
1260
- formattedString = this.toName();
1261
- }
1262
- if (format === "hsl") {
1263
- formattedString = this.toHslString();
1264
- }
1265
- if (format === "hsv") {
1266
- formattedString = this.toHsvString();
1267
- }
1247
+ return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false;
1248
+ },
1249
+ toFilter: function(secondColor) {
1250
+ var hex8String = '#' + rgbaToHex(this._r, this._g, this._b, this._a);
1251
+ var secondHex8String = hex8String;
1252
+ var gradientType = this._gradientType ? "GradientType = 1, " : "";
1268
1253
 
1269
- if (formatWithAlpha) {
1270
- return this.toRgbString();
1271
- }
1254
+ if (secondColor) {
1255
+ var s = tinycolor(secondColor);
1256
+ secondHex8String = s.toHex8String();
1257
+ }
1272
1258
 
1273
- return formattedString || this.toHexString();
1259
+ return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")";
1260
+ },
1261
+ toString: function(format) {
1262
+ var formatSet = !!format;
1263
+ format = format || this._format;
1264
+
1265
+ var formattedString = false;
1266
+ var hasAlpha = this._a < 1 && this._a >= 0;
1267
+ var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "name");
1268
+
1269
+ if (needsAlphaFormat) {
1270
+ // Special case for "transparent", all other non-alpha formats
1271
+ // will return rgba when there is transparency.
1272
+ if (format === "name" && this._a === 0) {
1273
+ return this.toName();
1274
1274
  }
1275
- };
1275
+ return this.toRgbString();
1276
+ }
1277
+ if (format === "rgb") {
1278
+ formattedString = this.toRgbString();
1279
+ }
1280
+ if (format === "prgb") {
1281
+ formattedString = this.toPercentageRgbString();
1282
+ }
1283
+ if (format === "hex" || format === "hex6") {
1284
+ formattedString = this.toHexString();
1285
+ }
1286
+ if (format === "hex3") {
1287
+ formattedString = this.toHexString(true);
1288
+ }
1289
+ if (format === "hex8") {
1290
+ formattedString = this.toHex8String();
1291
+ }
1292
+ if (format === "name") {
1293
+ formattedString = this.toName();
1294
+ }
1295
+ if (format === "hsl") {
1296
+ formattedString = this.toHslString();
1297
+ }
1298
+ if (format === "hsv") {
1299
+ formattedString = this.toHsvString();
1300
+ }
1301
+
1302
+ return formattedString || this.toHexString();
1276
1303
  }
1304
+ };
1277
1305
 
1278
- // If input is an object, force 1 into "1.0" to handle ratios properly
1279
- // String input requires "1.0" as input, so 1 will be treated as 1
1280
- tinycolor.fromRatio = function(color, opts) {
1281
- if (typeof color == "object") {
1282
- var newColor = {};
1283
- for (var i in color) {
1284
- if (color.hasOwnProperty(i)) {
1285
- if (i === "a") {
1286
- newColor[i] = color[i];
1287
- }
1288
- else {
1289
- newColor[i] = convertToPercentage(color[i]);
1290
- }
1306
+ // If input is an object, force 1 into "1.0" to handle ratios properly
1307
+ // String input requires "1.0" as input, so 1 will be treated as 1
1308
+ tinycolor.fromRatio = function(color, opts) {
1309
+ if (typeof color == "object") {
1310
+ var newColor = {};
1311
+ for (var i in color) {
1312
+ if (color.hasOwnProperty(i)) {
1313
+ if (i === "a") {
1314
+ newColor[i] = color[i];
1315
+ }
1316
+ else {
1317
+ newColor[i] = convertToPercentage(color[i]);
1291
1318
  }
1292
1319
  }
1293
- color = newColor;
1294
1320
  }
1321
+ color = newColor;
1322
+ }
1295
1323
 
1296
- return tinycolor(color, opts);
1297
- };
1324
+ return tinycolor(color, opts);
1325
+ };
1298
1326
 
1299
- // Given a string or object, convert that input to RGB
1300
- // Possible string inputs:
1301
- //
1302
- // "red"
1303
- // "#f00" or "f00"
1304
- // "#ff0000" or "ff0000"
1305
- // "#ff000000" or "ff000000"
1306
- // "rgb 255 0 0" or "rgb (255, 0, 0)"
1307
- // "rgb 1.0 0 0" or "rgb (1, 0, 0)"
1308
- // "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
1309
- // "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
1310
- // "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
1311
- // "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
1312
- // "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
1313
- //
1314
- function inputToRGB(color) {
1315
-
1316
- var rgb = { r: 0, g: 0, b: 0 };
1317
- var a = 1;
1318
- var ok = false;
1319
- var format = false;
1320
-
1321
- if (typeof color == "string") {
1322
- color = stringInputToObject(color);
1323
- }
1324
-
1325
- if (typeof color == "object") {
1326
- if (color.hasOwnProperty("r") && color.hasOwnProperty("g") && color.hasOwnProperty("b")) {
1327
- rgb = rgbToRgb(color.r, color.g, color.b);
1328
- ok = true;
1329
- format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb";
1330
- }
1331
- else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) {
1332
- color.s = convertToPercentage(color.s);
1333
- color.v = convertToPercentage(color.v);
1334
- rgb = hsvToRgb(color.h, color.s, color.v);
1335
- ok = true;
1336
- format = "hsv";
1337
- }
1338
- else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) {
1339
- color.s = convertToPercentage(color.s);
1340
- color.l = convertToPercentage(color.l);
1341
- rgb = hslToRgb(color.h, color.s, color.l);
1342
- ok = true;
1343
- format = "hsl";
1344
- }
1327
+ // Given a string or object, convert that input to RGB
1328
+ // Possible string inputs:
1329
+ //
1330
+ // "red"
1331
+ // "#f00" or "f00"
1332
+ // "#ff0000" or "ff0000"
1333
+ // "#ff000000" or "ff000000"
1334
+ // "rgb 255 0 0" or "rgb (255, 0, 0)"
1335
+ // "rgb 1.0 0 0" or "rgb (1, 0, 0)"
1336
+ // "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
1337
+ // "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
1338
+ // "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
1339
+ // "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
1340
+ // "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
1341
+ //
1342
+ function inputToRGB(color) {
1343
+
1344
+ var rgb = { r: 0, g: 0, b: 0 };
1345
+ var a = 1;
1346
+ var ok = false;
1347
+ var format = false;
1348
+
1349
+ if (typeof color == "string") {
1350
+ color = stringInputToObject(color);
1351
+ }
1345
1352
 
1346
- if (color.hasOwnProperty("a")) {
1347
- a = color.a;
1348
- }
1353
+ if (typeof color == "object") {
1354
+ if (color.hasOwnProperty("r") && color.hasOwnProperty("g") && color.hasOwnProperty("b")) {
1355
+ rgb = rgbToRgb(color.r, color.g, color.b);
1356
+ ok = true;
1357
+ format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb";
1358
+ }
1359
+ else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) {
1360
+ color.s = convertToPercentage(color.s);
1361
+ color.v = convertToPercentage(color.v);
1362
+ rgb = hsvToRgb(color.h, color.s, color.v);
1363
+ ok = true;
1364
+ format = "hsv";
1365
+ }
1366
+ else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) {
1367
+ color.s = convertToPercentage(color.s);
1368
+ color.l = convertToPercentage(color.l);
1369
+ rgb = hslToRgb(color.h, color.s, color.l);
1370
+ ok = true;
1371
+ format = "hsl";
1349
1372
  }
1350
1373
 
1351
- a = boundAlpha(a);
1352
-
1353
- return {
1354
- ok: ok,
1355
- format: color.format || format,
1356
- r: mathMin(255, mathMax(rgb.r, 0)),
1357
- g: mathMin(255, mathMax(rgb.g, 0)),
1358
- b: mathMin(255, mathMax(rgb.b, 0)),
1359
- a: a
1360
- };
1374
+ if (color.hasOwnProperty("a")) {
1375
+ a = color.a;
1376
+ }
1361
1377
  }
1362
1378
 
1379
+ a = boundAlpha(a);
1380
+
1381
+ return {
1382
+ ok: ok,
1383
+ format: color.format || format,
1384
+ r: mathMin(255, mathMax(rgb.r, 0)),
1385
+ g: mathMin(255, mathMax(rgb.g, 0)),
1386
+ b: mathMin(255, mathMax(rgb.b, 0)),
1387
+ a: a
1388
+ };
1389
+ }
1363
1390
 
1364
- // Conversion Functions
1365
- // --------------------
1366
1391
 
1367
- // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
1368
- // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
1392
+ // Conversion Functions
1393
+ // --------------------
1369
1394
 
1370
- // `rgbToRgb`
1371
- // Handle bounds / percentage checking to conform to CSS color spec
1372
- // <http://www.w3.org/TR/css3-color/>
1373
- // *Assumes:* r, g, b in [0, 255] or [0, 1]
1374
- // *Returns:* { r, g, b } in [0, 255]
1375
- function rgbToRgb(r, g, b){
1376
- return {
1377
- r: bound01(r, 255) * 255,
1378
- g: bound01(g, 255) * 255,
1379
- b: bound01(b, 255) * 255
1380
- };
1381
- }
1395
+ // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
1396
+ // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
1382
1397
 
1383
- // `rgbToHsl`
1384
- // Converts an RGB color value to HSL.
1385
- // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
1386
- // *Returns:* { h, s, l } in [0,1]
1387
- function rgbToHsl(r, g, b) {
1398
+ // `rgbToRgb`
1399
+ // Handle bounds / percentage checking to conform to CSS color spec
1400
+ // <http://www.w3.org/TR/css3-color/>
1401
+ // *Assumes:* r, g, b in [0, 255] or [0, 1]
1402
+ // *Returns:* { r, g, b } in [0, 255]
1403
+ function rgbToRgb(r, g, b){
1404
+ return {
1405
+ r: bound01(r, 255) * 255,
1406
+ g: bound01(g, 255) * 255,
1407
+ b: bound01(b, 255) * 255
1408
+ };
1409
+ }
1388
1410
 
1389
- r = bound01(r, 255);
1390
- g = bound01(g, 255);
1391
- b = bound01(b, 255);
1411
+ // `rgbToHsl`
1412
+ // Converts an RGB color value to HSL.
1413
+ // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
1414
+ // *Returns:* { h, s, l } in [0,1]
1415
+ function rgbToHsl(r, g, b) {
1392
1416
 
1393
- var max = mathMax(r, g, b), min = mathMin(r, g, b);
1394
- var h, s, l = (max + min) / 2;
1417
+ r = bound01(r, 255);
1418
+ g = bound01(g, 255);
1419
+ b = bound01(b, 255);
1395
1420
 
1396
- if(max == min) {
1397
- h = s = 0; // achromatic
1398
- }
1399
- else {
1400
- var d = max - min;
1401
- s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
1402
- switch(max) {
1403
- case r: h = (g - b) / d + (g < b ? 6 : 0); break;
1404
- case g: h = (b - r) / d + 2; break;
1405
- case b: h = (r - g) / d + 4; break;
1406
- }
1421
+ var max = mathMax(r, g, b), min = mathMin(r, g, b);
1422
+ var h, s, l = (max + min) / 2;
1407
1423
 
1408
- h /= 6;
1424
+ if(max == min) {
1425
+ h = s = 0; // achromatic
1426
+ }
1427
+ else {
1428
+ var d = max - min;
1429
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
1430
+ switch(max) {
1431
+ case r: h = (g - b) / d + (g < b ? 6 : 0); break;
1432
+ case g: h = (b - r) / d + 2; break;
1433
+ case b: h = (r - g) / d + 4; break;
1409
1434
  }
1410
1435
 
1411
- return { h: h, s: s, l: l };
1436
+ h /= 6;
1412
1437
  }
1413
1438
 
1414
- // `hslToRgb`
1415
- // Converts an HSL color value to RGB.
1416
- // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
1417
- // *Returns:* { r, g, b } in the set [0, 255]
1418
- function hslToRgb(h, s, l) {
1419
- var r, g, b;
1420
-
1421
- h = bound01(h, 360);
1422
- s = bound01(s, 100);
1423
- l = bound01(l, 100);
1424
-
1425
- function hue2rgb(p, q, t) {
1426
- if(t < 0) t += 1;
1427
- if(t > 1) t -= 1;
1428
- if(t < 1/6) return p + (q - p) * 6 * t;
1429
- if(t < 1/2) return q;
1430
- if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
1431
- return p;
1432
- }
1439
+ return { h: h, s: s, l: l };
1440
+ }
1433
1441
 
1434
- if(s === 0) {
1435
- r = g = b = l; // achromatic
1436
- }
1437
- else {
1438
- var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
1439
- var p = 2 * l - q;
1440
- r = hue2rgb(p, q, h + 1/3);
1441
- g = hue2rgb(p, q, h);
1442
- b = hue2rgb(p, q, h - 1/3);
1443
- }
1442
+ // `hslToRgb`
1443
+ // Converts an HSL color value to RGB.
1444
+ // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
1445
+ // *Returns:* { r, g, b } in the set [0, 255]
1446
+ function hslToRgb(h, s, l) {
1447
+ var r, g, b;
1448
+
1449
+ h = bound01(h, 360);
1450
+ s = bound01(s, 100);
1451
+ l = bound01(l, 100);
1452
+
1453
+ function hue2rgb(p, q, t) {
1454
+ if(t < 0) t += 1;
1455
+ if(t > 1) t -= 1;
1456
+ if(t < 1/6) return p + (q - p) * 6 * t;
1457
+ if(t < 1/2) return q;
1458
+ if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
1459
+ return p;
1460
+ }
1444
1461
 
1445
- return { r: r * 255, g: g * 255, b: b * 255 };
1462
+ if(s === 0) {
1463
+ r = g = b = l; // achromatic
1464
+ }
1465
+ else {
1466
+ var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
1467
+ var p = 2 * l - q;
1468
+ r = hue2rgb(p, q, h + 1/3);
1469
+ g = hue2rgb(p, q, h);
1470
+ b = hue2rgb(p, q, h - 1/3);
1446
1471
  }
1447
1472
 
1448
- // `rgbToHsv`
1449
- // Converts an RGB color value to HSV
1450
- // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
1451
- // *Returns:* { h, s, v } in [0,1]
1452
- function rgbToHsv(r, g, b) {
1473
+ return { r: r * 255, g: g * 255, b: b * 255 };
1474
+ }
1453
1475
 
1454
- r = bound01(r, 255);
1455
- g = bound01(g, 255);
1456
- b = bound01(b, 255);
1476
+ // `rgbToHsv`
1477
+ // Converts an RGB color value to HSV
1478
+ // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
1479
+ // *Returns:* { h, s, v } in [0,1]
1480
+ function rgbToHsv(r, g, b) {
1457
1481
 
1458
- var max = mathMax(r, g, b), min = mathMin(r, g, b);
1459
- var h, s, v = max;
1482
+ r = bound01(r, 255);
1483
+ g = bound01(g, 255);
1484
+ b = bound01(b, 255);
1460
1485
 
1461
- var d = max - min;
1462
- s = max === 0 ? 0 : d / max;
1486
+ var max = mathMax(r, g, b), min = mathMin(r, g, b);
1487
+ var h, s, v = max;
1463
1488
 
1464
- if(max == min) {
1465
- h = 0; // achromatic
1466
- }
1467
- else {
1468
- switch(max) {
1469
- case r: h = (g - b) / d + (g < b ? 6 : 0); break;
1470
- case g: h = (b - r) / d + 2; break;
1471
- case b: h = (r - g) / d + 4; break;
1472
- }
1473
- h /= 6;
1489
+ var d = max - min;
1490
+ s = max === 0 ? 0 : d / max;
1491
+
1492
+ if(max == min) {
1493
+ h = 0; // achromatic
1494
+ }
1495
+ else {
1496
+ switch(max) {
1497
+ case r: h = (g - b) / d + (g < b ? 6 : 0); break;
1498
+ case g: h = (b - r) / d + 2; break;
1499
+ case b: h = (r - g) / d + 4; break;
1474
1500
  }
1475
- return { h: h, s: s, v: v };
1501
+ h /= 6;
1476
1502
  }
1503
+ return { h: h, s: s, v: v };
1504
+ }
1477
1505
 
1478
- // `hsvToRgb`
1479
- // Converts an HSV color value to RGB.
1480
- // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
1481
- // *Returns:* { r, g, b } in the set [0, 255]
1482
- function hsvToRgb(h, s, v) {
1483
-
1484
- h = bound01(h, 360) * 6;
1485
- s = bound01(s, 100);
1486
- v = bound01(v, 100);
1487
-
1488
- var i = math.floor(h),
1489
- f = h - i,
1490
- p = v * (1 - s),
1491
- q = v * (1 - f * s),
1492
- t = v * (1 - (1 - f) * s),
1493
- mod = i % 6,
1494
- r = [v, q, p, p, t, v][mod],
1495
- g = [t, v, v, q, p, p][mod],
1496
- b = [p, p, t, v, v, q][mod];
1506
+ // `hsvToRgb`
1507
+ // Converts an HSV color value to RGB.
1508
+ // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
1509
+ // *Returns:* { r, g, b } in the set [0, 255]
1510
+ function hsvToRgb(h, s, v) {
1511
+
1512
+ h = bound01(h, 360) * 6;
1513
+ s = bound01(s, 100);
1514
+ v = bound01(v, 100);
1515
+
1516
+ var i = math.floor(h),
1517
+ f = h - i,
1518
+ p = v * (1 - s),
1519
+ q = v * (1 - f * s),
1520
+ t = v * (1 - (1 - f) * s),
1521
+ mod = i % 6,
1522
+ r = [v, q, p, p, t, v][mod],
1523
+ g = [t, v, v, q, p, p][mod],
1524
+ b = [p, p, t, v, v, q][mod];
1525
+
1526
+ return { r: r * 255, g: g * 255, b: b * 255 };
1527
+ }
1497
1528
 
1498
- return { r: r * 255, g: g * 255, b: b * 255 };
1529
+ // `rgbToHex`
1530
+ // Converts an RGB color to hex
1531
+ // Assumes r, g, and b are contained in the set [0, 255]
1532
+ // Returns a 3 or 6 character hex
1533
+ function rgbToHex(r, g, b, allow3Char) {
1534
+
1535
+ var hex = [
1536
+ pad2(mathRound(r).toString(16)),
1537
+ pad2(mathRound(g).toString(16)),
1538
+ pad2(mathRound(b).toString(16))
1539
+ ];
1540
+
1541
+ // Return a 3 character hex if possible
1542
+ 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)) {
1543
+ return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
1499
1544
  }
1500
1545
 
1501
- // `rgbToHex`
1502
- // Converts an RGB color to hex
1503
- // Assumes r, g, and b are contained in the set [0, 255]
1504
- // Returns a 3 or 6 character hex
1505
- function rgbToHex(r, g, b, allow3Char) {
1506
-
1507
- var hex = [
1508
- pad2(mathRound(r).toString(16)),
1509
- pad2(mathRound(g).toString(16)),
1510
- pad2(mathRound(b).toString(16))
1511
- ];
1512
-
1513
- // Return a 3 character hex if possible
1514
- 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)) {
1515
- return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
1516
- }
1517
-
1518
- return hex.join("");
1519
- }
1546
+ return hex.join("");
1547
+ }
1520
1548
  // `rgbaToHex`
1521
1549
  // Converts an RGBA color plus alpha transparency to hex
1522
1550
  // Assumes r, g, b and a are contained in the set [0, 255]
@@ -1533,536 +1561,542 @@
1533
1561
  return hex.join("");
1534
1562
  }
1535
1563
 
1536
- // `equals`
1537
- // Can be called with any tinycolor input
1538
- tinycolor.equals = function (color1, color2) {
1539
- if (!color1 || !color2) { return false; }
1540
- return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
1541
- };
1542
- tinycolor.random = function() {
1543
- return tinycolor.fromRatio({
1544
- r: mathRandom(),
1545
- g: mathRandom(),
1546
- b: mathRandom()
1547
- });
1548
- };
1549
-
1564
+ // `equals`
1565
+ // Can be called with any tinycolor input
1566
+ tinycolor.equals = function (color1, color2) {
1567
+ if (!color1 || !color2) { return false; }
1568
+ return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
1569
+ };
1570
+ tinycolor.random = function() {
1571
+ return tinycolor.fromRatio({
1572
+ r: mathRandom(),
1573
+ g: mathRandom(),
1574
+ b: mathRandom()
1575
+ });
1576
+ };
1550
1577
 
1551
- // Modification Functions
1552
- // ----------------------
1553
- // Thanks to less.js for some of the basics here
1554
- // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>
1555
1578
 
1556
- tinycolor.desaturate = function (color, amount) {
1557
- amount = (amount === 0) ? 0 : (amount || 10);
1558
- var hsl = tinycolor(color).toHsl();
1559
- hsl.s -= amount / 100;
1560
- hsl.s = clamp01(hsl.s);
1561
- return tinycolor(hsl);
1562
- };
1563
- tinycolor.saturate = function (color, amount) {
1564
- amount = (amount === 0) ? 0 : (amount || 10);
1565
- var hsl = tinycolor(color).toHsl();
1566
- hsl.s += amount / 100;
1567
- hsl.s = clamp01(hsl.s);
1568
- return tinycolor(hsl);
1569
- };
1570
- tinycolor.greyscale = function(color) {
1571
- return tinycolor.desaturate(color, 100);
1572
- };
1573
- tinycolor.lighten = function(color, amount) {
1574
- amount = (amount === 0) ? 0 : (amount || 10);
1575
- var hsl = tinycolor(color).toHsl();
1576
- hsl.l += amount / 100;
1577
- hsl.l = clamp01(hsl.l);
1578
- return tinycolor(hsl);
1579
- };
1580
- tinycolor.darken = function (color, amount) {
1581
- amount = (amount === 0) ? 0 : (amount || 10);
1582
- var hsl = tinycolor(color).toHsl();
1583
- hsl.l -= amount / 100;
1584
- hsl.l = clamp01(hsl.l);
1585
- return tinycolor(hsl);
1586
- };
1587
- tinycolor.complement = function(color) {
1588
- var hsl = tinycolor(color).toHsl();
1589
- hsl.h = (hsl.h + 180) % 360;
1590
- return tinycolor(hsl);
1591
- };
1579
+ // Modification Functions
1580
+ // ----------------------
1581
+ // Thanks to less.js for some of the basics here
1582
+ // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>
1592
1583
 
1584
+ tinycolor.desaturate = function (color, amount) {
1585
+ amount = (amount === 0) ? 0 : (amount || 10);
1586
+ var hsl = tinycolor(color).toHsl();
1587
+ hsl.s -= amount / 100;
1588
+ hsl.s = clamp01(hsl.s);
1589
+ return tinycolor(hsl);
1590
+ };
1591
+ tinycolor.saturate = function (color, amount) {
1592
+ amount = (amount === 0) ? 0 : (amount || 10);
1593
+ var hsl = tinycolor(color).toHsl();
1594
+ hsl.s += amount / 100;
1595
+ hsl.s = clamp01(hsl.s);
1596
+ return tinycolor(hsl);
1597
+ };
1598
+ tinycolor.greyscale = function(color) {
1599
+ return tinycolor.desaturate(color, 100);
1600
+ };
1601
+ tinycolor.lighten = function(color, amount) {
1602
+ amount = (amount === 0) ? 0 : (amount || 10);
1603
+ var hsl = tinycolor(color).toHsl();
1604
+ hsl.l += amount / 100;
1605
+ hsl.l = clamp01(hsl.l);
1606
+ return tinycolor(hsl);
1607
+ };
1608
+ tinycolor.brighten = function(color, amount) {
1609
+ amount = (amount === 0) ? 0 : (amount || 10);
1610
+ var rgb = tinycolor(color).toRgb();
1611
+ rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100))));
1612
+ rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100))));
1613
+ rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100))));
1614
+ return tinycolor(rgb);
1615
+ };
1616
+ tinycolor.darken = function (color, amount) {
1617
+ amount = (amount === 0) ? 0 : (amount || 10);
1618
+ var hsl = tinycolor(color).toHsl();
1619
+ hsl.l -= amount / 100;
1620
+ hsl.l = clamp01(hsl.l);
1621
+ return tinycolor(hsl);
1622
+ };
1623
+ tinycolor.complement = function(color) {
1624
+ var hsl = tinycolor(color).toHsl();
1625
+ hsl.h = (hsl.h + 180) % 360;
1626
+ return tinycolor(hsl);
1627
+ };
1593
1628
 
1594
- // Combination Functions
1595
- // ---------------------
1596
- // Thanks to jQuery xColor for some of the ideas behind these
1597
- // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>
1598
-
1599
- tinycolor.triad = function(color) {
1600
- var hsl = tinycolor(color).toHsl();
1601
- var h = hsl.h;
1602
- return [
1603
- tinycolor(color),
1604
- tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
1605
- tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })
1606
- ];
1607
- };
1608
- tinycolor.tetrad = function(color) {
1609
- var hsl = tinycolor(color).toHsl();
1610
- var h = hsl.h;
1611
- return [
1612
- tinycolor(color),
1613
- tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
1614
- tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
1615
- tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })
1616
- ];
1617
- };
1618
- tinycolor.splitcomplement = function(color) {
1619
- var hsl = tinycolor(color).toHsl();
1620
- var h = hsl.h;
1621
- return [
1622
- tinycolor(color),
1623
- tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),
1624
- tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})
1625
- ];
1626
- };
1627
- tinycolor.analogous = function(color, results, slices) {
1628
- results = results || 6;
1629
- slices = slices || 30;
1630
1629
 
1631
- var hsl = tinycolor(color).toHsl();
1632
- var part = 360 / slices;
1633
- var ret = [tinycolor(color)];
1630
+ // Combination Functions
1631
+ // ---------------------
1632
+ // Thanks to jQuery xColor for some of the ideas behind these
1633
+ // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>
1634
1634
 
1635
- for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {
1636
- hsl.h = (hsl.h + part) % 360;
1637
- ret.push(tinycolor(hsl));
1638
- }
1639
- return ret;
1640
- };
1641
- tinycolor.monochromatic = function(color, results) {
1642
- results = results || 6;
1643
- var hsv = tinycolor(color).toHsv();
1644
- var h = hsv.h, s = hsv.s, v = hsv.v;
1645
- var ret = [];
1646
- var modification = 1 / results;
1635
+ tinycolor.triad = function(color) {
1636
+ var hsl = tinycolor(color).toHsl();
1637
+ var h = hsl.h;
1638
+ return [
1639
+ tinycolor(color),
1640
+ tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
1641
+ tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })
1642
+ ];
1643
+ };
1644
+ tinycolor.tetrad = function(color) {
1645
+ var hsl = tinycolor(color).toHsl();
1646
+ var h = hsl.h;
1647
+ return [
1648
+ tinycolor(color),
1649
+ tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
1650
+ tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
1651
+ tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })
1652
+ ];
1653
+ };
1654
+ tinycolor.splitcomplement = function(color) {
1655
+ var hsl = tinycolor(color).toHsl();
1656
+ var h = hsl.h;
1657
+ return [
1658
+ tinycolor(color),
1659
+ tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),
1660
+ tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})
1661
+ ];
1662
+ };
1663
+ tinycolor.analogous = function(color, results, slices) {
1664
+ results = results || 6;
1665
+ slices = slices || 30;
1647
1666
 
1648
- while (results--) {
1649
- ret.push(tinycolor({ h: h, s: s, v: v}));
1650
- v = (v + modification) % 1;
1651
- }
1667
+ var hsl = tinycolor(color).toHsl();
1668
+ var part = 360 / slices;
1669
+ var ret = [tinycolor(color)];
1652
1670
 
1653
- return ret;
1654
- };
1671
+ for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {
1672
+ hsl.h = (hsl.h + part) % 360;
1673
+ ret.push(tinycolor(hsl));
1674
+ }
1675
+ return ret;
1676
+ };
1677
+ tinycolor.monochromatic = function(color, results) {
1678
+ results = results || 6;
1679
+ var hsv = tinycolor(color).toHsv();
1680
+ var h = hsv.h, s = hsv.s, v = hsv.v;
1681
+ var ret = [];
1682
+ var modification = 1 / results;
1683
+
1684
+ while (results--) {
1685
+ ret.push(tinycolor({ h: h, s: s, v: v}));
1686
+ v = (v + modification) % 1;
1687
+ }
1655
1688
 
1689
+ return ret;
1690
+ };
1656
1691
 
1657
- // Readability Functions
1658
- // ---------------------
1659
- // <http://www.w3.org/TR/AERT#color-contrast>
1660
-
1661
- // `readability`
1662
- // Analyze the 2 colors and returns an object with the following properties:
1663
- // `brightness`: difference in brightness between the two colors
1664
- // `color`: difference in color/hue between the two colors
1665
- tinycolor.readability = function(color1, color2) {
1666
- var a = tinycolor(color1).toRgb();
1667
- var b = tinycolor(color2).toRgb();
1668
- var brightnessA = (a.r * 299 + a.g * 587 + a.b * 114) / 1000;
1669
- var brightnessB = (b.r * 299 + b.g * 587 + b.b * 114) / 1000;
1670
- var colorDiff = (
1671
- Math.max(a.r, b.r) - Math.min(a.r, b.r) +
1672
- Math.max(a.g, b.g) - Math.min(a.g, b.g) +
1673
- Math.max(a.b, b.b) - Math.min(a.b, b.b)
1674
- );
1675
1692
 
1676
- return {
1677
- brightness: Math.abs(brightnessA - brightnessB),
1678
- color: colorDiff
1679
- };
1693
+ // Readability Functions
1694
+ // ---------------------
1695
+ // <http://www.w3.org/TR/AERT#color-contrast>
1696
+
1697
+ // `readability`
1698
+ // Analyze the 2 colors and returns an object with the following properties:
1699
+ // `brightness`: difference in brightness between the two colors
1700
+ // `color`: difference in color/hue between the two colors
1701
+ tinycolor.readability = function(color1, color2) {
1702
+ var a = tinycolor(color1).toRgb();
1703
+ var b = tinycolor(color2).toRgb();
1704
+ var brightnessA = (a.r * 299 + a.g * 587 + a.b * 114) / 1000;
1705
+ var brightnessB = (b.r * 299 + b.g * 587 + b.b * 114) / 1000;
1706
+ var colorDiff = (
1707
+ Math.max(a.r, b.r) - Math.min(a.r, b.r) +
1708
+ Math.max(a.g, b.g) - Math.min(a.g, b.g) +
1709
+ Math.max(a.b, b.b) - Math.min(a.b, b.b)
1710
+ );
1711
+
1712
+ return {
1713
+ brightness: Math.abs(brightnessA - brightnessB),
1714
+ color: colorDiff
1680
1715
  };
1716
+ };
1681
1717
 
1682
- // `readable`
1683
- // http://www.w3.org/TR/AERT#color-contrast
1684
- // Ensure that foreground and background color combinations provide sufficient contrast.
1685
- // *Example*
1686
- // tinycolor.readable("#000", "#111") => false
1687
- tinycolor.readable = function(color1, color2) {
1688
- var readability = tinycolor.readability(color1, color2);
1689
- return readability.brightness > 125 && readability.color > 500;
1690
- };
1718
+ // `readable`
1719
+ // http://www.w3.org/TR/AERT#color-contrast
1720
+ // Ensure that foreground and background color combinations provide sufficient contrast.
1721
+ // *Example*
1722
+ // tinycolor.readable("#000", "#111") => false
1723
+ tinycolor.readable = function(color1, color2) {
1724
+ var readability = tinycolor.readability(color1, color2);
1725
+ return readability.brightness > 125 && readability.color > 500;
1726
+ };
1691
1727
 
1692
- // `mostReadable`
1693
- // Given a base color and a list of possible foreground or background
1694
- // colors for that base, returns the most readable color.
1695
- // *Example*
1696
- // tinycolor.mostReadable("#123", ["#fff", "#000"]) => "#000"
1697
- tinycolor.mostReadable = function(baseColor, colorList) {
1698
- var bestColor = null;
1699
- var bestScore = 0;
1700
- var bestIsReadable = false;
1701
- for (var i=0; i < colorList.length; i++) {
1702
-
1703
- // We normalize both around the "acceptable" breaking point,
1704
- // but rank brightness constrast higher than hue.
1705
-
1706
- var readability = tinycolor.readability(baseColor, colorList[i]);
1707
- var readable = readability.brightness > 125 && readability.color > 500;
1708
- var score = 3 * (readability.brightness / 125) + (readability.color / 500);
1709
-
1710
- if ((readable && ! bestIsReadable) ||
1711
- (readable && bestIsReadable && score > bestScore) ||
1712
- ((! readable) && (! bestIsReadable) && score > bestScore)) {
1713
- bestIsReadable = readable;
1714
- bestScore = score;
1715
- bestColor = tinycolor(colorList[i]);
1716
- }
1728
+ // `mostReadable`
1729
+ // Given a base color and a list of possible foreground or background
1730
+ // colors for that base, returns the most readable color.
1731
+ // *Example*
1732
+ // tinycolor.mostReadable("#123", ["#fff", "#000"]) => "#000"
1733
+ tinycolor.mostReadable = function(baseColor, colorList) {
1734
+ var bestColor = null;
1735
+ var bestScore = 0;
1736
+ var bestIsReadable = false;
1737
+ for (var i=0; i < colorList.length; i++) {
1738
+
1739
+ // We normalize both around the "acceptable" breaking point,
1740
+ // but rank brightness constrast higher than hue.
1741
+
1742
+ var readability = tinycolor.readability(baseColor, colorList[i]);
1743
+ var readable = readability.brightness > 125 && readability.color > 500;
1744
+ var score = 3 * (readability.brightness / 125) + (readability.color / 500);
1745
+
1746
+ if ((readable && ! bestIsReadable) ||
1747
+ (readable && bestIsReadable && score > bestScore) ||
1748
+ ((! readable) && (! bestIsReadable) && score > bestScore)) {
1749
+ bestIsReadable = readable;
1750
+ bestScore = score;
1751
+ bestColor = tinycolor(colorList[i]);
1717
1752
  }
1718
- return bestColor;
1719
- };
1753
+ }
1754
+ return bestColor;
1755
+ };
1720
1756
 
1721
1757
 
1722
- // Big List of Colors
1723
- // ------------------
1724
- // <http://www.w3.org/TR/css3-color/#svg-color>
1725
- var names = tinycolor.names = {
1726
- aliceblue: "f0f8ff",
1727
- antiquewhite: "faebd7",
1728
- aqua: "0ff",
1729
- aquamarine: "7fffd4",
1730
- azure: "f0ffff",
1731
- beige: "f5f5dc",
1732
- bisque: "ffe4c4",
1733
- black: "000",
1734
- blanchedalmond: "ffebcd",
1735
- blue: "00f",
1736
- blueviolet: "8a2be2",
1737
- brown: "a52a2a",
1738
- burlywood: "deb887",
1739
- burntsienna: "ea7e5d",
1740
- cadetblue: "5f9ea0",
1741
- chartreuse: "7fff00",
1742
- chocolate: "d2691e",
1743
- coral: "ff7f50",
1744
- cornflowerblue: "6495ed",
1745
- cornsilk: "fff8dc",
1746
- crimson: "dc143c",
1747
- cyan: "0ff",
1748
- darkblue: "00008b",
1749
- darkcyan: "008b8b",
1750
- darkgoldenrod: "b8860b",
1751
- darkgray: "a9a9a9",
1752
- darkgreen: "006400",
1753
- darkgrey: "a9a9a9",
1754
- darkkhaki: "bdb76b",
1755
- darkmagenta: "8b008b",
1756
- darkolivegreen: "556b2f",
1757
- darkorange: "ff8c00",
1758
- darkorchid: "9932cc",
1759
- darkred: "8b0000",
1760
- darksalmon: "e9967a",
1761
- darkseagreen: "8fbc8f",
1762
- darkslateblue: "483d8b",
1763
- darkslategray: "2f4f4f",
1764
- darkslategrey: "2f4f4f",
1765
- darkturquoise: "00ced1",
1766
- darkviolet: "9400d3",
1767
- deeppink: "ff1493",
1768
- deepskyblue: "00bfff",
1769
- dimgray: "696969",
1770
- dimgrey: "696969",
1771
- dodgerblue: "1e90ff",
1772
- firebrick: "b22222",
1773
- floralwhite: "fffaf0",
1774
- forestgreen: "228b22",
1775
- fuchsia: "f0f",
1776
- gainsboro: "dcdcdc",
1777
- ghostwhite: "f8f8ff",
1778
- gold: "ffd700",
1779
- goldenrod: "daa520",
1780
- gray: "808080",
1781
- green: "008000",
1782
- greenyellow: "adff2f",
1783
- grey: "808080",
1784
- honeydew: "f0fff0",
1785
- hotpink: "ff69b4",
1786
- indianred: "cd5c5c",
1787
- indigo: "4b0082",
1788
- ivory: "fffff0",
1789
- khaki: "f0e68c",
1790
- lavender: "e6e6fa",
1791
- lavenderblush: "fff0f5",
1792
- lawngreen: "7cfc00",
1793
- lemonchiffon: "fffacd",
1794
- lightblue: "add8e6",
1795
- lightcoral: "f08080",
1796
- lightcyan: "e0ffff",
1797
- lightgoldenrodyellow: "fafad2",
1798
- lightgray: "d3d3d3",
1799
- lightgreen: "90ee90",
1800
- lightgrey: "d3d3d3",
1801
- lightpink: "ffb6c1",
1802
- lightsalmon: "ffa07a",
1803
- lightseagreen: "20b2aa",
1804
- lightskyblue: "87cefa",
1805
- lightslategray: "789",
1806
- lightslategrey: "789",
1807
- lightsteelblue: "b0c4de",
1808
- lightyellow: "ffffe0",
1809
- lime: "0f0",
1810
- limegreen: "32cd32",
1811
- linen: "faf0e6",
1812
- magenta: "f0f",
1813
- maroon: "800000",
1814
- mediumaquamarine: "66cdaa",
1815
- mediumblue: "0000cd",
1816
- mediumorchid: "ba55d3",
1817
- mediumpurple: "9370db",
1818
- mediumseagreen: "3cb371",
1819
- mediumslateblue: "7b68ee",
1820
- mediumspringgreen: "00fa9a",
1821
- mediumturquoise: "48d1cc",
1822
- mediumvioletred: "c71585",
1823
- midnightblue: "191970",
1824
- mintcream: "f5fffa",
1825
- mistyrose: "ffe4e1",
1826
- moccasin: "ffe4b5",
1827
- navajowhite: "ffdead",
1828
- navy: "000080",
1829
- oldlace: "fdf5e6",
1830
- olive: "808000",
1831
- olivedrab: "6b8e23",
1832
- orange: "ffa500",
1833
- orangered: "ff4500",
1834
- orchid: "da70d6",
1835
- palegoldenrod: "eee8aa",
1836
- palegreen: "98fb98",
1837
- paleturquoise: "afeeee",
1838
- palevioletred: "db7093",
1839
- papayawhip: "ffefd5",
1840
- peachpuff: "ffdab9",
1841
- peru: "cd853f",
1842
- pink: "ffc0cb",
1843
- plum: "dda0dd",
1844
- powderblue: "b0e0e6",
1845
- purple: "800080",
1846
- red: "f00",
1847
- rosybrown: "bc8f8f",
1848
- royalblue: "4169e1",
1849
- saddlebrown: "8b4513",
1850
- salmon: "fa8072",
1851
- sandybrown: "f4a460",
1852
- seagreen: "2e8b57",
1853
- seashell: "fff5ee",
1854
- sienna: "a0522d",
1855
- silver: "c0c0c0",
1856
- skyblue: "87ceeb",
1857
- slateblue: "6a5acd",
1858
- slategray: "708090",
1859
- slategrey: "708090",
1860
- snow: "fffafa",
1861
- springgreen: "00ff7f",
1862
- steelblue: "4682b4",
1863
- tan: "d2b48c",
1864
- teal: "008080",
1865
- thistle: "d8bfd8",
1866
- tomato: "ff6347",
1867
- turquoise: "40e0d0",
1868
- violet: "ee82ee",
1869
- wheat: "f5deb3",
1870
- white: "fff",
1871
- whitesmoke: "f5f5f5",
1872
- yellow: "ff0",
1873
- yellowgreen: "9acd32"
1874
- };
1758
+ // Big List of Colors
1759
+ // ------------------
1760
+ // <http://www.w3.org/TR/css3-color/#svg-color>
1761
+ var names = tinycolor.names = {
1762
+ aliceblue: "f0f8ff",
1763
+ antiquewhite: "faebd7",
1764
+ aqua: "0ff",
1765
+ aquamarine: "7fffd4",
1766
+ azure: "f0ffff",
1767
+ beige: "f5f5dc",
1768
+ bisque: "ffe4c4",
1769
+ black: "000",
1770
+ blanchedalmond: "ffebcd",
1771
+ blue: "00f",
1772
+ blueviolet: "8a2be2",
1773
+ brown: "a52a2a",
1774
+ burlywood: "deb887",
1775
+ burntsienna: "ea7e5d",
1776
+ cadetblue: "5f9ea0",
1777
+ chartreuse: "7fff00",
1778
+ chocolate: "d2691e",
1779
+ coral: "ff7f50",
1780
+ cornflowerblue: "6495ed",
1781
+ cornsilk: "fff8dc",
1782
+ crimson: "dc143c",
1783
+ cyan: "0ff",
1784
+ darkblue: "00008b",
1785
+ darkcyan: "008b8b",
1786
+ darkgoldenrod: "b8860b",
1787
+ darkgray: "a9a9a9",
1788
+ darkgreen: "006400",
1789
+ darkgrey: "a9a9a9",
1790
+ darkkhaki: "bdb76b",
1791
+ darkmagenta: "8b008b",
1792
+ darkolivegreen: "556b2f",
1793
+ darkorange: "ff8c00",
1794
+ darkorchid: "9932cc",
1795
+ darkred: "8b0000",
1796
+ darksalmon: "e9967a",
1797
+ darkseagreen: "8fbc8f",
1798
+ darkslateblue: "483d8b",
1799
+ darkslategray: "2f4f4f",
1800
+ darkslategrey: "2f4f4f",
1801
+ darkturquoise: "00ced1",
1802
+ darkviolet: "9400d3",
1803
+ deeppink: "ff1493",
1804
+ deepskyblue: "00bfff",
1805
+ dimgray: "696969",
1806
+ dimgrey: "696969",
1807
+ dodgerblue: "1e90ff",
1808
+ firebrick: "b22222",
1809
+ floralwhite: "fffaf0",
1810
+ forestgreen: "228b22",
1811
+ fuchsia: "f0f",
1812
+ gainsboro: "dcdcdc",
1813
+ ghostwhite: "f8f8ff",
1814
+ gold: "ffd700",
1815
+ goldenrod: "daa520",
1816
+ gray: "808080",
1817
+ green: "008000",
1818
+ greenyellow: "adff2f",
1819
+ grey: "808080",
1820
+ honeydew: "f0fff0",
1821
+ hotpink: "ff69b4",
1822
+ indianred: "cd5c5c",
1823
+ indigo: "4b0082",
1824
+ ivory: "fffff0",
1825
+ khaki: "f0e68c",
1826
+ lavender: "e6e6fa",
1827
+ lavenderblush: "fff0f5",
1828
+ lawngreen: "7cfc00",
1829
+ lemonchiffon: "fffacd",
1830
+ lightblue: "add8e6",
1831
+ lightcoral: "f08080",
1832
+ lightcyan: "e0ffff",
1833
+ lightgoldenrodyellow: "fafad2",
1834
+ lightgray: "d3d3d3",
1835
+ lightgreen: "90ee90",
1836
+ lightgrey: "d3d3d3",
1837
+ lightpink: "ffb6c1",
1838
+ lightsalmon: "ffa07a",
1839
+ lightseagreen: "20b2aa",
1840
+ lightskyblue: "87cefa",
1841
+ lightslategray: "789",
1842
+ lightslategrey: "789",
1843
+ lightsteelblue: "b0c4de",
1844
+ lightyellow: "ffffe0",
1845
+ lime: "0f0",
1846
+ limegreen: "32cd32",
1847
+ linen: "faf0e6",
1848
+ magenta: "f0f",
1849
+ maroon: "800000",
1850
+ mediumaquamarine: "66cdaa",
1851
+ mediumblue: "0000cd",
1852
+ mediumorchid: "ba55d3",
1853
+ mediumpurple: "9370db",
1854
+ mediumseagreen: "3cb371",
1855
+ mediumslateblue: "7b68ee",
1856
+ mediumspringgreen: "00fa9a",
1857
+ mediumturquoise: "48d1cc",
1858
+ mediumvioletred: "c71585",
1859
+ midnightblue: "191970",
1860
+ mintcream: "f5fffa",
1861
+ mistyrose: "ffe4e1",
1862
+ moccasin: "ffe4b5",
1863
+ navajowhite: "ffdead",
1864
+ navy: "000080",
1865
+ oldlace: "fdf5e6",
1866
+ olive: "808000",
1867
+ olivedrab: "6b8e23",
1868
+ orange: "ffa500",
1869
+ orangered: "ff4500",
1870
+ orchid: "da70d6",
1871
+ palegoldenrod: "eee8aa",
1872
+ palegreen: "98fb98",
1873
+ paleturquoise: "afeeee",
1874
+ palevioletred: "db7093",
1875
+ papayawhip: "ffefd5",
1876
+ peachpuff: "ffdab9",
1877
+ peru: "cd853f",
1878
+ pink: "ffc0cb",
1879
+ plum: "dda0dd",
1880
+ powderblue: "b0e0e6",
1881
+ purple: "800080",
1882
+ red: "f00",
1883
+ rosybrown: "bc8f8f",
1884
+ royalblue: "4169e1",
1885
+ saddlebrown: "8b4513",
1886
+ salmon: "fa8072",
1887
+ sandybrown: "f4a460",
1888
+ seagreen: "2e8b57",
1889
+ seashell: "fff5ee",
1890
+ sienna: "a0522d",
1891
+ silver: "c0c0c0",
1892
+ skyblue: "87ceeb",
1893
+ slateblue: "6a5acd",
1894
+ slategray: "708090",
1895
+ slategrey: "708090",
1896
+ snow: "fffafa",
1897
+ springgreen: "00ff7f",
1898
+ steelblue: "4682b4",
1899
+ tan: "d2b48c",
1900
+ teal: "008080",
1901
+ thistle: "d8bfd8",
1902
+ tomato: "ff6347",
1903
+ turquoise: "40e0d0",
1904
+ violet: "ee82ee",
1905
+ wheat: "f5deb3",
1906
+ white: "fff",
1907
+ whitesmoke: "f5f5f5",
1908
+ yellow: "ff0",
1909
+ yellowgreen: "9acd32"
1910
+ };
1875
1911
 
1876
- // Make it easy to access colors via `hexNames[hex]`
1877
- var hexNames = tinycolor.hexNames = flip(names);
1912
+ // Make it easy to access colors via `hexNames[hex]`
1913
+ var hexNames = tinycolor.hexNames = flip(names);
1878
1914
 
1879
1915
 
1880
- // Utilities
1881
- // ---------
1916
+ // Utilities
1917
+ // ---------
1882
1918
 
1883
- // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
1884
- function flip(o) {
1885
- var flipped = { };
1886
- for (var i in o) {
1887
- if (o.hasOwnProperty(i)) {
1888
- flipped[o[i]] = i;
1889
- }
1919
+ // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
1920
+ function flip(o) {
1921
+ var flipped = { };
1922
+ for (var i in o) {
1923
+ if (o.hasOwnProperty(i)) {
1924
+ flipped[o[i]] = i;
1890
1925
  }
1891
- return flipped;
1892
1926
  }
1927
+ return flipped;
1928
+ }
1893
1929
 
1894
- // Return a valid alpha value [0,1] with all invalid values being set to 1
1895
- function boundAlpha(a) {
1896
- a = parseFloat(a);
1930
+ // Return a valid alpha value [0,1] with all invalid values being set to 1
1931
+ function boundAlpha(a) {
1932
+ a = parseFloat(a);
1897
1933
 
1898
- if (isNaN(a) || a < 0 || a > 1) {
1899
- a = 1;
1900
- }
1901
-
1902
- return a;
1934
+ if (isNaN(a) || a < 0 || a > 1) {
1935
+ a = 1;
1903
1936
  }
1904
1937
 
1905
- // Take input from [0, n] and return it as [0, 1]
1906
- function bound01(n, max) {
1907
- if (isOnePointZero(n)) { n = "100%"; }
1908
-
1909
- var processPercent = isPercentage(n);
1910
- n = mathMin(max, mathMax(0, parseFloat(n)));
1938
+ return a;
1939
+ }
1911
1940
 
1912
- // Automatically convert percentage into number
1913
- if (processPercent) {
1914
- n = parseInt(n * max, 10) / 100;
1915
- }
1941
+ // Take input from [0, n] and return it as [0, 1]
1942
+ function bound01(n, max) {
1943
+ if (isOnePointZero(n)) { n = "100%"; }
1916
1944
 
1917
- // Handle floating point rounding errors
1918
- if ((math.abs(n - max) < 0.000001)) {
1919
- return 1;
1920
- }
1945
+ var processPercent = isPercentage(n);
1946
+ n = mathMin(max, mathMax(0, parseFloat(n)));
1921
1947
 
1922
- // Convert into [0, 1] range if it isn't already
1923
- return (n % max) / parseFloat(max);
1948
+ // Automatically convert percentage into number
1949
+ if (processPercent) {
1950
+ n = parseInt(n * max, 10) / 100;
1924
1951
  }
1925
1952
 
1926
- // Force a number between 0 and 1
1927
- function clamp01(val) {
1928
- return mathMin(1, mathMax(0, val));
1953
+ // Handle floating point rounding errors
1954
+ if ((math.abs(n - max) < 0.000001)) {
1955
+ return 1;
1929
1956
  }
1930
1957
 
1931
- // Parse a base-16 hex value into a base-10 integer
1932
- function parseIntFromHex(val) {
1933
- return parseInt(val, 16);
1934
- }
1958
+ // Convert into [0, 1] range if it isn't already
1959
+ return (n % max) / parseFloat(max);
1960
+ }
1935
1961
 
1936
- // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
1937
- // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
1938
- function isOnePointZero(n) {
1939
- return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1;
1940
- }
1962
+ // Force a number between 0 and 1
1963
+ function clamp01(val) {
1964
+ return mathMin(1, mathMax(0, val));
1965
+ }
1941
1966
 
1942
- // Check to see if string passed in is a percentage
1943
- function isPercentage(n) {
1944
- return typeof n === "string" && n.indexOf('%') != -1;
1945
- }
1967
+ // Parse a base-16 hex value into a base-10 integer
1968
+ function parseIntFromHex(val) {
1969
+ return parseInt(val, 16);
1970
+ }
1946
1971
 
1947
- // Force a hex value to have 2 characters
1948
- function pad2(c) {
1949
- return c.length == 1 ? '0' + c : '' + c;
1950
- }
1972
+ // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
1973
+ // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
1974
+ function isOnePointZero(n) {
1975
+ return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1;
1976
+ }
1951
1977
 
1952
- // Replace a decimal with it's percentage value
1953
- function convertToPercentage(n) {
1954
- if (n <= 1) {
1955
- n = (n * 100) + "%";
1956
- }
1978
+ // Check to see if string passed in is a percentage
1979
+ function isPercentage(n) {
1980
+ return typeof n === "string" && n.indexOf('%') != -1;
1981
+ }
1957
1982
 
1958
- return n;
1959
- }
1983
+ // Force a hex value to have 2 characters
1984
+ function pad2(c) {
1985
+ return c.length == 1 ? '0' + c : '' + c;
1986
+ }
1960
1987
 
1961
- // Converts a decimal to a hex value
1962
- function convertDecimalToHex(d) {
1963
- return Math.round(parseFloat(d) * 255).toString(16);
1964
- }
1965
- // Converts a hex value to a decimal
1966
- function convertHexToDecimal(h) {
1967
- return (parseIntFromHex(h) / 255);
1988
+ // Replace a decimal with it's percentage value
1989
+ function convertToPercentage(n) {
1990
+ if (n <= 1) {
1991
+ n = (n * 100) + "%";
1968
1992
  }
1969
1993
 
1970
- var matchers = (function() {
1994
+ return n;
1995
+ }
1971
1996
 
1972
- // <http://www.w3.org/TR/css3-values/#integers>
1973
- var CSS_INTEGER = "[-\\+]?\\d+%?";
1997
+ // Converts a decimal to a hex value
1998
+ function convertDecimalToHex(d) {
1999
+ return Math.round(parseFloat(d) * 255).toString(16);
2000
+ }
2001
+ // Converts a hex value to a decimal
2002
+ function convertHexToDecimal(h) {
2003
+ return (parseIntFromHex(h) / 255);
2004
+ }
1974
2005
 
1975
- // <http://www.w3.org/TR/css3-values/#number-value>
1976
- var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?";
2006
+ var matchers = (function() {
1977
2007
 
1978
- // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome.
1979
- var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")";
2008
+ // <http://www.w3.org/TR/css3-values/#integers>
2009
+ var CSS_INTEGER = "[-\\+]?\\d+%?";
1980
2010
 
1981
- // Actual matching.
1982
- // Parentheses and commas are optional, but not required.
1983
- // Whitespace can take the place of commas or opening paren
1984
- var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
1985
- var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
2011
+ // <http://www.w3.org/TR/css3-values/#number-value>
2012
+ var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?";
1986
2013
 
1987
- return {
1988
- rgb: new RegExp("rgb" + PERMISSIVE_MATCH3),
1989
- rgba: new RegExp("rgba" + PERMISSIVE_MATCH4),
1990
- hsl: new RegExp("hsl" + PERMISSIVE_MATCH3),
1991
- hsla: new RegExp("hsla" + PERMISSIVE_MATCH4),
1992
- hsv: new RegExp("hsv" + PERMISSIVE_MATCH3),
1993
- hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
1994
- hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
1995
- hex8: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/
1996
- };
1997
- })();
2014
+ // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome.
2015
+ var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")";
1998
2016
 
1999
- // `stringInputToObject`
2000
- // Permissive string parsing. Take in a number of formats, and output an object
2001
- // based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
2002
- function stringInputToObject(color) {
2017
+ // Actual matching.
2018
+ // Parentheses and commas are optional, but not required.
2019
+ // Whitespace can take the place of commas or opening paren
2020
+ var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
2021
+ var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
2003
2022
 
2004
- color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase();
2005
- var named = false;
2006
- if (names[color]) {
2007
- color = names[color];
2008
- named = true;
2009
- }
2010
- else if (color == 'transparent') {
2011
- return { r: 0, g: 0, b: 0, a: 0, format: "name" };
2012
- }
2023
+ return {
2024
+ rgb: new RegExp("rgb" + PERMISSIVE_MATCH3),
2025
+ rgba: new RegExp("rgba" + PERMISSIVE_MATCH4),
2026
+ hsl: new RegExp("hsl" + PERMISSIVE_MATCH3),
2027
+ hsla: new RegExp("hsla" + PERMISSIVE_MATCH4),
2028
+ hsv: new RegExp("hsv" + PERMISSIVE_MATCH3),
2029
+ hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
2030
+ hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
2031
+ hex8: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/
2032
+ };
2033
+ })();
2013
2034
 
2014
- // Try to match string input using regular expressions.
2015
- // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
2016
- // Just return an object and let the conversion functions handle that.
2017
- // This way the result will be the same whether the tinycolor is initialized with string or object.
2018
- var match;
2019
- if ((match = matchers.rgb.exec(color))) {
2020
- return { r: match[1], g: match[2], b: match[3] };
2021
- }
2022
- if ((match = matchers.rgba.exec(color))) {
2023
- return { r: match[1], g: match[2], b: match[3], a: match[4] };
2024
- }
2025
- if ((match = matchers.hsl.exec(color))) {
2026
- return { h: match[1], s: match[2], l: match[3] };
2027
- }
2028
- if ((match = matchers.hsla.exec(color))) {
2029
- return { h: match[1], s: match[2], l: match[3], a: match[4] };
2030
- }
2031
- if ((match = matchers.hsv.exec(color))) {
2032
- return { h: match[1], s: match[2], v: match[3] };
2033
- }
2034
- if ((match = matchers.hex8.exec(color))) {
2035
- return {
2036
- a: convertHexToDecimal(match[1]),
2037
- r: parseIntFromHex(match[2]),
2038
- g: parseIntFromHex(match[3]),
2039
- b: parseIntFromHex(match[4]),
2040
- format: named ? "name" : "hex8"
2041
- };
2042
- }
2043
- if ((match = matchers.hex6.exec(color))) {
2044
- return {
2045
- r: parseIntFromHex(match[1]),
2046
- g: parseIntFromHex(match[2]),
2047
- b: parseIntFromHex(match[3]),
2048
- format: named ? "name" : "hex"
2049
- };
2050
- }
2051
- if ((match = matchers.hex3.exec(color))) {
2052
- return {
2053
- r: parseIntFromHex(match[1] + '' + match[1]),
2054
- g: parseIntFromHex(match[2] + '' + match[2]),
2055
- b: parseIntFromHex(match[3] + '' + match[3]),
2056
- format: named ? "name" : "hex"
2057
- };
2058
- }
2035
+ // `stringInputToObject`
2036
+ // Permissive string parsing. Take in a number of formats, and output an object
2037
+ // based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
2038
+ function stringInputToObject(color) {
2059
2039
 
2060
- return false;
2040
+ color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase();
2041
+ var named = false;
2042
+ if (names[color]) {
2043
+ color = names[color];
2044
+ named = true;
2045
+ }
2046
+ else if (color == 'transparent') {
2047
+ return { r: 0, g: 0, b: 0, a: 0, format: "name" };
2048
+ }
2049
+
2050
+ // Try to match string input using regular expressions.
2051
+ // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
2052
+ // Just return an object and let the conversion functions handle that.
2053
+ // This way the result will be the same whether the tinycolor is initialized with string or object.
2054
+ var match;
2055
+ if ((match = matchers.rgb.exec(color))) {
2056
+ return { r: match[1], g: match[2], b: match[3] };
2057
+ }
2058
+ if ((match = matchers.rgba.exec(color))) {
2059
+ return { r: match[1], g: match[2], b: match[3], a: match[4] };
2060
+ }
2061
+ if ((match = matchers.hsl.exec(color))) {
2062
+ return { h: match[1], s: match[2], l: match[3] };
2063
+ }
2064
+ if ((match = matchers.hsla.exec(color))) {
2065
+ return { h: match[1], s: match[2], l: match[3], a: match[4] };
2066
+ }
2067
+ if ((match = matchers.hsv.exec(color))) {
2068
+ return { h: match[1], s: match[2], v: match[3] };
2069
+ }
2070
+ if ((match = matchers.hex8.exec(color))) {
2071
+ return {
2072
+ a: convertHexToDecimal(match[1]),
2073
+ r: parseIntFromHex(match[2]),
2074
+ g: parseIntFromHex(match[3]),
2075
+ b: parseIntFromHex(match[4]),
2076
+ format: named ? "name" : "hex8"
2077
+ };
2078
+ }
2079
+ if ((match = matchers.hex6.exec(color))) {
2080
+ return {
2081
+ r: parseIntFromHex(match[1]),
2082
+ g: parseIntFromHex(match[2]),
2083
+ b: parseIntFromHex(match[3]),
2084
+ format: named ? "name" : "hex"
2085
+ };
2086
+ }
2087
+ if ((match = matchers.hex3.exec(color))) {
2088
+ return {
2089
+ r: parseIntFromHex(match[1] + '' + match[1]),
2090
+ g: parseIntFromHex(match[2] + '' + match[2]),
2091
+ b: parseIntFromHex(match[3] + '' + match[3]),
2092
+ format: named ? "name" : "hex"
2093
+ };
2061
2094
  }
2062
2095
 
2063
- // Expose tinycolor to window, does not need to run in non-browser context.
2064
- window.tinycolor = tinycolor;
2096
+ return false;
2097
+ }
2065
2098
 
2099
+ window.tinycolor = tinycolor;
2066
2100
  })();
2067
2101
 
2068
2102