spectrum-rails 1.0.9 → 1.1.1

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.
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  # Spectrum::Rails
2
2
 
3
- TODO: Write a gem description
3
+ A ruby gem that uses the Rails asset pipeline to include the Spectrum jQuery plugin by Brian Grinstead (@bgrins):
4
+
5
+ * Homepage: http://bgrins.github.com/spectrum/
6
+ * Source Code: https://github.com/bgrins/spectrum
4
7
 
5
8
  ## Installation
6
9
 
@@ -16,9 +19,19 @@ Or install it yourself as:
16
19
 
17
20
  $ gem install spectrum-rails
18
21
 
22
+ NOTE: this is a jQuery plugin so you will also need the `jquery-rails` gem:
23
+
24
+ * https://github.com/rails/jquery-rails
25
+
19
26
  ## Usage
20
27
 
21
- TODO: Write usage instructions here
28
+ In your `application.js` you will need to add this line:
29
+
30
+ //= require spectrum
31
+
32
+ And in your `application.css` you will need to add this line:
33
+
34
+ *= require spectrum
22
35
 
23
36
  ## Contributing
24
37
 
@@ -1,5 +1,5 @@
1
1
  module Spectrum
2
2
  module Rails
3
- VERSION = "1.0.9"
3
+ VERSION = "1.1.1"
4
4
  end
5
5
  end
@@ -1,4 +1,4 @@
1
- // Spectrum Colorpicker v1.0.9
1
+ // Spectrum Colorpicker v1.1.1
2
2
  // https://github.com/bgrins/spectrum
3
3
  // Author: Brian Grinstead
4
4
  // License: MIT
