jquery-minicolors-rails 2.1.4.1 → 2.2.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 31edbc368f746fffa33bb3419e0c80c099a48404
4
- data.tar.gz: 37ad6f3cc9acb334c411232d04f1da53a87d46bb
3
+ metadata.gz: 870266e817956f141f6ce934a3cca56a3e3d2087
4
+ data.tar.gz: 85248ae97fce0bb91d8ec6c2d04a09cec278800a
5
5
  SHA512:
6
- metadata.gz: a6cbbfa3524e914ce9927e47c7aab3f7015b7e2d3eccb1f6f71980acc5dbc74af88ff4045196700311042efd6041fddb788306e99e4c491243f5a39495598493
7
- data.tar.gz: d5668e2407c99d6a8e92c44c3ca77333576503f15cc7ca54468d736637f11a58864c6f670535a57fd83ab842cad89877c774e49a2ac847de6f86c4be24e968f6
6
+ metadata.gz: fdf04d688331f79754e8daae188225b38a3d5235e3f6bc23b031392b66b0534d17f2ea46b08cda077bdf15f947393b4513e471f9c91b580be42dd5894f5b936e
7
+ data.tar.gz: c08f3bf231f3ce831ad19bdc15368cb6d3ac58dd87cebb2bd9479b4a6b8d1bc4481e981e308895c4c76a79731ea50756a0b5dbbfc1836765b3559ece4a9e0e11
data/README.md CHANGED
@@ -73,32 +73,28 @@ See https://github.com/plataformatec/simple_form
73
73
  <% end %>
74
74
  ```
75
75
 
76
- ## Configuration
77
-
78
- As of https://github.com/rails/rails/pull/7968 (Rails > 4.*) the asset pipeline precompile command will ignore the images.
79
- Since `jquery.minicolors` uses an image for backgrounds, the image is by default splitted into chunks of data URLs and embedded into the CSS directly.
80
- This results in a slightly bigger compiled CSS (~50k bigger), but avoids unnecessary image request to the server and headache on deployment.
81
- You can still instruct `JqueryMinicolorsRails` to use the original image instead of the data URLs:
76
+ ## Testing
82
77
 
83
- ```ruby
84
- # config/initializers/jquery_minicolors_rails.rb
85
- JqueryMinicolorsRails.use_data_urls = false
78
+ ```bash
79
+ bundle exec rspec
86
80
  ```
87
81
 
88
- Additionally you would also have to copy the image to the deployment target:
82
+ Since this gem uses a lot of different frameworks, anything is possible. So despite the specs are
83
+ "green", please verify manually:
89
84
 
90
- ```ruby
91
- # config/deploy.rb
92
- after :deploy do
93
- target = File.join(%W[#{release_path} public assets])
94
- run "cp -r `cd #{release_path} && bundle show jquery-minicolors-rails`/vendor/assets/images/jquery.minicolors.png #{target}"
95
- end
85
+ ```bash
86
+ cd test_app
87
+ bundle
88
+ rails s
89
+ open http://localhost:3000/ # Assert everything looks & works good.
96
90
  ```
97
91
 
98
- ## Testing
99
-
100
92
  ```bash
101
- bundle exec rspec
93
+ rm -rf tmp/cache
94
+ rm -rf public/assets
95
+ RAILS_ENV=production bundle exec rake assets:precompile
96
+ rails s -eproduction
97
+ open http://localhost:3000/ # Assert everything looks & works good.
102
98
  ```
103
99
 
104
100
  ## Versioning
@@ -1,28 +1,4 @@
1
1
  require 'jquery-minicolors-rails/engine'
2
2
 
3
3
  module JqueryMinicolorsRails
4
- class << self
5
- attr_writer :use_data_urls
6
-
7
- def use_data_urls?
8
- defined?(@use_data_urls) ? !!@use_data_urls : true
9
- end
10
-
11
- def image_data_url(name)
12
- image_data_url_cache.fetch(name) do
13
- image_data_url_cache[:name] = load_image_data_url(name)
14
- end
15
- end
16
-
17
- private
18
-
19
- def image_data_url_cache
20
- @image_data_url_cache ||= {}
21
- end
22
-
23
- def load_image_data_url(name)
24
- path = File.expand_path("../../vendor/assets/images/jquery.minicolors.#{name}", __FILE__)
25
- File.read(path).strip
26
- end
27
- end
28
4
  end
@@ -1,3 +1,3 @@
1
1
  module JqueryMinicolorsRails
2
- VERSION = '2.1.4.1'
2
+ VERSION = '2.2.2.0'
3
3
  end
@@ -1,842 +1,1039 @@
1
1
  /*
2
2
  * jQuery MiniColors: A tiny color picker built on jQuery
3
3
  *
4
- * Copyright Cory LaViska for A Beautiful Site, LLC. (http://www.abeautifulsite.net/)
4
+ * Copyright: Cory LaViska for A Beautiful Site, LLC: http://www.abeautifulsite.net/
5
5
  *
6
- * Licensed under the MIT license: http://opensource.org/licenses/MIT
6
+ * Contribute: https://github.com/claviska/jquery-minicolors
7
+ *
8
+ * @license: http://opensource.org/licenses/MIT
7
9
  *
8
10
  */
