spectrum-rails 1.0.9 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
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