@@ -6,7 +6,7 @@
6
6
  (function (window, $, undefined) {
7
7
  var defaultOpts = {
8
8
 
9
- // Events
9
+ // Callbacks
10
10
  beforeShow: noop,
11
11
  move: noop,
12
12
  change: noop,
@@ -24,6 +24,7 @@
24
24
  showPaletteOnly: false,
25
25
  showSelectionPalette: true,
26
26
  localStorageKey: false,
27
+ appendTo: "body",
27
28
  maxSelectionSize: 7,
28
29
  cancelText: "cancel",
29
30
  chooseText: "choose",
@@ -65,7 +66,7 @@
65
66
  }
66
67
 
67
68
  return [
68
- "<div class='sp-container'>",
69
+ "<div class='sp-container sp-hidden'>",
69
70
  "<div class='sp-palette-container'>",
70
71
  "<div class='sp-palette sp-thumb sp-cf'></div>",
71
72
  "</div>",
@@ -159,7 +160,9 @@
159
160
  palette = opts.palette.slice(0),
160
161
  paletteArray = $.isArray(palette[0]) ? palette : [palette],
161
162
  selectionPalette = opts.selectionPalette.slice(0),
162
- draggingClass = "sp-dragging";
163
+ maxSelectionSize = opts.maxSelectionSize,
164
+ draggingClass = "sp-dragging",
165
+ shiftMovementDirection = null;
163
166
 
164
167
  var doc = element.ownerDocument,
165
168
  body = doc.body,
@@ -180,7 +183,7 @@
180
183
  chooseButton = container.find(".sp-choose"),
181
184
  isInput = boundElement.is("input"),
182
185
  shouldReplace = isInput && !flat,
183
- replacer = (shouldReplace) ? $(replaceInput).addClass(theme) : $([]),
186
+ replacer = (shouldReplace) ? $(replaceInput).addClass(theme).addClass(opts.className) : $([]),
184
187
  offsetElement = (shouldReplace) ? replacer : boundElement,
185
188
  previewElement = replacer.find(".sp-preview-inner"),
186
189
  initialColor = opts.color || (isInput && boundElement.val()),
@@ -195,7 +198,7 @@
195
198
  container.toggleClass("sp-flat", flat);
196
199
  container.toggleClass("sp-input-disabled", !opts.showInput);
197
200
  container.toggleClass("sp-alpha-enabled", opts.showAlpha);
198
- container.toggleClass("sp-buttons-disabled", !opts.showButtons || flat);
201
+ container.toggleClass("sp-buttons-disabled", !opts.showButtons);
199
202
  container.toggleClass("sp-palette-disabled", !opts.showPalette);
200
203
  container.toggleClass("sp-palette-only", opts.showPaletteOnly);
201
204
  container.toggleClass("sp-initial-disabled", !opts.showInitial);
@@ -213,14 +216,20 @@
213
216
  applyOptions();
214
217
 
215
218
  if (shouldReplace) {
216
- boundElement.hide().after(replacer);
219
+ boundElement.after(replacer).hide();
217
220
  }
218
221
 
219
222
  if (flat) {
220
223
  boundElement.after(container).hide();
221
224
  }
222
225
  else {
223
- $(body).append(container.hide());
226
+
227
+ var appendTo = opts.appendTo === "parent" ? boundElement.parent() : $(opts.appendTo);
228
+ if (appendTo.length !== 1) {
229
+ appendTo = $("body");
230
+ }
231
+
232
+ appendTo.append(container);
224
233
  }
225
234
 
226
235
  if (localStorageKey && window.localStorage) {
@@ -301,10 +310,32 @@
301
310
  move();
302
311
  }, dragStart, dragStop);
303
312
 
304
- draggable(dragger, function (dragX, dragY) {
305
- currentSaturation = parseFloat(dragX / dragWidth);
306
- currentValue = parseFloat((dragHeight - dragY) / dragHeight);
313
+ draggable(dragger, function (dragX, dragY, e) {
314
+
315
+ // shift+drag should snap the movement to either the x or y axis.
316
+ if (!e.shiftKey) {
317
+ shiftMovementDirection = null;
318
+ }
319
+ else if (!shiftMovementDirection) {
320
+ var oldDragX = currentSaturation * dragWidth;
321
+ var oldDragY = dragHeight - (currentValue * dragHeight);
322
+ var furtherFromX = Math.abs(dragX - oldDragX) > Math.abs(dragY - oldDragY);
323
+
324
+ shiftMovementDirection = furtherFromX ? "x" : "y";
325
+ }
326
+
327
+ var setSaturation = !shiftMovementDirection || shiftMovementDirection === "x";
328
+ var setValue = !shiftMovementDirection || shiftMovementDirection === "y";
329
+
330
+ if (setSaturation) {
331
+ currentSaturation = parseFloat(dragX / dragWidth);
332
+ }
333
+ if (setValue) {
334
+ currentValue = parseFloat((dragHeight - dragY) / dragHeight);
335
+ }
336
+
307
337
  move();
338
+
308
339
  }, dragStart, dragStop);
309
340
 
310
341
  if (!!initialColor) {
@@ -350,6 +381,9 @@
350
381
  var colorRgb = tinycolor(color).toRgbString();
351
382
  if ($.inArray(colorRgb, selectionPalette) === -1) {
352
383
  selectionPalette.push(colorRgb);
384
+ while(selectionPalette.length > maxSelectionSize) {
385
+ selectionPalette.shift();
386
+ }
353
387
  }
354
388
 
355
389
  if (localStorageKey && window.localStorage) {
@@ -413,10 +447,11 @@
413
447
  }
414
448
 
415
449
  function dragStart() {
416
- if (dragHeight === 0 || dragWidth === 0 || slideHeight === 0) {
450
+ if (dragHeight <= 0 || dragWidth <= 0 || slideHeight <= 0) {
417
451
  reflow();
418
452
  }
419
453
  container.addClass(draggingClass);
454
+ shiftMovementDirection = null;
420
455
  }
421
456
 
422
457
  function dragStop() {
@@ -443,11 +478,18 @@
443
478
  }
444
479
 
445
480
  function show() {
481
+ var event = $.Event('beforeShow.spectrum');
482
+
446
483
  if (visible) {
447
484
  reflow();
448
485
  return;
449
486
  }
450
- if (callbacks.beforeShow(get()) === false) return;
487
+
488
+ boundElement.trigger(event, [ get() ]);
489
+
490
+ if (callbacks.beforeShow(get()) === false || event.isDefaultPrevented()) {
491
+ return;
492
+ }
451
493
 
452
494
  hideAll();
453
495
  visible = true;
@@ -455,7 +497,7 @@
455
497
  $(doc).bind("click.spectrum", hide);
456
498
  $(window).bind("resize.spectrum", resize);
457
499
  replacer.addClass("sp-active");
458
- container.show();
500
+ container.removeClass("sp-hidden");
459
501
 
460
502
  if (opts.showPalette) {
461
503
  drawPalette();
@@ -467,6 +509,7 @@
467
509
 
468
510
  drawInitial();
469
511
  callbacks.show(colorOnShow);
512
+ boundElement.trigger('show.spectrum', [ colorOnShow ]);
470
513
  }
471
514
 
472
515
  function hide(e) {
@@ -482,7 +525,7 @@
482
525
  $(window).unbind("resize.spectrum", resize);
483
526
 
484
527
  replacer.removeClass("sp-active");
485
- container.hide();
528
+ container.addClass("sp-hidden");
486
529
 
487
530
  var colorHasChanged = !tinycolor.equals(get(), colorOnShow);
488
531
 
@@ -496,6 +539,7 @@
496
539
  }
497
540
 
498
541
  callbacks.hide(get());
542
+ boundElement.trigger('hide.spectrum', [ get() ]);
499
543
  }
500
544
 
501
545
  function revert() {
@@ -510,20 +554,26 @@
510
554
  var newColor = tinycolor(color);
511
555
  var newHsv = newColor.toHsv();
512
556
 
513
- currentHue = newHsv.h;
557
+ currentHue = (newHsv.h % 360) / 360;
514
558
  currentSaturation = newHsv.s;
515
559
  currentValue = newHsv.v;
516
560
  currentAlpha = newHsv.a;
517
561
 
518
562
  updateUI();
519
563
 
520
- if (!ignoreFormatChange) {
564
+ if (newColor.ok && !ignoreFormatChange) {
521
565
  currentPreferredFormat = preferredFormat || newColor.format;
522
566
  }
523
567
  }
524
568
 
525
- function get() {
526
- return tinycolor.fromRatio({ h: currentHue, s: currentSaturation, v: currentValue, a: Math.round(currentAlpha * 100) / 100 });
569
+ function get(opts) {
570
+ opts = opts || { };
571
+ return tinycolor.fromRatio({
572
+ h: currentHue,
573
+ s: currentSaturation,
574
+ v: currentValue,
575
+ a: Math.round(currentAlpha * 100) / 100
576
+ }, { format: opts.format || currentPreferredFormat });
527
577
  }
528
578
 
529
579
  function isValid() {
@@ -534,6 +584,7 @@
534
584
  updateUI();
535
585
 
536
586
  callbacks.move(get());
587
+ boundElement.trigger('move.spectrum', [ get() ]);
537
588
  }
538
589
 
539
590
  function updateUI() {
@@ -543,22 +594,21 @@
543
594
  updateHelperLocations();
544
595
 
545
596
  // Update dragger background color (gradients take care of saturation and value).
546
- var flatColor = tinycolor({ h: currentHue, s: "1.0", v: "1.0" });
597
+ var flatColor = tinycolor.fromRatio({ h: currentHue, s: 1, v: 1 });
547
598
  dragger.css("background-color", flatColor.toHexString());
548
599
 
549
600
  // Get a format that alpha will be included in (hex and names ignore alpha)
550
601
  var format = currentPreferredFormat;
551
602
  if (currentAlpha < 1) {
552
- if (format === "hex" || format === "name") {
603
+ if (format === "hex" || format === "hex3" || format === "hex6" || format === "name") {
553
604
  format = "rgb";
554
605
  }
555
606
  }
556
607
 
557
- var realColor = get(),
608
+ var realColor = get({ format: format }),
558
609
  realHex = realColor.toHexString(),
559
610
  realRgb = realColor.toRgbString();
560
611
 
561
-
562
612
  // Update the replaced elements background color (with actual selected color)
563
613
  if (rgbaSupport || realColor.alpha === 1) {
564
614
  previewElement.css("background-color", realRgb);
@@ -588,11 +638,6 @@
588
638
 
589
639
  // Update the text entry input as it changes happen
590
640
  if (opts.showInput) {
591
- if (currentAlpha < 1) {
592
- if (format === "hex" || format === "name") {
593
- format = "rgb";
594
- }
595
- }
596
641
  textInput.val(realColor.toString(format));
597
642
  }
598
643
 
@@ -649,6 +694,7 @@
649
694
  addColorToSelectionPalette(color);
650
695
  if (fireCallback && hasChanged) {
651
696
  callbacks.change(color);
697
+ boundElement.trigger('change.spectrum', [ color ]);
652
698
  }
653
699
  }
654
700
 
@@ -663,6 +709,7 @@
663
709
  alphaSlideHelperWidth = alphaSlideHelper.width();
664
710
 
665
711
  if (!flat) {
712
+ container.css("position", "absolute");
666
713
  container.offset(getOffset(container, offsetElement));
667
714
  }
668
715
 
@@ -797,8 +844,8 @@
797
844
  var duringDragEvents = {};
798
845
  duringDragEvents["selectstart"] = prevent;
799
846
  duringDragEvents["dragstart"] = prevent;
800
- duringDragEvents[(hasTouch ? "touchmove" : "mousemove")] = move;
801
- duringDragEvents[(hasTouch ? "touchend" : "mouseup")] = stop;
847
+ duringDragEvents["touchmove mousemove"] = move;
848
+ duringDragEvents["touchend mouseup"] = stop;
802
849
 
803
850
  function prevent(e) {
804
851
  if (e.stopPropagation) {
@@ -863,7 +910,7 @@
863
910
  dragging = false;
864
911
  }
865
912
 
866
- $(element).bind(hasTouch ? "touchstart" : "mousedown", start);
913
+ $(element).bind("touchstart mousedown", start);
867
914
  }
868
915
 
869
916
  function throttle(func, wait, debounce) {
@@ -880,6 +927,8 @@
880
927
  }
881
928
 
882
929
 
930
+ 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);}}
931
+
883
932
  /**
884
933
  * Define a jQuery plugin
885
934
  */
@@ -948,78 +997,100 @@
948
997
  });
949
998
  }
950
999
  };
1000
+ // TinyColor v0.9.14
1001
+ // https://github.com/bgrins/TinyColor
1002
+ // 2013-02-24, Brian Grinstead, MIT License
951
1003
 
952
- // TinyColor.js - <https://github.com/bgrins/TinyColor> - 2011 Brian Grinstead - v0.5
953
-
954
- (function (window) {
1004
+ (function(root) {
955
1005
 
956
1006
  var trimLeft = /^[\s,#]+/,
957
- trimRight = /\s+$/,
958
- tinyCounter = 0,
959
- math = Math,
960
- mathRound = math.round,
961
- mathMin = math.min,
962
- mathMax = math.max,
963
- mathRandom = math.random,
964
- parseFloat = window.parseFloat;
1007
+ trimRight = /\s+$/,
1008
+ tinyCounter = 0,
1009
+ math = Math,
1010
+ mathRound = math.round,
1011
+ mathMin = math.min,
1012
+ mathMax = math.max,
1013
+ mathRandom = math.random;
965
1014
 
966
- function tinycolor(color, opts) {
1015
+ function tinycolor (color, opts) {
1016
+
1017
+ color = (color) ? color : '';
1018
+ opts = opts || { };
967
1019
 
968
1020
  // If input is already a tinycolor, return itself
969
1021
  if (typeof color == "object" && color.hasOwnProperty("_tc_id")) {
970
- return color;
1022
+ return color;
971
1023
  }
972
-
973
1024
  var rgb = inputToRGB(color);
974
- var r = rgb.r, g = rgb.g, b = rgb.b, a = parseFloat(rgb.a), format = rgb.format;
1025
+ var r = rgb.r,
1026
+ g = rgb.g,
1027
+ b = rgb.b,
1028
+ a = rgb.a,
1029
+ roundA = mathRound(100*a) / 100,
1030
+ format = opts.format || rgb.format;
1031
+
1032
+ // Don't let the range of [0,255] come back in [0,1].
1033
+ // Potentially lose a little bit of precision here, but will fix issues where
1034
+ // .5 gets interpreted as half of the total, instead of half of 1
1035
+ // If it was supposed to be 128, this was already taken care of by `inputToRgb`
1036
+ if (r < 1) { r = mathRound(r); }
1037
+ if (g < 1) { g = mathRound(g); }
1038
+ if (b < 1) { b = mathRound(b); }
975
1039
 
976
1040
  return {
977
1041
  ok: rgb.ok,
978
1042
  format: format,
979
1043
  _tc_id: tinyCounter++,
980
1044
  alpha: a,
981
- toHsv: function () {
1045
+ toHsv: function() {
982
1046
  var hsv = rgbToHsv(r, g, b);
983
- return { h: hsv.h, s: hsv.s, v: hsv.v, a: a };
1047
+ return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: a };
984
1048
  },
985
- toHsvString: function () {
1049
+ toHsvString: function() {
986
1050
  var hsv = rgbToHsv(r, g, b);
987
1051
  var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);
988
1052
  return (a == 1) ?
989
- "hsv(" + h + ", " + s + "%, " + v + "%)" :
990
- "hsva(" + h + ", " + s + "%, " + v + "%, " + a + ")";
1053
+ "hsv(" + h + ", " + s + "%, " + v + "%)" :
1054
+ "hsva(" + h + ", " + s + "%, " + v + "%, "+ roundA + ")";
991
1055
  },
992
- toHsl: function () {
1056
+ toHsl: function() {
993
1057
  var hsl = rgbToHsl(r, g, b);
994
- return { h: hsl.h, s: hsl.s, l: hsl.l, a: a };
1058
+ return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: a };
995
1059
  },
996
- toHslString: function () {
1060
+ toHslString: function() {
997
1061
  var hsl = rgbToHsl(r, g, b);
998
1062
  var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);
999
1063
  return (a == 1) ?
1000
- "hsl(" + h + ", " + s + "%, " + l + "%)" :
1001
- "hsla(" + h + ", " + s + "%, " + l + "%, " + a + ")";
1064
+ "hsl(" + h + ", " + s + "%, " + l + "%)" :
1065
+ "hsla(" + h + ", " + s + "%, " + l + "%, "+ roundA + ")";
1002
1066
  },
1003
- toHex: function () {
1004
- return rgbToHex(r, g, b);
1067
+ toHex: function(allow3Char) {
1068
+ return rgbToHex(r, g, b, allow3Char);
1005
1069
  },
1006
- toHexString: function (force6Char) {
1007
- return '#' + rgbToHex(r, g, b, force6Char);
1070
+ toHexString: function(allow3Char) {
1071
+ return '#' + rgbToHex(r, g, b, allow3Char);
1008
1072
  },
1009
- toRgb: function () {
1073
+ toRgb: function() {
1010
1074
  return { r: mathRound(r), g: mathRound(g), b: mathRound(b), a: a };
1011
1075
  },
1012
- toRgbString: function () {
1076
+ toRgbString: function() {
1013
1077
  return (a == 1) ?
1014
- "rgb(" + mathRound(r) + ", " + mathRound(g) + ", " + mathRound(b) + ")" :
1015
- "rgba(" + mathRound(r) + ", " + mathRound(g) + ", " + mathRound(b) + ", " + a + ")";
1078
+ "rgb(" + mathRound(r) + ", " + mathRound(g) + ", " + mathRound(b) + ")" :
1079
+ "rgba(" + mathRound(r) + ", " + mathRound(g) + ", " + mathRound(b) + ", " + roundA + ")";
1016
1080
  },
1017
- toName: function () {
1018
- return hexNames[rgbToHex(r, g, b)] || false;
1081
+ toPercentageRgb: function() {
1082
+ return { r: mathRound(bound01(r, 255) * 100) + "%", g: mathRound(bound01(g, 255) * 100) + "%", b: mathRound(bound01(b, 255) * 100) + "%", a: a };
1019
1083
  },
1020
- toFilter: function (opts, secondColor) {
1021
-
1022
- var hex = rgbToHex(r, g, b, true);
1084
+ toPercentageRgbString: function() {
1085
+ return (a == 1) ?
1086
+ "rgb(" + mathRound(bound01(r, 255) * 100) + "%, " + mathRound(bound01(g, 255) * 100) + "%, " + mathRound(bound01(b, 255) * 100) + "%)" :
1087
+ "rgba(" + mathRound(bound01(r, 255) * 100) + "%, " + mathRound(bound01(g, 255) * 100) + "%, " + mathRound(bound01(b, 255) * 100) + "%, " + roundA + ")";
1088
+ },
1089
+ toName: function() {
1090
+ return hexNames[rgbToHex(r, g, b, true)] || false;
1091
+ },
1092
+ toFilter: function(secondColor) {
1093
+ var hex = rgbToHex(r, g, b);
1023
1094
  var secondHex = hex;
1024
1095
  var alphaHex = Math.round(parseFloat(a) * 255).toString(16);
1025
1096
  var secondAlphaHex = alphaHex;
@@ -1033,16 +1104,19 @@
1033
1104
 
1034
1105
  return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr=#" + pad2(alphaHex) + hex + ",endColorstr=#" + pad2(secondAlphaHex) + secondHex + ")";
1035
1106
  },
1036
- toString: function (format) {
1107
+ toString: function(format) {
1037
1108
  format = format || this.format;
1038
1109
  var formattedString = false;
1039
1110
  if (format === "rgb") {
1040
1111
  formattedString = this.toRgbString();
1041
1112
  }
1042
- if (format === "hex") {
1113
+ if (format === "prgb") {
1114
+ formattedString = this.toPercentageRgbString();
1115
+ }
1116
+ if (format === "hex" || format === "hex6") {
1043
1117
  formattedString = this.toHexString();
1044
1118
  }
1045
- if (format === "hex6") {
1119
+ if (format === "hex3") {
1046
1120
  formattedString = this.toHexString(true);
1047
1121
  }
1048
1122
  if (format === "name") {
@@ -1055,25 +1129,30 @@
1055
1129
  formattedString = this.toHsvString();
1056
1130
  }
1057
1131
 
1058
- return formattedString || this.toHexString(true);
1132
+ return formattedString || this.toHexString();
1059
1133
  }
1060
1134
  };
1061
1135
  }
1062
1136
 
1063
1137
  // If input is an object, force 1 into "1.0" to handle ratios properly
1064
1138
  // String input requires "1.0" as input, so 1 will be treated as 1
1065
- tinycolor.fromRatio = function (color) {
1066
-
1139
+ tinycolor.fromRatio = function(color, opts) {
1067
1140
  if (typeof color == "object") {
1141
+ var newColor = {};
1068
1142
  for (var i in color) {
1069
- if (color[i] === 1) {
1070
- color[i] = "1.0";
1143
+ if (color.hasOwnProperty(i)) {
1144
+ if (i === "a") {
1145
+ newColor[i] = color[i];
1146
+ }
1147
+ else {
1148
+ newColor[i] = convertToPercentage(color[i]);
1149
+ }
1071
1150
  }
1072
1151
  }
1152
+ color = newColor;
1073
1153
  }
1074
1154
 
1075
- return tinycolor(color);
1076
-
1155
+ return tinycolor(color, opts);
1077
1156
  };
1078
1157
 
1079
1158
  // Given a string or object, convert that input to RGB
@@ -1105,14 +1184,18 @@
1105
1184
  if (color.hasOwnProperty("r") && color.hasOwnProperty("g") && color.hasOwnProperty("b")) {
1106
1185
  rgb = rgbToRgb(color.r, color.g, color.b);
1107
1186
  ok = true;
1108
- format = "rgb";
1187
+ format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb";
1109
1188
  }
1110
1189
  else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) {
1190
+ color.s = convertToPercentage(color.s);
1191
+ color.v = convertToPercentage(color.v);
1111
1192
  rgb = hsvToRgb(color.h, color.s, color.v);
1112
1193
  ok = true;
1113
1194
  format = "hsv";
1114
1195
  }
1115
1196
  else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) {
1197
+ color.s = convertToPercentage(color.s);
1198
+ color.l = convertToPercentage(color.l);
1116
1199
  rgb = hslToRgb(color.h, color.s, color.l);
1117
1200
  ok = true;
1118
1201
  format = "hsl";
@@ -1123,25 +1206,19 @@
1123
1206
  }
1124
1207
  }
1125
1208
 
1126
- rgb.r = mathMin(255, mathMax(rgb.r, 0));
1127
- rgb.g = mathMin(255, mathMax(rgb.g, 0));
1128
- rgb.b = mathMin(255, mathMax(rgb.b, 0));
1209
+ a = parseFloat(a);
1129
1210
 
1130
-
1131
- // Don't let the range of [0,255] come back in [0,1].
1132
- // Potentially lose a little bit of precision here, but will fix issues where
1133
- // .5 gets interpreted as half of the total, instead of half of 1.
1134
- // If it was supposed to be 128, this was already taken care of in the conversion function
1135
- if (rgb.r < 1) { rgb.r = mathRound(rgb.r); }
1136
- if (rgb.g < 1) { rgb.g = mathRound(rgb.g); }
1137
- if (rgb.b < 1) { rgb.b = mathRound(rgb.b); }
1211
+ // Handle invalid alpha characters by setting to 1
1212
+ if (isNaN(a) || a < 0 || a > 1) {
1213
+ a = 1;
1214
+ }
1138
1215
 
1139
1216
  return {
1140
1217
  ok: ok,
1141
- format: (color && color.format) || format,
1142
- r: rgb.r,
1143
- g: rgb.g,
1144
- b: rgb.b,
1218
+ format: color.format || format,
1219
+ r: mathMin(255, mathMax(rgb.r, 0)),
1220
+ g: mathMin(255, mathMax(rgb.g, 0)),
1221
+ b: mathMin(255, mathMax(rgb.b, 0)),
1145
1222
  a: a
1146
1223
  };
1147
1224
  }
@@ -1159,7 +1236,7 @@
1159
1236
  // <http://www.w3.org/TR/css3-color/>
1160
1237
  // *Assumes:* r, g, b in [0, 255] or [0, 1]
1161
1238
  // *Returns:* { r, g, b } in [0, 255]
1162
- function rgbToRgb(r, g, b) {
1239
+ function rgbToRgb(r, g, b){
1163
1240
  return {
1164
1241
  r: bound01(r, 255) * 255,
1165
1242
  g: bound01(g, 255) * 255,
@@ -1180,13 +1257,13 @@
1180
1257
  var max = mathMax(r, g, b), min = mathMin(r, g, b);
1181
1258
  var h, s, l = (max + min) / 2;
1182
1259
 
1183
- if (max == min) {
1260
+ if(max == min) {
1184
1261
  h = s = 0; // achromatic
1185
1262
  }
1186
1263
  else {
1187
1264
  var d = max - min;
1188
1265
  s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
1189
- switch (max) {
1266
+ switch(max) {
1190
1267
  case r: h = (g - b) / d + (g < b ? 6 : 0); break;
1191
1268
  case g: h = (b - r) / d + 2; break;
1192
1269
  case b: h = (r - g) / d + 4; break;
@@ -1210,23 +1287,23 @@
1210
1287
  l = bound01(l, 100);
1211
1288
 
1212
1289
  function hue2rgb(p, q, t) {
1213
- if (t < 0) t += 1;
1214
- if (t > 1) t -= 1;
1215
- if (t < 1 / 6) return p + (q - p) * 6 * t;
1216
- if (t < 1 / 2) return q;
1217
- if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
1290
+ if(t < 0) t += 1;
1291
+ if(t > 1) t -= 1;
1292
+ if(t < 1/6) return p + (q - p) * 6 * t;
1293
+ if(t < 1/2) return q;
1294
+ if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
1218
1295
  return p;
1219
1296
  }
1220
1297
 
1221
- if (s === 0) {
1298
+ if(s === 0) {
1222
1299
  r = g = b = l; // achromatic
1223
1300
  }
1224
1301
  else {
1225
1302
  var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
1226
1303
  var p = 2 * l - q;
1227
- r = hue2rgb(p, q, h + 1 / 3);
1304
+ r = hue2rgb(p, q, h + 1/3);
1228
1305
  g = hue2rgb(p, q, h);
1229
- b = hue2rgb(p, q, h - 1 / 3);
1306
+ b = hue2rgb(p, q, h - 1/3);
1230
1307
  }
1231
1308
 
1232
1309
  return { r: r * 255, g: g * 255, b: b * 255 };
@@ -1248,11 +1325,11 @@
1248
1325
  var d = max - min;
1249
1326
  s = max === 0 ? 0 : d / max;
1250
1327
 
1251
- if (max == min) {
1328
+ if(max == min) {
1252
1329
  h = 0; // achromatic
1253
1330
  }
1254
1331
  else {
1255
- switch (max) {
1332
+ switch(max) {
1256
1333
  case r: h = (g - b) / d + (g < b ? 6 : 0); break;
1257
1334
  case g: h = (b - r) / d + 2; break;
1258
1335
  case b: h = (r - g) / d + 4; break;
@@ -1266,7 +1343,8 @@
1266
1343
  // Converts an HSV color value to RGB.
1267
1344
  // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
1268
1345
  // *Returns:* { r, g, b } in the set [0, 255]
1269
- function hsvToRgb(h, s, v) {
1346
+ function hsvToRgb(h, s, v) {
1347
+
1270
1348
  h = bound01(h, 360) * 6;
1271
1349
  s = bound01(s, 100);
1272
1350
  v = bound01(v, 100);
@@ -1288,7 +1366,7 @@
1288
1366
  // Converts an RGB color to hex
1289
1367
  // Assumes r, g, and b are contained in the set [0, 255]
1290
1368
  // Returns a 3 or 6 character hex
1291
- function rgbToHex(r, g, b, force6Char) {
1369
+ function rgbToHex(r, g, b, allow3Char) {
1292
1370
 
1293
1371
  var hex = [
1294
1372
  pad2(mathRound(r).toString(16)),
@@ -1297,7 +1375,7 @@
1297
1375
  ];
1298
1376
 
1299
1377
  // Return a 3 character hex if possible
1300
- if (!force6Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {
1378
+ 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)) {
1301
1379
  return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
1302
1380
  }
1303
1381
 
@@ -1310,7 +1388,7 @@
1310
1388
  if (!color1 || !color2) { return false; }
1311
1389
  return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
1312
1390
  };
1313
- tinycolor.random = function () {
1391
+ tinycolor.random = function() {
1314
1392
  return tinycolor.fromRatio({
1315
1393
  r: mathRandom(),
1316
1394
  g: mathRandom(),
@@ -1337,10 +1415,10 @@
1337
1415
  hsl.s = clamp01(hsl.s);
1338
1416
  return tinycolor(hsl);
1339
1417
  };
1340
- tinycolor.greyscale = function (color) {
1418
+ tinycolor.greyscale = function(color) {
1341
1419
  return tinycolor.desaturate(color, 100);
1342
1420
  };
1343
- tinycolor.lighten = function (color, amount) {
1421
+ tinycolor.lighten = function(color, amount) {
1344
1422
  var hsl = tinycolor(color).toHsl();
1345
1423
  hsl.l += ((amount || 10) / 100);
1346
1424
  hsl.l = clamp01(hsl.l);
@@ -1352,9 +1430,9 @@
1352
1430
  hsl.l = clamp01(hsl.l);
1353
1431
  return tinycolor(hsl);
1354
1432
  };
1355
- tinycolor.complement = function (color) {
1433
+ tinycolor.complement = function(color) {
1356
1434
  var hsl = tinycolor(color).toHsl();
1357
- hsl.h = (hsl.h + 0.5) % 1;
1435
+ hsl.h = (hsl.h + 180) % 360;
1358
1436
  return tinycolor(hsl);
1359
1437
  };
1360
1438
 
@@ -1364,35 +1442,35 @@
1364
1442
  // Thanks to jQuery xColor for some of the ideas behind these
1365
1443
  // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>
1366
1444
 
1367
- tinycolor.triad = function (color) {
1445
+ tinycolor.triad = function(color) {
1368
1446
  var hsl = tinycolor(color).toHsl();
1369
- var h = hsl.h * 360;
1447
+ var h = hsl.h;
1370
1448
  return [
1371
- tinycolor(color),
1372
- tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
1373
- tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })
1374
- ];
1449
+ tinycolor(color),
1450
+ tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
1451
+ tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })
1452
+ ];
1375
1453
  };
1376
- tinycolor.tetrad = function (color) {
1454
+ tinycolor.tetrad = function(color) {
1377
1455
  var hsl = tinycolor(color).toHsl();
1378
- var h = hsl.h * 360;
1456
+ var h = hsl.h;
1379
1457
  return [
1380
- tinycolor(color),
1381
- tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
1382
- tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
1383
- tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })
1384
- ];
1458
+ tinycolor(color),
1459
+ tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
1460
+ tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
1461
+ tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })
1462
+ ];
1385
1463
  };
1386
- tinycolor.splitcomplement = function (color) {
1464
+ tinycolor.splitcomplement = function(color) {
1387
1465
  var hsl = tinycolor(color).toHsl();
1388
- var h = hsl.h * 360;
1466
+ var h = hsl.h;
1389
1467
  return [
1390
- tinycolor(color),
1391
- tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l }),
1392
- tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l })
1393
- ];
1468
+ tinycolor(color),
1469
+ tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),
1470
+ tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})
1471
+ ];
1394
1472
  };
1395
- tinycolor.analogous = function (color, results, slices) {
1473
+ tinycolor.analogous = function(color, results, slices) {
1396
1474
  results = results || 6;
1397
1475
  slices = slices || 30;
1398
1476
 
@@ -1400,15 +1478,13 @@
1400
1478
  var part = 360 / slices;
1401
1479
  var ret = [tinycolor(color)];
1402
1480
 
1403
- hsl.h *= 360;
1404
-
1405
1481
  for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {
1406
1482
  hsl.h = (hsl.h + part) % 360;
1407
1483
  ret.push(tinycolor(hsl));
1408
1484
  }
1409
1485
  return ret;
1410
1486
  };
1411
- tinycolor.monochromatic = function (color, results) {
1487
+ tinycolor.monochromatic = function(color, results) {
1412
1488
  results = results || 6;
1413
1489
  var hsv = tinycolor(color).toHsv();
1414
1490
  var h = hsv.h, s = hsv.s, v = hsv.v;
@@ -1416,23 +1492,80 @@
1416
1492
  var modification = 1 / results;
1417
1493
 
1418
1494
  while (results--) {
1419
- ret.push(tinycolor({ h: h, s: s, v: v }));
1495
+ ret.push(tinycolor({ h: h, s: s, v: v}));
1420
1496
  v = (v + modification) % 1;
1421
1497
  }
1422
1498
 
1423
1499
  return ret;
1424
1500
  };
1425
- tinycolor.readable = function (color1, color2) {
1426
- var a = tinycolor(color1).toRgb(), b = tinycolor(color2).toRgb();
1427
- return (
1428
- (b.r - a.r) * (b.r - a.r) +
1429
- (b.g - a.g) * (b.g - a.g) +
1430
- (b.b - a.b) * (b.b - a.b)
1431
- ) > 0x28A4;
1501
+
1502
+ // Readability Functions
1503
+ // ---------------------
1504
+ // <http://www.w3.org/TR/AERT#color-contrast>
1505
+
1506
+ // `readability`
1507
+ // Analyze the 2 colors and returns an object with the following properties:
1508
+ // `brightness`: difference in brightness between the two colors
1509
+ // `color`: difference in color/hue between the two colors
1510
+ tinycolor.readability = function(color1, color2) {
1511
+ var a = tinycolor(color1).toRgb();
1512
+ var b = tinycolor(color2).toRgb();
1513
+ var brightnessA = (a.r * 299 + a.g * 587 + a.b * 114) / 1000;
1514
+ var brightnessB = (b.r * 299 + b.g * 587 + b.b * 114) / 1000;
1515
+ var colorDiff = (
1516
+ Math.max(a.r, b.r) - Math.min(a.r, b.r) +
1517
+ Math.max(a.g, b.g) - Math.min(a.g, b.g) +
1518
+ Math.max(a.b, b.b) - Math.min(a.b, b.b)
1519
+ );
1520
+
1521
+ return {
1522
+ brightness: Math.abs(brightnessA - brightnessB),
1523
+ color: colorDiff
1524
+ };
1525
+ };
1526
+
1527
+ // `readable`
1528
+ // http://www.w3.org/TR/AERT#color-contrast
1529
+ // Ensure that foreground and background color combinations provide sufficient contrast.
1530
+ // *Example*
1531
+ // tinycolor.readable("#000", "#111") => false
1532
+ tinycolor.readable = function(color1, color2) {
1533
+ var readability = tinycolor.readability(color1, color2);
1534
+ return readability.brightness > 125 && readability.color > 500;
1432
1535
  };
1433
1536
 
1537
+ // `mostReadable`
1538
+ // Given a base color and a list of possible foreground or background
1539
+ // colors for that base, returns the most readable color.
1540
+ // *Example*
1541
+ // tinycolor.mostReadable("#123", ["#fff", "#000"]) => "#000"
1542
+ tinycolor.mostReadable = function(baseColor, colorList) {
1543
+ var bestColor = null;
1544
+ var bestScore = 0;
1545
+ var bestIsReadable = false;
1546
+ for (var i=0; i < colorList.length; i++) {
1547
+
1548
+ // We normalize both around the "acceptable" breaking point,
1549
+ // but rank brightness constrast higher than hue.
1550
+
1551
+ var readability = tinycolor.readability(baseColor, colorList[i]);
1552
+ var readable = readability.brightness > 125 && readability.color > 500;
1553
+ var score = 3 * (readability.brightness / 125) + (readability.color / 500);
1554
+
1555
+ if ((readable && ! bestIsReadable) ||
1556
+ (readable && bestIsReadable && score > bestScore) ||
1557
+ ((! readable) && (! bestIsReadable) && score > bestScore)) {
1558
+ bestIsReadable = readable;
1559
+ bestScore = score;
1560
+ bestColor = tinycolor(colorList[i]);
1561
+ }
1562
+ }
1563
+ return bestColor;
1564
+ };
1565
+
1566
+
1434
1567
  // Big List of Colors
1435
- // ---------
1568
+ // ------------------
1436
1569
  // <http://www.w3.org/TR/css3-color/#svg-color>
1437
1570
  var names = tinycolor.names = {
1438
1571
  aliceblue: "f0f8ff",
@@ -1594,7 +1727,7 @@
1594
1727
 
1595
1728
  // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
1596
1729
  function flip(o) {
1597
- var flipped = {};
1730
+ var flipped = { };
1598
1731
  for (var i in o) {
1599
1732
  if (o.hasOwnProperty(i)) {
1600
1733
  flipped[o[i]] = i;
@@ -1612,17 +1745,16 @@
1612
1745
 
1613
1746
  // Automatically convert percentage into number
1614
1747
  if (processPercent) {
1615
- n = n * (max / 100);
1748
+ n = parseInt(n * max, 10) / 100;
1616
1749
  }
1617
1750
 
1618
1751
  // Handle floating point rounding errors
1619
- if (math.abs(n - max) < 0.000001) {
1752
+ if ((math.abs(n - max) < 0.000001)) {
1620
1753
  return 1;
1621
1754
  }
1622
- else if (n >= 1) {
1623
- return (n % max) / parseFloat(max);
1624
- }
1625
- return n;
1755
+
1756
+ // Convert into [0, 1] range if it isn't already
1757
+ return (n % max) / parseFloat(max);
1626
1758
  }
1627
1759
 
1628
1760
  // Force a number between 0 and 1
@@ -1651,7 +1783,16 @@
1651
1783
  return c.length == 1 ? '0' + c : '' + c;
1652
1784
  }
1653
1785
 
1654
- var matchers = (function () {
1786
+ // Replace a decimal with it's percentage value
1787
+ function convertToPercentage(n) {
1788
+ if (n <= 1) {
1789
+ n = (n * 100) + "%";
1790
+ }
1791
+
1792
+ return n;
1793
+ }
1794
+
1795
+ var matchers = (function() {
1655
1796
 
1656
1797
  // <http://www.w3.org/TR/css3-values/#integers>
1657
1798
  var CSS_INTEGER = "[-\\+]?\\d+%?";
@@ -1684,7 +1825,7 @@
1684
1825
  // based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
1685
1826
  function stringInputToObject(color) {
1686
1827
 
1687
- color = color.replace(trimLeft, '').replace(trimRight, '').toLowerCase();
1828
+ color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase();
1688
1829
  var named = false;
1689
1830
  if (names[color]) {
1690
1831
  color = names[color];
@@ -1734,8 +1875,7 @@
1734
1875
  return false;
1735
1876
  }
1736
1877
 
1737
- // Everything is ready, expose to window
1738
- window.tinycolor = tinycolor;
1878
+ root.tinycolor = tinycolor;
1739
1879
 
1740
1880
  })(this);
1741
1881
 
@@ -1745,4 +1885,4 @@
1745
1885
  }
1746
1886
  });
1747
1887
 
1748
- })(window, jQuery);
1888
+ })(window, jQuery);
@@ -1,5 +1,5 @@
1
1
  /***
2
- Spectrum Colorpicker v1.0.9
2
+ Spectrum Colorpicker v1.1.1
3
3
  https://github.com/bgrins/spectrum
4
4
  Author: Brian Grinstead
5
5
  License: MIT
@@ -179,6 +179,10 @@ License: MIT
179
179
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff', endColorstr='#ff0000');
180
180
  }
181
181
 
182
+ .sp-hidden {
183
+ display: none !important;
184
+ }
185
+
182
186
  /* Clearfix hack */
183
187
  .sp-cf:before, .sp-cf:after { content: ""; display: table; }
184
188
  .sp-cf:after { clear: both; }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spectrum-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.9
4
+ version: 1.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-14 00:00:00.000000000 Z
12
+ date: 2013-06-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: railties