9
- if(jQuery) (function($) {
10
-
11
- // Defaults
12
- $.minicolors = {
13
- defaults: {
14
- animationSpeed: 50,
15
- animationEasing: 'swing',
16
- change: null,
17
- changeDelay: 0,
18
- control: 'hue',
19
- defaultValue: '',
20
- hide: null,
21
- hideSpeed: 100,
22
- inline: false,
23
- letterCase: 'lowercase',
24
- opacity: false,
25
- position: 'bottom left',
26
- show: null,
27
- showSpeed: 100,
28
- theme: 'default'
29
- }
30
- };
31
-
32
- // Public methods
33
- $.extend($.fn, {
34
- minicolors: function(method, data) {
35
-
36
- switch(method) {
37
-
38
- // Destroy the control
39
- case 'destroy':
40
- $(this).each( function() {
41
- destroy($(this));
42
- });
43
- return $(this);
44
-
45
- // Hide the color picker
46
- case 'hide':
47
- hide();
48
- return $(this);
49
-
50
- // Get/set opacity
51
- case 'opacity':
52
- // Getter
53
- if( data === undefined ) {
54
- // Getter
55
- return $(this).attr('data-opacity');
56
- } else {
57
- // Setter
58
- $(this).each( function() {
59
- updateFromInput($(this).attr('data-opacity', data));
60
- });
61
- }
62
- return $(this);
63
-
64
- // Get an RGB(A) object based on the current color/opacity
65
- case 'rgbObject':
66
- return rgbObject($(this), method === 'rgbaObject');
67
-
68
- // Get an RGB(A) string based on the current color/opacity
69
- case 'rgbString':
70
- case 'rgbaString':
71
- return rgbString($(this), method === 'rgbaString');
72
-
73
- // Get/set settings on the fly
74
- case 'settings':
75
- if( data === undefined ) {
76
- return $(this).data('minicolors-settings');
77
- } else {
78
- // Setter
79
- $(this).each( function() {
80
- var settings = $(this).data('minicolors-settings') || {};
81
- destroy($(this));
82
- $(this).minicolors($.extend(true, settings, data));
83
- });
84
- }
85
- return $(this);
86
-
87
- // Show the color picker
88
- case 'show':
89
- show( $(this).eq(0) );
90
- return $(this);
91
-
92
- // Get/set the hex color value
93
- case 'value':
94
- if( data === undefined ) {
95
- // Getter
96
- return $(this).val();
97
- } else {
98
- // Setter
99
- $(this).each( function() {
100
- updateFromInput($(this).val(data));
101
- });
102
- }
103
- return $(this);
104
-
105
- // Initializes the control
106
- default:
107
- if( method !== 'create' ) data = method;
108
- $(this).each( function() {
109
- init($(this), data);
110
- });
111
- return $(this);
112
-
113
- }
114
-
115
- }
116
- });
117
-
118
- // Initialize input elements
119
- function init(input, settings) {
120
-
121
- var minicolors = $('<div class="minicolors" />'),
122
- defaults = $.minicolors.defaults;
123
-
124
- // Do nothing if already initialized
125
- if( input.data('minicolors-initialized') ) return;
126
-
127
- // Handle settings
128
- settings = $.extend(true, {}, defaults, settings);
129
-
130
- // The wrapper
131
- minicolors
132
- .addClass('minicolors-theme-' + settings.theme)
133
- .toggleClass('minicolors-with-opacity', settings.opacity);
134
-
135
- // Custom positioning
136
- if( settings.position !== undefined ) {
137
- $.each(settings.position.split(' '), function() {
138
- minicolors.addClass('minicolors-position-' + this);
139
- });
140
- }
141
-
142
- // The input
143
- input
144
- .addClass('minicolors-input')
145
- .data('minicolors-initialized', false)
146
- .data('minicolors-settings', settings)
147
- .prop('size', 7)
148
- .wrap(minicolors)
149
- .after(
150
- '<div class="minicolors-panel minicolors-slider-' + settings.control + '">' +
151
- '<div class="minicolors-slider">' +
152
- '<div class="minicolors-picker"></div>' +
153
- '</div>' +
154
- '<div class="minicolors-opacity-slider">' +
155
- '<div class="minicolors-picker"></div>' +
156
- '</div>' +
157
- '<div class="minicolors-grid">' +
158
- '<div class="minicolors-grid-inner"></div>' +
159
- '<div class="minicolors-picker"><div></div></div>' +
160
- '</div>' +
161
- '</div>'
162
- );
163
-
164
- // The swatch
165
- if( !settings.inline ) {
166
- input.after('<span class="minicolors-swatch"><span class="minicolors-swatch-color"></span></span>');
167
- input.next('.minicolors-swatch').on('click', function(event) {
168
- event.preventDefault();
169
- input.focus();
170
- });
171
- }
172
-
173
- // Prevent text selection in IE
174
- input.parent().find('.minicolors-panel').on('selectstart', function() { return false; }).end();
175
-
176
- // Inline controls
177
- if( settings.inline ) input.parent().addClass('minicolors-inline');
178
-
179
- updateFromInput(input, false);
180
-
181
- input.data('minicolors-initialized', true);
182
-
183
- }
184
-
185
- // Returns the input back to its original state
186
- function destroy(input) {
187
-
188
- var minicolors = input.parent();
189
-
190
- // Revert the input element
191
- input
192
- .removeData('minicolors-initialized')
193
- .removeData('minicolors-settings')
194
- .removeProp('size')
195
- .removeClass('minicolors-input');
196
-
197
- // Remove the wrap and destroy whatever remains
198
- minicolors.before(input).remove();
199
-
200
- }
201
-
202
- // Shows the specified dropdown panel
203
- function show(input) {
204
-
205
- var minicolors = input.parent(),
206
- panel = minicolors.find('.minicolors-panel'),
207
- settings = input.data('minicolors-settings');
208
-
209
- // Do nothing if uninitialized, disabled, inline, or already open
210
- if( !input.data('minicolors-initialized') ||
211
- input.prop('disabled') ||
212
- minicolors.hasClass('minicolors-inline') ||
213
- minicolors.hasClass('minicolors-focus')
214
- ) return;
215
-
216
- hide();
217
-
218
- minicolors.addClass('minicolors-focus');
219
- panel
220
- .stop(true, true)
221
- .fadeIn(settings.showSpeed, function() {
222
- if( settings.show ) settings.show.call(input.get(0));
223
- });
224
-
225
- }
226
-
227
- // Hides all dropdown panels
228
- function hide() {
229
-
230
- $('.minicolors-focus').each( function() {
231
-
232
- var minicolors = $(this),
233
- input = minicolors.find('.minicolors-input'),
234
- panel = minicolors.find('.minicolors-panel'),
235
- settings = input.data('minicolors-settings');
236
-
237
- panel.fadeOut(settings.hideSpeed, function() {
238
- if( settings.hide ) settings.hide.call(input.get(0));
239
- minicolors.removeClass('minicolors-focus');
240
- });
241
-
242
- });
243
- }
244
-
245
- // Moves the selected picker
246
- function move(target, event, animate) {
247
-
248
- var input = target.parents('.minicolors').find('.minicolors-input'),
249
- settings = input.data('minicolors-settings'),
250
- picker = target.find('[class$=-picker]'),
251
- offsetX = target.offset().left,
252
- offsetY = target.offset().top,
253
- x = Math.round(event.pageX - offsetX),
254
- y = Math.round(event.pageY - offsetY),
255
- duration = animate ? settings.animationSpeed : 0,
256
- wx, wy, r, phi;
257
-
258
- // Touch support
259
- if( event.originalEvent.changedTouches ) {
260
- x = event.originalEvent.changedTouches[0].pageX - offsetX;
261
- y = event.originalEvent.changedTouches[0].pageY - offsetY;
262
- }
263
-
264
- // Constrain picker to its container
265
- if( x < 0 ) x = 0;
266
- if( y < 0 ) y = 0;
267
- if( x > target.width() ) x = target.width();
268
- if( y > target.height() ) y = target.height();
269
-
270
- // Constrain color wheel values to the wheel
271
- if( target.parent().is('.minicolors-slider-wheel') && picker.parent().is('.minicolors-grid') ) {
272
- wx = 75 - x;
273
- wy = 75 - y;
274
- r = Math.sqrt(wx * wx + wy * wy);
275
- phi = Math.atan2(wy, wx);
276
- if( phi < 0 ) phi += Math.PI * 2;
277
- if( r > 75 ) {
278
- r = 75;
279
- x = 75 - (75 * Math.cos(phi));
280
- y = 75 - (75 * Math.sin(phi));
281
- }
282
- x = Math.round(x);
283
- y = Math.round(y);
284
- }
285
-
286
- // Move the picker
287
- if( target.is('.minicolors-grid') ) {
288
- picker
289
- .stop(true)
290
- .animate({
291
- top: y + 'px',
292
- left: x + 'px'
293
- }, duration, settings.animationEasing, function() {
294
- updateFromControl(input, target);
295
- });
296
- } else {
297
- picker
298
- .stop(true)
299
- .animate({
300
- top: y + 'px'
301
- }, duration, settings.animationEasing, function() {
302
- updateFromControl(input, target);
303
- });
304
- }
305
-
306
- }
307
-
308
- // Sets the input based on the color picker values
309
- function updateFromControl(input, target) {
310
-
311
- function getCoords(picker, container) {
312
-
313
- var left, top;
314
- if( !picker.length || !container ) return null;
315
- left = picker.offset().left;
316
- top = picker.offset().top;
317
-
318
- return {
319
- x: left - container.offset().left + (picker.outerWidth() / 2),
320
- y: top - container.offset().top + (picker.outerHeight() / 2)
321
- };
322
-
323
- }
324
-
325
- var hue, saturation, brightness, x, y, r, phi,
326
-
327
- hex = input.val(),
328
- opacity = input.attr('data-opacity'),
329
-
330
- // Helpful references
331
- minicolors = input.parent(),
332
- settings = input.data('minicolors-settings'),
333
- swatch = minicolors.find('.minicolors-swatch'),
334
-
335
- // Panel objects
336
- grid = minicolors.find('.minicolors-grid'),
337
- slider = minicolors.find('.minicolors-slider'),
338
- opacitySlider = minicolors.find('.minicolors-opacity-slider'),
339
-
340
- // Picker objects
341
- gridPicker = grid.find('[class$=-picker]'),
342
- sliderPicker = slider.find('[class$=-picker]'),
343
- opacityPicker = opacitySlider.find('[class$=-picker]'),
344
-
345
- // Picker positions
346
- gridPos = getCoords(gridPicker, grid),
347
- sliderPos = getCoords(sliderPicker, slider),
348
- opacityPos = getCoords(opacityPicker, opacitySlider);
349
-
350
- // Handle colors
351
- if( target.is('.minicolors-grid, .minicolors-slider') ) {
352
-
353
- // Determine HSB values
354
- switch(settings.control) {
355
-
356
- case 'wheel':
357
- // Calculate hue, saturation, and brightness
358
- x = (grid.width() / 2) - gridPos.x;
359
- y = (grid.height() / 2) - gridPos.y;
360
- r = Math.sqrt(x * x + y * y);
361
- phi = Math.atan2(y, x);
362
- if( phi < 0 ) phi += Math.PI * 2;
363
- if( r > 75 ) {
364
- r = 75;
365
- gridPos.x = 69 - (75 * Math.cos(phi));
366
- gridPos.y = 69 - (75 * Math.sin(phi));
367
- }
368
- saturation = keepWithin(r / 0.75, 0, 100);
369
- hue = keepWithin(phi * 180 / Math.PI, 0, 360);
370
- brightness = keepWithin(100 - Math.floor(sliderPos.y * (100 / slider.height())), 0, 100);
371
- hex = hsb2hex({
372
- h: hue,
373
- s: saturation,
374
- b: brightness
375
- });
376
-
377
- // Update UI
378
- slider.css('backgroundColor', hsb2hex({ h: hue, s: saturation, b: 100 }));
379
- break;
380
-
381
- case 'saturation':
382
- // Calculate hue, saturation, and brightness
383
- hue = keepWithin(parseInt(gridPos.x * (360 / grid.width()), 10), 0, 360);
384
- saturation = keepWithin(100 - Math.floor(sliderPos.y * (100 / slider.height())), 0, 100);
385
- brightness = keepWithin(100 - Math.floor(gridPos.y * (100 / grid.height())), 0, 100);
386
- hex = hsb2hex({
387
- h: hue,
388
- s: saturation,
389
- b: brightness
390
- });
391
-
392
- // Update UI
393
- slider.css('backgroundColor', hsb2hex({ h: hue, s: 100, b: brightness }));
394
- minicolors.find('.minicolors-grid-inner').css('opacity', saturation / 100);
395
- break;
396
-
397
- case 'brightness':
398
- // Calculate hue, saturation, and brightness
399
- hue = keepWithin(parseInt(gridPos.x * (360 / grid.width()), 10), 0, 360);
400
- saturation = keepWithin(100 - Math.floor(gridPos.y * (100 / grid.height())), 0, 100);
401
- brightness = keepWithin(100 - Math.floor(sliderPos.y * (100 / slider.height())), 0, 100);
402
- hex = hsb2hex({
403
- h: hue,
404
- s: saturation,
405
- b: brightness
406
- });
407
-
408
- // Update UI
409
- slider.css('backgroundColor', hsb2hex({ h: hue, s: saturation, b: 100 }));
410
- minicolors.find('.minicolors-grid-inner').css('opacity', 1 - (brightness / 100));
411
- break;
412
-
413
- default:
414
- // Calculate hue, saturation, and brightness
415
- hue = keepWithin(360 - parseInt(sliderPos.y * (360 / slider.height()), 10), 0, 360);
416
- saturation = keepWithin(Math.floor(gridPos.x * (100 / grid.width())), 0, 100);
417
- brightness = keepWithin(100 - Math.floor(gridPos.y * (100 / grid.height())), 0, 100);
418
- hex = hsb2hex({
419
- h: hue,
420
- s: saturation,
421
- b: brightness
422
- });
423
-
424
- // Update UI
425
- grid.css('backgroundColor', hsb2hex({ h: hue, s: 100, b: 100 }));
426
- break;
427
-
428
- }
429
-
430
- // Adjust case
431
- input.val( convertCase(hex, settings.letterCase) );
432
-
433
- }
434
-
435
- // Handle opacity
436
- if( target.is('.minicolors-opacity-slider') ) {
437
- if( settings.opacity ) {
438
- opacity = parseFloat(1 - (opacityPos.y / opacitySlider.height())).toFixed(2);
439
- } else {
440
- opacity = 1;
441
- }
442
- if( settings.opacity ) input.attr('data-opacity', opacity);
443
- }
444
-
445
- // Set swatch color
446
- swatch.find('SPAN').css({
447
- backgroundColor: hex,
448
- opacity: opacity
449
- });
450
-
451
- // Handle change event
452
- doChange(input, hex, opacity);
453
-
454
- }
455
-
456
- // Sets the color picker values from the input
457
- function updateFromInput(input, preserveInputValue) {
458
-
459
- var hex,
460
- hsb,
461
- opacity,
462
- x, y, r, phi,
463
-
464
- // Helpful references
465
- minicolors = input.parent(),
466
- settings = input.data('minicolors-settings'),
467
- swatch = minicolors.find('.minicolors-swatch'),
468
-
469
- // Panel objects
470
- grid = minicolors.find('.minicolors-grid'),
471
- slider = minicolors.find('.minicolors-slider'),
472
- opacitySlider = minicolors.find('.minicolors-opacity-slider'),
473
-
474
- // Picker objects
475
- gridPicker = grid.find('[class$=-picker]'),
476
- sliderPicker = slider.find('[class$=-picker]'),
477
- opacityPicker = opacitySlider.find('[class$=-picker]');
478
-
479
- // Determine hex/HSB values
480
- hex = convertCase(parseHex(input.val(), true), settings.letterCase);
481
- if( !hex ){
482
- hex = convertCase(parseHex(settings.defaultValue, true), settings.letterCase);
483
- }
484
- hsb = hex2hsb(hex);
485
-
486
- // Update input value
487
- if( !preserveInputValue ) input.val(hex);
488
-
489
- // Determine opacity value
490
- if( settings.opacity ) {
491
- // Get from data-opacity attribute and keep within 0-1 range
492
- opacity = input.attr('data-opacity') === '' ? 1 : keepWithin(parseFloat(input.attr('data-opacity')).toFixed(2), 0, 1);
493
- if( isNaN(opacity) ) opacity = 1;
494
- input.attr('data-opacity', opacity);
495
- swatch.find('SPAN').css('opacity', opacity);
496
-
497
- // Set opacity picker position
498
- y = keepWithin(opacitySlider.height() - (opacitySlider.height() * opacity), 0, opacitySlider.height());
499
- opacityPicker.css('top', y + 'px');
500
- }
501
-
502
- // Update swatch
503
- swatch.find('SPAN').css('backgroundColor', hex);
504
-
505
- // Determine picker locations
506
- switch(settings.control) {
507
-
508
- case 'wheel':
509
- // Set grid position
510
- r = keepWithin(Math.ceil(hsb.s * 0.75), 0, grid.height() / 2);
511
- phi = hsb.h * Math.PI / 180;
512
- x = keepWithin(75 - Math.cos(phi) * r, 0, grid.width());
513
- y = keepWithin(75 - Math.sin(phi) * r, 0, grid.height());
514
- gridPicker.css({
515
- top: y + 'px',
516
- left: x + 'px'
517
- });
518
-
519
- // Set slider position
520
- y = 150 - (hsb.b / (100 / grid.height()));
521
- if( hex === '' ) y = 0;
522
- sliderPicker.css('top', y + 'px');
523
-
524
- // Update panel color
525
- slider.css('backgroundColor', hsb2hex({ h: hsb.h, s: hsb.s, b: 100 }));
526
- break;
527
-
528
- case 'saturation':
529
- // Set grid position
530
- x = keepWithin((5 * hsb.h) / 12, 0, 150);
531
- y = keepWithin(grid.height() - Math.ceil(hsb.b / (100 / grid.height())), 0, grid.height());
532
- gridPicker.css({
533
- top: y + 'px',
534
- left: x + 'px'
535
- });
536
-
537
- // Set slider position
538
- y = keepWithin(slider.height() - (hsb.s * (slider.height() / 100)), 0, slider.height());
539
- sliderPicker.css('top', y + 'px');
540
-
541
- // Update UI
542
- slider.css('backgroundColor', hsb2hex({ h: hsb.h, s: 100, b: hsb.b }));
543
- minicolors.find('.minicolors-grid-inner').css('opacity', hsb.s / 100);
544
- break;
545
-
546
- case 'brightness':
547
- // Set grid position
548
- x = keepWithin((5 * hsb.h) / 12, 0, 150);
549
- y = keepWithin(grid.height() - Math.ceil(hsb.s / (100 / grid.height())), 0, grid.height());
550
- gridPicker.css({
551
- top: y + 'px',
552
- left: x + 'px'
553
- });
554
-
555
- // Set slider position
556
- y = keepWithin(slider.height() - (hsb.b * (slider.height() / 100)), 0, slider.height());
557
- sliderPicker.css('top', y + 'px');
558
-
559
- // Update UI
560
- slider.css('backgroundColor', hsb2hex({ h: hsb.h, s: hsb.s, b: 100 }));
561
- minicolors.find('.minicolors-grid-inner').css('opacity', 1 - (hsb.b / 100));
562
- break;
563
-
564
- default:
565
- // Set grid position
566
- x = keepWithin(Math.ceil(hsb.s / (100 / grid.width())), 0, grid.width());
567
- y = keepWithin(grid.height() - Math.ceil(hsb.b / (100 / grid.height())), 0, grid.height());
568
- gridPicker.css({
569
- top: y + 'px',
570
- left: x + 'px'
571
- });
572
-
573
- // Set slider position
574
- y = keepWithin(slider.height() - (hsb.h / (360 / slider.height())), 0, slider.height());
575
- sliderPicker.css('top', y + 'px');
576
-
577
- // Update panel color
578
- grid.css('backgroundColor', hsb2hex({ h: hsb.h, s: 100, b: 100 }));
579
- break;
580
-
581
- }
582
-
583
- // Fire change event, but only if minicolors is fully initialized
584
- if( input.data('minicolors-initialized') ) {
585
- doChange(input, hex, opacity);
586
- }
587
-
588
- }
589
-
590
- // Runs the change and changeDelay callbacks
591
- function doChange(input, hex, opacity) {
592
-
593
- var settings = input.data('minicolors-settings'),
594
- lastChange = input.data('minicolors-lastChange');
595
-
596
- // Only run if it actually changed
597
- if( !lastChange || lastChange.hex !== hex || lastChange.opacity !== opacity ) {
598
-
599
- // Remember last-changed value
600
- input.data('minicolors-lastChange', {
601
- hex: hex,
602
- opacity: opacity
603
- });
604
-
605
- // Fire change event
606
- if( settings.change ) {
607
- if( settings.changeDelay ) {
608
- // Call after a delay
609
- clearTimeout(input.data('minicolors-changeTimeout'));
610
- input.data('minicolors-changeTimeout', setTimeout( function() {
611
- settings.change.call(input.get(0), hex, opacity);
612
- }, settings.changeDelay));
613
- } else {
614
- // Call immediately
615
- settings.change.call(input.get(0), hex, opacity);
616
- }
617
- }
618
- input.trigger('change').trigger('input');
619
- }
620
-
621
- }
622
-
623
- // Generates an RGB(A) object based on the input's value
624
- function rgbObject(input) {
625
- var hex = parseHex($(input).val(), true),
626
- rgb = hex2rgb(hex),
627
- opacity = $(input).attr('data-opacity');
628
- if( !rgb ) return null;
629
- if( opacity !== undefined ) $.extend(rgb, { a: parseFloat(opacity) });
630
- return rgb;
631
- }
632
-
633
- // Genearates an RGB(A) string based on the input's value
634
- function rgbString(input, alpha) {
635
- var hex = parseHex($(input).val(), true),
636
- rgb = hex2rgb(hex),
637
- opacity = $(input).attr('data-opacity');
638
- if( !rgb ) return null;
639
- if( opacity === undefined ) opacity = 1;
640
- if( alpha ) {
641
- return 'rgba(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ', ' + parseFloat(opacity) + ')';
642
- } else {
643
- return 'rgb(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ')';
644
- }
645
- }
646
-
647
- // Converts to the letter case specified in settings
648
- function convertCase(string, letterCase) {
649
- return letterCase === 'uppercase' ? string.toUpperCase() : string.toLowerCase();
650
- }
651
-
652
- // Parses a string and returns a valid hex string when possible
653
- function parseHex(string, expand) {
654
- string = string.replace(/[^A-F0-9]/ig, '');
655
- if( string.length !== 3 && string.length !== 6 ) return '';
656
- if( string.length === 3 && expand ) {
657
- string = string[0] + string[0] + string[1] + string[1] + string[2] + string[2];
658
- }
659
- return '#' + string;
660
- }
661
-
662
- // Keeps value within min and max
663
- function keepWithin(value, min, max) {
664
- if( value < min ) value = min;
665
- if( value > max ) value = max;
666
- return value;
667
- }
668
-
669
- // Converts an HSB object to an RGB object
670
- function hsb2rgb(hsb) {
671
- var rgb = {};
672
- var h = Math.round(hsb.h);
673
- var s = Math.round(hsb.s * 255 / 100);
674
- var v = Math.round(hsb.b * 255 / 100);
675
- if(s === 0) {
676
- rgb.r = rgb.g = rgb.b = v;
677
- } else {
678
- var t1 = v;
679
- var t2 = (255 - s) * v / 255;
680
- var t3 = (t1 - t2) * (h % 60) / 60;
681
- if( h === 360 ) h = 0;
682
- if( h < 60 ) { rgb.r = t1; rgb.b = t2; rgb.g = t2 + t3; }
683
- else if( h < 120 ) {rgb.g = t1; rgb.b = t2; rgb.r = t1 - t3; }
684
- else if( h < 180 ) {rgb.g = t1; rgb.r = t2; rgb.b = t2 + t3; }
685
- else if( h < 240 ) {rgb.b = t1; rgb.r = t2; rgb.g = t1 - t3; }
686
- else if( h < 300 ) {rgb.b = t1; rgb.g = t2; rgb.r = t2 + t3; }
687
- else if( h < 360 ) {rgb.r = t1; rgb.g = t2; rgb.b = t1 - t3; }
688
- else { rgb.r = 0; rgb.g = 0; rgb.b = 0; }
689
- }
690
- return {
691
- r: Math.round(rgb.r),
692
- g: Math.round(rgb.g),
693
- b: Math.round(rgb.b)
694
- };
695
- }
696
-
697
- // Converts an RGB object to a hex string
698
- function rgb2hex(rgb) {
699
- var hex = [
700
- rgb.r.toString(16),
701
- rgb.g.toString(16),
702
- rgb.b.toString(16)
703
- ];
704
- $.each(hex, function(nr, val) {
705
- if (val.length === 1) hex[nr] = '0' + val;
706
- });
707
- return '#' + hex.join('');
708
- }
709
-
710
- // Converts an HSB object to a hex string
711
- function hsb2hex(hsb) {
712
- return rgb2hex(hsb2rgb(hsb));
713
- }
714
-
715
- // Converts a hex string to an HSB object
716
- function hex2hsb(hex) {
717
- var hsb = rgb2hsb(hex2rgb(hex));
718
- if( hsb.s === 0 ) hsb.h = 360;
719
- return hsb;
720
- }
721
-
722
- // Converts an RGB object to an HSB object
723
- function rgb2hsb(rgb) {
724
- var hsb = { h: 0, s: 0, b: 0 };
725
- var min = Math.min(rgb.r, rgb.g, rgb.b);
726
- var max = Math.max(rgb.r, rgb.g, rgb.b);
727
- var delta = max - min;
728
- hsb.b = max;
729
- hsb.s = max !== 0 ? 255 * delta / max : 0;
730
- if( hsb.s !== 0 ) {
731
- if( rgb.r === max ) {
732
- hsb.h = (rgb.g - rgb.b) / delta;
733
- } else if( rgb.g === max ) {
734
- hsb.h = 2 + (rgb.b - rgb.r) / delta;
735
- } else {
736
- hsb.h = 4 + (rgb.r - rgb.g) / delta;
737
- }
738
- } else {
739
- hsb.h = -1;
740
- }
741
- hsb.h *= 60;
742
- if( hsb.h < 0 ) {
743
- hsb.h += 360;
744
- }
745
- hsb.s *= 100/255;
746
- hsb.b *= 100/255;
747
- return hsb;
748
- }
749
-
750
- // Converts a hex string to an RGB object
751
- function hex2rgb(hex) {
752
- hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16);
753
- return {
754
- r: hex >> 16,
755
- g: (hex & 0x00FF00) >> 8,
756
- b: (hex & 0x0000FF)
757
- };
758
- }
759
-
760
- // Handle events
761
- $(document)
762
- // Hide on clicks outside of the control
763
- .on('mousedown.minicolors touchstart.minicolors', function(event) {
764
- if( !$(event.target).parents().add(event.target).hasClass('minicolors') ) {
765
- hide();
766
- }
767
- })
768
- // Start moving
769
- .on('mousedown.minicolors touchstart.minicolors', '.minicolors-grid, .minicolors-slider, .minicolors-opacity-slider', function(event) {
770
- var target = $(this);
771
- event.preventDefault();
772
- $(document).data('minicolors-target', target);
773
- move(target, event, true);
774
- })
775
- // Move pickers
776
- .on('mousemove.minicolors touchmove.minicolors', function(event) {
777
- var target = $(document).data('minicolors-target');
778
- if( target ) move(target, event);
779
- })
780
- // Stop moving
781
- .on('mouseup.minicolors touchend.minicolors', function() {
782
- $(this).removeData('minicolors-target');
783
- })
784
- // Show panel when swatch is clicked
785
- .on('mousedown.minicolors touchstart.minicolors', '.minicolors-swatch', function(event) {
786
- var input = $(this).parent().find('.minicolors-input');
787
- event.preventDefault();
788
- show(input);
789
- })
790
- // Show on focus
791
- .on('focus.minicolors', '.minicolors-input', function() {
792
- var input = $(this);
793
- if( !input.data('minicolors-initialized') ) return;
794
- show(input);
795
- })
796
- // Fix hex on blur
797
- .on('blur.minicolors', '.minicolors-input', function() {
798
- var input = $(this),
799
- settings = input.data('minicolors-settings');
800
- if( !input.data('minicolors-initialized') ) return;
801
-
802
- // Parse Hex
803
- input.val(parseHex(input.val(), true));
804
-
805
- // Is it blank?
806
- if( input.val() === '' ) input.val(parseHex(settings.defaultValue, true));
807
-
808
- // Adjust case
809
- input.val( convertCase(input.val(), settings.letterCase) );
810
-
811
- })
812
- // Handle keypresses
813
- .on('keydown.minicolors', '.minicolors-input', function(event) {
814
- var input = $(this);
815
- if( !input.data('minicolors-initialized') ) return;
816
- switch(event.keyCode) {
817
- case 9: // tab
818
- hide();
819
- break;
820
- case 13: // enter
821
- case 27: // esc
822
- hide();
823
- input.blur();
824
- break;
825
- }
826
- })
827
- // Update on keyup
828
- .on('keyup.minicolors', '.minicolors-input', function() {
829
- var input = $(this);
830
- if( !input.data('minicolors-initialized') ) return;
831
- updateFromInput(input, true);
832
- })
833
- // Update on paste
834
- .on('paste.minicolors', '.minicolors-input', function() {
835
- var input = $(this);
836
- if( !input.data('minicolors-initialized') ) return;
837
- setTimeout( function() {
838
- updateFromInput(input, true);
839
- }, 1);
840
- });
841
-
842
- })(jQuery);
11
+ (function (factory) {
12
+ /* jshint ignore:start */
13
+ if (typeof define === 'function' && define.amd) {
14
+ // AMD. Register as an anonymous module.
15
+ define(['jquery'], factory);
16
+ } else if (typeof exports === 'object') {
17
+ // Node/CommonJS
18
+ module.exports = factory(require('jquery'));
19
+ } else {
20
+ // Browser globals
21
+ factory(jQuery);
22
+ }
23
+ /* jshint ignore:end */
24
+ }(function ($) {
25
+
26
+ 'use strict';
27
+
28
+ // Defaults
29
+ $.minicolors = {
30
+ defaults: {
31
+ animationSpeed: 50,
32
+ animationEasing: 'swing',
33
+ change: null,
34
+ changeDelay: 0,
35
+ control: 'hue',
36
+ dataUris: true,
37
+ defaultValue: '',
38
+ format: 'hex',
39
+ hide: null,
40
+ hideSpeed: 100,
41
+ inline: false,
42
+ keywords: '',
43
+ letterCase: 'lowercase',
44
+ opacity: false,
45
+ position: 'bottom left',
46
+ show: null,
47
+ showSpeed: 100,
48
+ theme: 'default'
49
+ }
50
+ };
51
+
52
+ // Public methods
53
+ $.extend($.fn, {
54
+ minicolors: function(method, data) {
55
+
56
+ switch(method) {
57
+
58
+ // Destroy the control
59
+ case 'destroy':
60
+ $(this).each( function() {
61
+ destroy($(this));
62
+ });
63
+ return $(this);
64
+
65
+ // Hide the color picker
66
+ case 'hide':
67
+ hide();
68
+ return $(this);
69
+
70
+ // Get/set opacity
71
+ case 'opacity':
72
+ // Getter
73
+ if( data === undefined ) {
74
+ // Getter
75
+ return $(this).attr('data-opacity');
76
+ } else {
77
+ // Setter
78
+ $(this).each( function() {
79
+ updateFromInput($(this).attr('data-opacity', data));
80
+ });
81
+ }
82
+ return $(this);
83
+
84
+ // Get an RGB(A) object based on the current color/opacity
85
+ case 'rgbObject':
86
+ return rgbObject($(this), method === 'rgbaObject');
87
+
88
+ // Get an RGB(A) string based on the current color/opacity
89
+ case 'rgbString':
90
+ case 'rgbaString':
91
+ return rgbString($(this), method === 'rgbaString');
92
+
93
+ // Get/set settings on the fly
94
+ case 'settings':
95
+ if( data === undefined ) {
96
+ return $(this).data('minicolors-settings');
97
+ } else {
98
+ // Setter
99
+ $(this).each( function() {
100
+ var settings = $(this).data('minicolors-settings') || {};
101
+ destroy($(this));
102
+ $(this).minicolors($.extend(true, settings, data));
103
+ });
104
+ }
105
+ return $(this);
106
+
107
+ // Show the color picker
108
+ case 'show':
109
+ show( $(this).eq(0) );
110
+ return $(this);
111
+
112
+ // Get/set the hex color value
113
+ case 'value':
114
+ if( data === undefined ) {
115
+ // Getter
116
+ return $(this).val();
117
+ } else {
118
+ // Setter
119
+ $(this).each( function() {
120
+ if( typeof(data) === 'object' ) {
121
+ if( data.opacity ) {
122
+ $(this).attr('data-opacity', keepWithin(data.opacity, 0, 1));
123
+ }
124
+ if( data.color ) {
125
+ $(this).val(data.color);
126
+ }
127
+ } else {
128
+ $(this).val(data);
129
+ }
130
+ updateFromInput($(this));
131
+ });
132
+ }
133
+ return $(this);
134
+
135
+ // Initializes the control
136
+ default:
137
+ if( method !== 'create' ) data = method;
138
+ $(this).each( function() {
139
+ init($(this), data);
140
+ });
141
+ return $(this);
142
+
143
+ }
144
+
145
+ }
146
+ });
147
+
148
+ // Initialize input elements
149
+ function init(input, settings) {
150
+
151
+ var minicolors = $('<div class="minicolors" />'),
152
+ defaults = $.minicolors.defaults,
153
+ opacity = input.attr('data-opacity'),
154
+ size;
155
+
156
+ // Do nothing if already initialized
157
+ if( input.data('minicolors-initialized') ) return;
158
+
159
+ // Handle settings
160
+ settings = $.extend(true, {}, defaults, settings);
161
+
162
+ // The wrapper
163
+ minicolors
164
+ .addClass('minicolors-theme-' + settings.theme)
165
+ .toggleClass('minicolors-with-opacity', settings.opacity)
166
+ .toggleClass('minicolors-no-data-uris', settings.dataUris !== true);
167
+
168
+ // Custom positioning
169
+ if( settings.position !== undefined ) {
170
+ $.each(settings.position.split(' '), function() {
171
+ minicolors.addClass('minicolors-position-' + this);
172
+ });
173
+ }
174
+
175
+ // Input size
176
+ if( settings.format === 'rgb' ) {
177
+ size = settings.opacity ? '25' : '20';
178
+ } else {
179
+ size = settings.keywords ? '11' : '7';
180
+ }
181
+
182
+ // The input
183
+ input
184
+ .addClass('minicolors-input')
185
+ .data('minicolors-initialized', false)
186
+ .data('minicolors-settings', settings)
187
+ .prop('size', size)
188
+ .wrap(minicolors)
189
+ .after(
190
+ '<div class="minicolors-panel minicolors-slider-' + settings.control + '">' +
191
+ '<div class="minicolors-slider minicolors-sprite">' +
192
+ '<div class="minicolors-picker"></div>' +
193
+ '</div>' +
194
+ '<div class="minicolors-opacity-slider minicolors-sprite">' +
195
+ '<div class="minicolors-picker"></div>' +
196
+ '</div>' +
197
+ '<div class="minicolors-grid minicolors-sprite">' +
198
+ '<div class="minicolors-grid-inner"></div>' +
199
+ '<div class="minicolors-picker"><div></div></div>' +
200
+ '</div>' +
201
+ '</div>'
202
+ );
203
+
204
+ // The swatch
205
+ if( !settings.inline ) {
206
+ input.after('<span class="minicolors-swatch minicolors-sprite"><span class="minicolors-swatch-color"></span></span>');
207
+ input.next('.minicolors-swatch').on('click', function(event) {
208
+ event.preventDefault();
209
+ input.focus();
210
+ });
211
+ }
212
+
213
+ // Prevent text selection in IE
214
+ input.parent().find('.minicolors-panel').on('selectstart', function() { return false; }).end();
215
+
216
+ // Inline controls
217
+ if( settings.inline ) input.parent().addClass('minicolors-inline');
218
+
219
+ updateFromInput(input, false);
220
+
221
+ input.data('minicolors-initialized', true);
222
+
223
+ }
224
+
225
+ // Returns the input back to its original state
226
+ function destroy(input) {
227
+
228
+ var minicolors = input.parent();
229
+
230
+ // Revert the input element
231
+ input
232
+ .removeData('minicolors-initialized')
233
+ .removeData('minicolors-settings')
234
+ .removeProp('size')
235
+ .removeClass('minicolors-input');
236
+
237
+ // Remove the wrap and destroy whatever remains
238
+ minicolors.before(input).remove();
239
+
240
+ }
241
+
242
+ // Shows the specified dropdown panel
243
+ function show(input) {
244
+
245
+ var minicolors = input.parent(),
246
+ panel = minicolors.find('.minicolors-panel'),
247
+ settings = input.data('minicolors-settings');
248
+
249
+ // Do nothing if uninitialized, disabled, inline, or already open
250
+ if( !input.data('minicolors-initialized') ||
251
+ input.prop('disabled') ||
252
+ minicolors.hasClass('minicolors-inline') ||
253
+ minicolors.hasClass('minicolors-focus')
254
+ ) return;
255
+
256
+ hide();
257
+
258
+ minicolors.addClass('minicolors-focus');
259
+ panel
260
+ .stop(true, true)
261
+ .fadeIn(settings.showSpeed, function() {
262
+ if( settings.show ) settings.show.call(input.get(0));
263
+ });
264
+
265
+ }
266
+
267
+ // Hides all dropdown panels
268
+ function hide() {
269
+
270
+ $('.minicolors-focus').each( function() {
271
+
272
+ var minicolors = $(this),
273
+ input = minicolors.find('.minicolors-input'),
274
+ panel = minicolors.find('.minicolors-panel'),
275
+ settings = input.data('minicolors-settings');
276
+
277
+ panel.fadeOut(settings.hideSpeed, function() {
278
+ if( settings.hide ) settings.hide.call(input.get(0));
279
+ minicolors.removeClass('minicolors-focus');
280
+ });
281
+
282
+ });
283
+ }
284
+
285
+ // Moves the selected picker
286
+ function move(target, event, animate) {
287
+
288
+ var input = target.parents('.minicolors').find('.minicolors-input'),
289
+ settings = input.data('minicolors-settings'),
290
+ picker = target.find('[class$=-picker]'),
291
+ offsetX = target.offset().left,
292
+ offsetY = target.offset().top,
293
+ x = Math.round(event.pageX - offsetX),
294
+ y = Math.round(event.pageY - offsetY),
295
+ duration = animate ? settings.animationSpeed : 0,
296
+ wx, wy, r, phi;
297
+
298
+ // Touch support
299
+ if( event.originalEvent.changedTouches ) {
300
+ x = event.originalEvent.changedTouches[0].pageX - offsetX;
301
+ y = event.originalEvent.changedTouches[0].pageY - offsetY;
302
+ }
303
+
304
+ // Constrain picker to its container
305
+ if( x < 0 ) x = 0;
306
+ if( y < 0 ) y = 0;
307
+ if( x > target.width() ) x = target.width();
308
+ if( y > target.height() ) y = target.height();
309
+
310
+ // Constrain color wheel values to the wheel
311
+ if( target.parent().is('.minicolors-slider-wheel') && picker.parent().is('.minicolors-grid') ) {
312
+ wx = 75 - x;
313
+ wy = 75 - y;
314
+ r = Math.sqrt(wx * wx + wy * wy);
315
+ phi = Math.atan2(wy, wx);
316
+ if( phi < 0 ) phi += Math.PI * 2;
317
+ if( r > 75 ) {
318
+ r = 75;
319
+ x = 75 - (75 * Math.cos(phi));
320
+ y = 75 - (75 * Math.sin(phi));
321
+ }
322
+ x = Math.round(x);
323
+ y = Math.round(y);
324
+ }
325
+
326
+ // Move the picker
327
+ if( target.is('.minicolors-grid') ) {
328
+ picker
329
+ .stop(true)
330
+ .animate({
331
+ top: y + 'px',
332
+ left: x + 'px'
333
+ }, duration, settings.animationEasing, function() {
334
+ updateFromControl(input, target);
335
+ });
336
+ } else {
337
+ picker
338
+ .stop(true)
339
+ .animate({
340
+ top: y + 'px'
341
+ }, duration, settings.animationEasing, function() {
342
+ updateFromControl(input, target);
343
+ });
344
+ }
345
+
346
+ }
347
+
348
+ // Sets the input based on the color picker values
349
+ function updateFromControl(input, target) {
350
+
351
+ function getCoords(picker, container) {
352
+
353
+ var left, top;
354
+ if( !picker.length || !container ) return null;
355
+ left = picker.offset().left;
356
+ top = picker.offset().top;
357
+
358
+ return {
359
+ x: left - container.offset().left + (picker.outerWidth() / 2),
360
+ y: top - container.offset().top + (picker.outerHeight() / 2)
361
+ };
362
+
363
+ }
364
+
365
+ var hue, saturation, brightness, x, y, r, phi,
366
+
367
+ hex = input.val(),
368
+ opacity = input.attr('data-opacity'),
369
+ value,
370
+
371
+ // Helpful references
372
+ minicolors = input.parent(),
373
+ settings = input.data('minicolors-settings'),
374
+ swatch = minicolors.find('.minicolors-swatch'),
375
+
376
+ // Panel objects
377
+ grid = minicolors.find('.minicolors-grid'),
378
+ slider = minicolors.find('.minicolors-slider'),
379
+ opacitySlider = minicolors.find('.minicolors-opacity-slider'),
380
+
381
+ // Picker objects
382
+ gridPicker = grid.find('[class$=-picker]'),
383
+ sliderPicker = slider.find('[class$=-picker]'),
384
+ opacityPicker = opacitySlider.find('[class$=-picker]'),
385
+
386
+ // Picker positions
387
+ gridPos = getCoords(gridPicker, grid),
388
+ sliderPos = getCoords(sliderPicker, slider),
389
+ opacityPos = getCoords(opacityPicker, opacitySlider);
390
+
391
+ // Handle colors
392
+ if( target.is('.minicolors-grid, .minicolors-slider, .minicolors-opacity-slider') ) {
393
+
394
+ // Determine HSB values
395
+ switch(settings.control) {
396
+
397
+ case 'wheel':
398
+ // Calculate hue, saturation, and brightness
399
+ x = (grid.width() / 2) - gridPos.x;
400
+ y = (grid.height() / 2) - gridPos.y;
401
+ r = Math.sqrt(x * x + y * y);
402
+ phi = Math.atan2(y, x);
403
+ if( phi < 0 ) phi += Math.PI * 2;
404
+ if( r > 75 ) {
405
+ r = 75;
406
+ gridPos.x = 69 - (75 * Math.cos(phi));
407
+ gridPos.y = 69 - (75 * Math.sin(phi));
408
+ }
409
+ saturation = keepWithin(r / 0.75, 0, 100);
410
+ hue = keepWithin(phi * 180 / Math.PI, 0, 360);
411
+ brightness = keepWithin(100 - Math.floor(sliderPos.y * (100 / slider.height())), 0, 100);
412
+ hex = hsb2hex({
413
+ h: hue,
414
+ s: saturation,
415
+ b: brightness
416
+ });
417
+
418
+ // Update UI
419
+ slider.css('backgroundColor', hsb2hex({ h: hue, s: saturation, b: 100 }));
420
+ break;
421
+
422
+ case 'saturation':
423
+ // Calculate hue, saturation, and brightness
424
+ hue = keepWithin(parseInt(gridPos.x * (360 / grid.width()), 10), 0, 360);
425
+ saturation = keepWithin(100 - Math.floor(sliderPos.y * (100 / slider.height())), 0, 100);
426
+ brightness = keepWithin(100 - Math.floor(gridPos.y * (100 / grid.height())), 0, 100);
427
+ hex = hsb2hex({
428
+ h: hue,
429
+ s: saturation,
430
+ b: brightness
431
+ });
432
+
433
+ // Update UI
434
+ slider.css('backgroundColor', hsb2hex({ h: hue, s: 100, b: brightness }));
435
+ minicolors.find('.minicolors-grid-inner').css('opacity', saturation / 100);
436
+ break;
437
+
438
+ case 'brightness':
439
+ // Calculate hue, saturation, and brightness
440
+ hue = keepWithin(parseInt(gridPos.x * (360 / grid.width()), 10), 0, 360);
441
+ saturation = keepWithin(100 - Math.floor(gridPos.y * (100 / grid.height())), 0, 100);
442
+ brightness = keepWithin(100 - Math.floor(sliderPos.y * (100 / slider.height())), 0, 100);
443
+ hex = hsb2hex({
444
+ h: hue,
445
+ s: saturation,
446
+ b: brightness
447
+ });
448
+
449
+ // Update UI
450
+ slider.css('backgroundColor', hsb2hex({ h: hue, s: saturation, b: 100 }));
451
+ minicolors.find('.minicolors-grid-inner').css('opacity', 1 - (brightness / 100));
452
+ break;
453
+
454
+ default:
455
+ // Calculate hue, saturation, and brightness
456
+ hue = keepWithin(360 - parseInt(sliderPos.y * (360 / slider.height()), 10), 0, 360);
457
+ saturation = keepWithin(Math.floor(gridPos.x * (100 / grid.width())), 0, 100);
458
+ brightness = keepWithin(100 - Math.floor(gridPos.y * (100 / grid.height())), 0, 100);
459
+ hex = hsb2hex({
460
+ h: hue,
461
+ s: saturation,
462
+ b: brightness
463
+ });
464
+
465
+ // Update UI
466
+ grid.css('backgroundColor', hsb2hex({ h: hue, s: 100, b: 100 }));
467
+ break;
468
+
469
+ }
470
+
471
+ // Handle opacity
472
+ if( settings.opacity ) {
473
+ opacity = parseFloat(1 - (opacityPos.y / opacitySlider.height())).toFixed(2);
474
+ } else {
475
+ opacity = 1;
476
+ }
477
+ if( settings.opacity ) input.attr('data-opacity', opacity);
478
+
479
+ // Set color string
480
+ if( settings.format === 'rgb' ) {
481
+ // Returns RGB(A) string
482
+ var rgb = hex2rgb(hex),
483
+ opacity = input.attr('data-opacity') === '' ? 1 : keepWithin( parseFloat( input.attr('data-opacity') ).toFixed(2), 0, 1 );
484
+ if( isNaN( opacity ) || !settings.opacity ) opacity = 1;
485
+
486
+ if( input.minicolors('rgbObject').a <= 1 && rgb && settings.opacity) {
487
+ // Set RGBA string if alpha
488
+ value = 'rgba(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ', ' + parseFloat( opacity ) + ')';
489
+ } else {
490
+ // Set RGB string (alpha = 1)
491
+ value = 'rgb(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ')';
492
+ }
493
+ } else {
494
+ // Returns hex color
495
+ value = convertCase( hex, settings.letterCase );
496
+ }
497
+
498
+ // Update value from picker
499
+ input.val( value );
500
+ }
501
+
502
+ // Set swatch color
503
+ swatch.find('span').css({
504
+ backgroundColor: hex,
505
+ opacity: opacity
506
+ });
507
+
508
+ // Handle change event
509
+ doChange(input, value, opacity);
510
+
511
+ }
512
+
513
+ // Sets the color picker values from the input
514
+ function updateFromInput(input, preserveInputValue) {
515
+
516
+ var hex,
517
+ hsb,
518
+ opacity,
519
+ keywords,
520
+ alpha,
521
+ value,
522
+ x, y, r, phi,
523
+
524
+ // Helpful references
525
+ minicolors = input.parent(),
526
+ settings = input.data('minicolors-settings'),
527
+ swatch = minicolors.find('.minicolors-swatch'),
528
+
529
+ // Panel objects
530
+ grid = minicolors.find('.minicolors-grid'),
531
+ slider = minicolors.find('.minicolors-slider'),
532
+ opacitySlider = minicolors.find('.minicolors-opacity-slider'),
533
+
534
+ // Picker objects
535
+ gridPicker = grid.find('[class$=-picker]'),
536
+ sliderPicker = slider.find('[class$=-picker]'),
537
+ opacityPicker = opacitySlider.find('[class$=-picker]');
538
+
539
+ // Determine hex/HSB values
540
+ if( isRgb(input.val()) ) {
541
+ // If input value is a rgb(a) string, convert it to hex color and update opacity
542
+ hex = rgbString2hex(input.val());
543
+ alpha = keepWithin(parseFloat(getAlpha(input.val())).toFixed(2), 0, 1);
544
+ if( alpha ) {
545
+ input.attr('data-opacity', alpha);
546
+ }
547
+ } else {
548
+ hex = convertCase(parseHex(input.val(), true), settings.letterCase);
549
+ }
550
+
551
+ if( !hex ){
552
+ hex = convertCase(parseInput(settings.defaultValue, true), settings.letterCase);
553
+ }
554
+ hsb = hex2hsb(hex);
555
+
556
+ // Get array of lowercase keywords
557
+ keywords = !settings.keywords ? [] : $.map(settings.keywords.split(','), function(a) {
558
+ return $.trim(a.toLowerCase());
559
+ });
560
+
561
+ // Set color string
562
+ if( input.val() !== '' && $.inArray(input.val().toLowerCase(), keywords) > -1 ) {
563
+ value = convertCase(input.val());
564
+ } else {
565
+ value = isRgb(input.val()) ? parseRgb(input.val()) : hex;
566
+ }
567
+
568
+ // Update input value
569
+ if( !preserveInputValue ) input.val(value);
570
+
571
+ // Determine opacity value
572
+ if( settings.opacity ) {
573
+ // Get from data-opacity attribute and keep within 0-1 range
574
+ opacity = input.attr('data-opacity') === '' ? 1 : keepWithin(parseFloat(input.attr('data-opacity')).toFixed(2), 0, 1);
575
+ if( isNaN(opacity) ) opacity = 1;
576
+ input.attr('data-opacity', opacity);
577
+ swatch.find('span').css('opacity', opacity);
578
+
579
+ // Set opacity picker position
580
+ y = keepWithin(opacitySlider.height() - (opacitySlider.height() * opacity), 0, opacitySlider.height());
581
+ opacityPicker.css('top', y + 'px');
582
+ }
583
+
584
+ // Set opacity to zero if input value is transparent
585
+ if( input.val().toLowerCase() === 'transparent' ) {
586
+ swatch.find('span').css('opacity', 0);
587
+ }
588
+
589
+ // Update swatch
590
+ swatch.find('span').css('backgroundColor', hex);
591
+
592
+ // Determine picker locations
593
+ switch(settings.control) {
594
+
595
+ case 'wheel':
596
+ // Set grid position
597
+ r = keepWithin(Math.ceil(hsb.s * 0.75), 0, grid.height() / 2);
598
+ phi = hsb.h * Math.PI / 180;
599
+ x = keepWithin(75 - Math.cos(phi) * r, 0, grid.width());
600
+ y = keepWithin(75 - Math.sin(phi) * r, 0, grid.height());
601
+ gridPicker.css({
602
+ top: y + 'px',
603
+ left: x + 'px'
604
+ });
605
+
606
+ // Set slider position
607
+ y = 150 - (hsb.b / (100 / grid.height()));
608
+ if( hex === '' ) y = 0;
609
+ sliderPicker.css('top', y + 'px');
610
+
611
+ // Update panel color
612
+ slider.css('backgroundColor', hsb2hex({ h: hsb.h, s: hsb.s, b: 100 }));
613
+ break;
614
+
615
+ case 'saturation':
616
+ // Set grid position
617
+ x = keepWithin((5 * hsb.h) / 12, 0, 150);
618
+ y = keepWithin(grid.height() - Math.ceil(hsb.b / (100 / grid.height())), 0, grid.height());
619
+ gridPicker.css({
620
+ top: y + 'px',
621
+ left: x + 'px'
622
+ });
623
+
624
+ // Set slider position
625
+ y = keepWithin(slider.height() - (hsb.s * (slider.height() / 100)), 0, slider.height());
626
+ sliderPicker.css('top', y + 'px');
627
+
628
+ // Update UI
629
+ slider.css('backgroundColor', hsb2hex({ h: hsb.h, s: 100, b: hsb.b }));
630
+ minicolors.find('.minicolors-grid-inner').css('opacity', hsb.s / 100);
631
+ break;
632
+
633
+ case 'brightness':
634
+ // Set grid position
635
+ x = keepWithin((5 * hsb.h) / 12, 0, 150);
636
+ y = keepWithin(grid.height() - Math.ceil(hsb.s / (100 / grid.height())), 0, grid.height());
637
+ gridPicker.css({
638
+ top: y + 'px',
639
+ left: x + 'px'
640
+ });
641
+
642
+ // Set slider position
643
+ y = keepWithin(slider.height() - (hsb.b * (slider.height() / 100)), 0, slider.height());
644
+ sliderPicker.css('top', y + 'px');
645
+
646
+ // Update UI
647
+ slider.css('backgroundColor', hsb2hex({ h: hsb.h, s: hsb.s, b: 100 }));
648
+ minicolors.find('.minicolors-grid-inner').css('opacity', 1 - (hsb.b / 100));
649
+ break;
650
+
651
+ default:
652
+ // Set grid position
653
+ x = keepWithin(Math.ceil(hsb.s / (100 / grid.width())), 0, grid.width());
654
+ y = keepWithin(grid.height() - Math.ceil(hsb.b / (100 / grid.height())), 0, grid.height());
655
+ gridPicker.css({
656
+ top: y + 'px',
657
+ left: x + 'px'
658
+ });
659
+
660
+ // Set slider position
661
+ y = keepWithin(slider.height() - (hsb.h / (360 / slider.height())), 0, slider.height());
662
+ sliderPicker.css('top', y + 'px');
663
+
664
+ // Update panel color
665
+ grid.css('backgroundColor', hsb2hex({ h: hsb.h, s: 100, b: 100 }));
666
+ break;
667
+
668
+ }
669
+
670
+ // Fire change event, but only if minicolors is fully initialized
671
+ if( input.data('minicolors-initialized') ) {
672
+ doChange(input, value, opacity);
673
+ }
674
+
675
+ }
676
+
677
+ // Runs the change and changeDelay callbacks
678
+ function doChange(input, value, opacity) {
679
+
680
+ var settings = input.data('minicolors-settings'),
681
+ lastChange = input.data('minicolors-lastChange');
682
+
683
+ // Only run if it actually changed
684
+ if( !lastChange || lastChange.value !== value || lastChange.opacity !== opacity ) {
685
+
686
+ // Remember last-changed value
687
+ input.data('minicolors-lastChange', {
688
+ value: value,
689
+ opacity: opacity
690
+ });
691
+
692
+ // Fire change event
693
+ if( settings.change ) {
694
+ if( settings.changeDelay ) {
695
+ // Call after a delay
696
+ clearTimeout(input.data('minicolors-changeTimeout'));
697
+ input.data('minicolors-changeTimeout', setTimeout( function() {
698
+ settings.change.call(input.get(0), value, opacity);
699
+ }, settings.changeDelay));
700
+ } else {
701
+ // Call immediately
702
+ settings.change.call(input.get(0), value, opacity);
703
+ }
704
+ }
705
+ input.trigger('change').trigger('input');
706
+ }
707
+
708
+ }
709
+
710
+ // Generates an RGB(A) object based on the input's value
711
+ function rgbObject(input) {
712
+ var hex = parseHex($(input).val(), true),
713
+ rgb = hex2rgb(hex),
714
+ opacity = $(input).attr('data-opacity');
715
+ if( !rgb ) return null;
716
+ if( opacity !== undefined ) $.extend(rgb, { a: parseFloat(opacity) });
717
+ return rgb;
718
+ }
719
+
720
+ // Generates an RGB(A) string based on the input's value
721
+ function rgbString(input, alpha) {
722
+ var hex = parseHex($(input).val(), true),
723
+ rgb = hex2rgb(hex),
724
+ opacity = $(input).attr('data-opacity');
725
+ if( !rgb ) return null;
726
+ if( opacity === undefined ) opacity = 1;
727
+ if( alpha ) {
728
+ return 'rgba(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ', ' + parseFloat(opacity) + ')';
729
+ } else {
730
+ return 'rgb(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ')';
731
+ }
732
+ }
733
+
734
+ // Converts to the letter case specified in settings
735
+ function convertCase(string, letterCase) {
736
+ return letterCase === 'uppercase' ? string.toUpperCase() : string.toLowerCase();
737
+ }
738
+
739
+ // Parses a string and returns a valid hex string when possible
740
+ function parseHex(string, expand) {
741
+ string = string.replace(/^#/g, '');
742
+ if( !string.match(/^[A-F0-9]{3,6}/ig) ) return '';
743
+ if( string.length !== 3 && string.length !== 6 ) return '';
744
+ if( string.length === 3 && expand ) {
745
+ string = string[0] + string[0] + string[1] + string[1] + string[2] + string[2];
746
+ }
747
+ return '#' + string;
748
+ }
749
+
750
+ // Parses a string and returns a valid RGB(A) string when possible
751
+ function parseRgb(string, obj) {
752
+
753
+ var values = string.replace(/[^\d,.]/g, ''),
754
+ rgba = values.split(','),
755
+ output;
756
+
757
+ rgba[0] = keepWithin(parseInt(rgba[0], 10), 0, 255);
758
+ rgba[1] = keepWithin(parseInt(rgba[1], 10), 0, 255);
759
+ rgba[2] = keepWithin(parseInt(rgba[2], 10), 0, 255);
760
+ if( rgba[3] ) {
761
+ rgba[3] = keepWithin(parseFloat(rgba[3], 10), 0, 1);
762
+ }
763
+
764
+ // Return RGBA object
765
+ if( obj ) {
766
+ return {
767
+ r: rgba[0],
768
+ g: rgba[1],
769
+ b: rgba[2],
770
+ a: rgba[3] ? rgba[3] : null
771
+ };
772
+ }
773
+
774
+ // Return RGBA string
775
+ if( typeof(rgba[3]) !== 'undefined' && rgba[3] <= 1 ) {
776
+ return 'rgba(' + rgba[0] + ', ' + rgba[1] + ', ' + rgba[2] + ', ' + rgba[3] + ')';
777
+ } else {
778
+ return 'rgb(' + rgba[0] + ', ' + rgba[1] + ', ' + rgba[2] + ')';
779
+ }
780
+
781
+ }
782
+
783
+ // Parses a string and returns a valid color string when possible
784
+ function parseInput(string, expand) {
785
+ if( isRgb(string) ) {
786
+ // Returns a valid rgb(a) string
787
+ return parseRgb(string);
788
+ } else {
789
+ return parseHex(string, expand);
790
+ }
791
+ }
792
+
793
+ // Keeps value within min and max
794
+ function keepWithin(value, min, max) {
795
+ if( value < min ) value = min;
796
+ if( value > max ) value = max;
797
+ return value;
798
+ }
799
+
800
+ // Checks if a string is a valid RGB(A) string
801
+ function isRgb(string) {
802
+ var rgb = string.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
803
+ return (rgb && rgb.length === 4) ? true : false;
804
+ }
805
+
806
+ // Function to get alpha from a RGB(A) string
807
+ function getAlpha(rgba) {
808
+ var rgba = rgba.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+(\.\d{1,2})?|\.\d{1,2})[\s+]?/i);
809
+ return (rgba && rgba.length === 6) ? rgba[4] : '1';
810
+ }
811
+
812
+ // Converts an HSB object to an RGB object
813
+ function hsb2rgb(hsb) {
814
+ var rgb = {};
815
+ var h = Math.round(hsb.h);
816
+ var s = Math.round(hsb.s * 255 / 100);
817
+ var v = Math.round(hsb.b * 255 / 100);
818
+ if(s === 0) {
819
+ rgb.r = rgb.g = rgb.b = v;
820
+ } else {
821
+ var t1 = v;
822
+ var t2 = (255 - s) * v / 255;
823
+ var t3 = (t1 - t2) * (h % 60) / 60;
824
+ if( h === 360 ) h = 0;
825
+ if( h < 60 ) { rgb.r = t1; rgb.b = t2; rgb.g = t2 + t3; }
826
+ else if( h < 120 ) {rgb.g = t1; rgb.b = t2; rgb.r = t1 - t3; }
827
+ else if( h < 180 ) {rgb.g = t1; rgb.r = t2; rgb.b = t2 + t3; }
828
+ else if( h < 240 ) {rgb.b = t1; rgb.r = t2; rgb.g = t1 - t3; }
829
+ else if( h < 300 ) {rgb.b = t1; rgb.g = t2; rgb.r = t2 + t3; }
830
+ else if( h < 360 ) {rgb.r = t1; rgb.g = t2; rgb.b = t1 - t3; }
831
+ else { rgb.r = 0; rgb.g = 0; rgb.b = 0; }
832
+ }
833
+ return {
834
+ r: Math.round(rgb.r),
835
+ g: Math.round(rgb.g),
836
+ b: Math.round(rgb.b)
837
+ };
838
+ }
839
+
840
+ // Converts an RGB string to a hex string
841
+ function rgbString2hex(rgb){
842
+ rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
843
+ return (rgb && rgb.length === 4) ? '#' +
844
+ ('0' + parseInt(rgb[1],10).toString(16)).slice(-2) +
845
+ ('0' + parseInt(rgb[2],10).toString(16)).slice(-2) +
846
+ ('0' + parseInt(rgb[3],10).toString(16)).slice(-2) : '';
847
+ }
848
+
849
+ // Converts an RGB object to a hex string
850
+ function rgb2hex(rgb) {
851
+ var hex = [
852
+ rgb.r.toString(16),
853
+ rgb.g.toString(16),
854
+ rgb.b.toString(16)
855
+ ];
856
+ $.each(hex, function(nr, val) {
857
+ if (val.length === 1) hex[nr] = '0' + val;
858
+ });
859
+ return '#' + hex.join('');
860
+ }
861
+
862
+ // Converts an HSB object to a hex string
863
+ function hsb2hex(hsb) {
864
+ return rgb2hex(hsb2rgb(hsb));
865
+ }
866
+
867
+ // Converts a hex string to an HSB object
868
+ function hex2hsb(hex) {
869
+ var hsb = rgb2hsb(hex2rgb(hex));
870
+ if( hsb.s === 0 ) hsb.h = 360;
871
+ return hsb;
872
+ }
873
+
874
+ // Converts an RGB object to an HSB object
875
+ function rgb2hsb(rgb) {
876
+ var hsb = { h: 0, s: 0, b: 0 };
877
+ var min = Math.min(rgb.r, rgb.g, rgb.b);
878
+ var max = Math.max(rgb.r, rgb.g, rgb.b);
879
+ var delta = max - min;
880
+ hsb.b = max;
881
+ hsb.s = max !== 0 ? 255 * delta / max : 0;
882
+ if( hsb.s !== 0 ) {
883
+ if( rgb.r === max ) {
884
+ hsb.h = (rgb.g - rgb.b) / delta;
885
+ } else if( rgb.g === max ) {
886
+ hsb.h = 2 + (rgb.b - rgb.r) / delta;
887
+ } else {
888
+ hsb.h = 4 + (rgb.r - rgb.g) / delta;
889
+ }
890
+ } else {
891
+ hsb.h = -1;
892
+ }
893
+ hsb.h *= 60;
894
+ if( hsb.h < 0 ) {
895
+ hsb.h += 360;
896
+ }
897
+ hsb.s *= 100/255;
898
+ hsb.b *= 100/255;
899
+ return hsb;
900
+ }
901
+
902
+ // Converts a hex string to an RGB object
903
+ function hex2rgb(hex) {
904
+ hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16);
905
+ return {
906
+ /* jshint ignore:start */
907
+ r: hex >> 16,
908
+ g: (hex & 0x00FF00) >> 8,
909
+ b: (hex & 0x0000FF)
910
+ /* jshint ignore:end */
911
+ };
912
+ }
913
+
914
+ // Handle events
915
+ $(document)
916
+ // Hide on clicks outside of the control
917
+ .on('mousedown.minicolors touchstart.minicolors', function(event) {
918
+ if( !$(event.target).parents().add(event.target).hasClass('minicolors') ) {
919
+ hide();
920
+ }
921
+ })
922
+ // Start moving
923
+ .on('mousedown.minicolors touchstart.minicolors', '.minicolors-grid, .minicolors-slider, .minicolors-opacity-slider', function(event) {
924
+ var target = $(this);
925
+ event.preventDefault();
926
+ $(document).data('minicolors-target', target);
927
+ move(target, event, true);
928
+ })
929
+ // Move pickers
930
+ .on('mousemove.minicolors touchmove.minicolors', function(event) {
931
+ var target = $(document).data('minicolors-target');
932
+ if( target ) move(target, event);
933
+ })
934
+ // Stop moving
935
+ .on('mouseup.minicolors touchend.minicolors', function() {
936
+ $(this).removeData('minicolors-target');
937
+ })
938
+ // Show panel when swatch is clicked
939
+ .on('mousedown.minicolors touchstart.minicolors', '.minicolors-swatch', function(event) {
940
+ var input = $(this).parent().find('.minicolors-input');
941
+ event.preventDefault();
942
+ show(input);
943
+ })
944
+ // Show on focus
945
+ .on('focus.minicolors', '.minicolors-input', function() {
946
+ var input = $(this);
947
+ if( !input.data('minicolors-initialized') ) return;
948
+ show(input);
949
+ })
950
+ // Update value on blur
951
+ .on('blur.minicolors', '.minicolors-input', function() {
952
+ var input = $(this),
953
+ settings = input.data('minicolors-settings'),
954
+ keywords,
955
+ hex,
956
+ rgba,
957
+ swatchOpacity,
958
+ value;
959
+
960
+ if( !input.data('minicolors-initialized') ) return;
961
+
962
+ // Get array of lowercase keywords
963
+ keywords = !settings.keywords ? [] : $.map(settings.keywords.split(','), function(a) {
964
+ return $.trim(a.toLowerCase());
965
+ });
966
+
967
+ // Set color string
968
+ if( input.val() !== '' && $.inArray(input.val().toLowerCase(), keywords) > -1 ) {
969
+ value = input.val();
970
+ } else {
971
+ // Get RGBA values for easy conversion
972
+ if( isRgb(input.val()) ) {
973
+ rgba = parseRgb(input.val(), true);
974
+ } else {
975
+ hex = parseHex(input.val(), true);
976
+ rgba = hex ? hex2rgb(hex) : null;
977
+ }
978
+
979
+ // Convert to format
980
+ if( rgba === null ) {
981
+ value = settings.defaultValue;
982
+ } else if( settings.format === 'rgb' ) {
983
+ value = settings.opacity ?
984
+ parseRgb('rgba(' + rgba.r + ',' + rgba.g + ',' + rgba.b + ',' + input.attr('data-opacity') + ')') :
985
+ parseRgb('rgb(' + rgba.r + ',' + rgba.g + ',' + rgba.b + ')');
986
+ } else {
987
+ value = rgb2hex(rgba);
988
+ }
989
+ }
990
+
991
+ // Update swatch opacity
992
+ swatchOpacity = settings.opacity ? input.attr('data-opacity') : 1;
993
+ if( value.toLowerCase() === 'transparent' ) swatchOpacity = 0;
994
+ input
995
+ .closest('.minicolors')
996
+ .find('.minicolors-swatch > span')
997
+ .css('opacity', swatchOpacity);
998
+
999
+ // Set input value
1000
+ input.val(value);
1001
+
1002
+ // Is it blank?
1003
+ if( input.val() === '' ) input.val(parseInput(settings.defaultValue, true));
1004
+
1005
+ // Adjust case
1006
+ input.val( convertCase(input.val(), settings.letterCase) );
1007
+
1008
+ })
1009
+ // Handle keypresses
1010
+ .on('keydown.minicolors', '.minicolors-input', function(event) {
1011
+ var input = $(this);
1012
+ if( !input.data('minicolors-initialized') ) return;
1013
+ switch(event.keyCode) {
1014
+ case 9: // tab
1015
+ hide();
1016
+ break;
1017
+ case 13: // enter
1018
+ case 27: // esc
1019
+ hide();
1020
+ input.blur();
1021
+ break;
1022
+ }
1023
+ })
1024
+ // Update on keyup
1025
+ .on('keyup.minicolors', '.minicolors-input', function() {
1026
+ var input = $(this);
1027
+ if( !input.data('minicolors-initialized') ) return;
1028
+ updateFromInput(input, true);
1029
+ })
1030
+ // Update on paste
1031
+ .on('paste.minicolors', '.minicolors-input', function() {
1032
+ var input = $(this);
1033
+ if( !input.data('minicolors-initialized') ) return;
1034
+ setTimeout( function() {
1035
+ updateFromInput(input, true);
1036
+ }, 1);
1037
+ });
1038
+
1039
+ }));