Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Avatar for KuCalc : devops.
Download
50654 views
1
/* =========================================================
2
* bootstrap-colorpicker.js
3
* http://www.eyecon.ro/bootstrap-colorpicker
4
* =========================================================
5
* Copyright 2012 Stefan Petre
6
*
7
* Licensed under the Apache License, Version 2.0 (the "License");
8
* you may not use this file except in compliance with the License.
9
* You may obtain a copy of the License at
10
*
11
* http://www.apache.org/licenses/LICENSE-2.0
12
*
13
* Unless required by applicable law or agreed to in writing, software
14
* distributed under the License is distributed on an "AS IS" BASIS,
15
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
* See the License for the specific language governing permissions and
17
* limitations under the License.
18
* ========================================================= */
19
20
!function( $ ) {
21
22
// Color object
23
24
var Color = function(val) {
25
this.value = {
26
h: 1,
27
s: 1,
28
b: 1,
29
a: 1
30
};
31
this.setColor(val);
32
};
33
34
Color.prototype = {
35
constructor: Color,
36
37
//parse a string to HSB
38
setColor: function(val){
39
val = val.toLowerCase();
40
var that = this;
41
$.each( CPGlobal.stringParsers, function( i, parser ) {
42
var match = parser.re.exec( val ),
43
values = match && parser.parse( match ),
44
space = parser.space||'rgba';
45
if ( values ) {
46
if (space === 'hsla') {
47
that.value = CPGlobal.RGBtoHSB.apply(null, CPGlobal.HSLtoRGB.apply(null, values));
48
} else {
49
that.value = CPGlobal.RGBtoHSB.apply(null, values);
50
}
51
return false;
52
}
53
});
54
},
55
56
setHue: function(h) {
57
this.value.h = 1- h;
58
},
59
60
setSaturation: function(s) {
61
this.value.s = s;
62
},
63
64
setLightness: function(b) {
65
this.value.b = 1- b;
66
},
67
68
setAlpha: function(a) {
69
this.value.a = parseInt((1 - a)*100, 10)/100;
70
},
71
72
// HSBtoRGB from RaphaelJS
73
// https://github.com/DmitryBaranovskiy/raphael/
74
toRGB: function(h, s, b, a) {
75
if (!h) {
76
h = this.value.h;
77
s = this.value.s;
78
b = this.value.b;
79
}
80
h *= 360;
81
var R, G, B, X, C;
82
h = (h % 360) / 60;
83
C = b * s;
84
X = C * (1 - Math.abs(h % 2 - 1));
85
R = G = B = b - C;
86
87
h = ~~h;
88
R += [C, X, 0, 0, X, C][h];
89
G += [X, C, C, X, 0, 0][h];
90
B += [0, 0, X, C, C, X][h];
91
return {
92
r: Math.round(R*255),
93
g: Math.round(G*255),
94
b: Math.round(B*255),
95
a: a||this.value.a
96
};
97
},
98
99
toHex: function(h, s, b, a){
100
var rgb = this.toRGB(h, s, b, a);
101
return '#'+((1 << 24) | (parseInt(rgb.r) << 16) | (parseInt(rgb.g) << 8) | parseInt(rgb.b)).toString(16).substr(1);
102
},
103
104
toHSL: function(h, s, b, a){
105
if (!h) {
106
h = this.value.h;
107
s = this.value.s;
108
b = this.value.b;
109
}
110
var H = h,
111
L = (2 - s) * b,
112
S = s * b;
113
if (L > 0 && L <= 1) {
114
S /= L;
115
} else {
116
S /= 2 - L;
117
}
118
L /= 2;
119
if (S > 1) {
120
S = 1;
121
}
122
return {
123
h: H,
124
s: S,
125
l: L,
126
a: a||this.value.a
127
};
128
}
129
};
130
131
// Picker object
132
133
var Colorpicker = function(element, options){
134
this.element = $(element);
135
var format = options.format||this.element.data('color-format')||'hex';
136
this.format = CPGlobal.translateFormats[format];
137
this.isInput = this.element.is('input');
138
this.component = this.element.is('.color') ? this.element.find('.add-on') : false;
139
140
this.picker = $(CPGlobal.template)
141
.appendTo('body')
142
.on('mousedown', $.proxy(this.mousedown, this));
143
144
if (this.isInput) {
145
this.element.on({
146
'focus': $.proxy(this.show, this),
147
'keyup': $.proxy(this.update, this)
148
});
149
} else if (this.component){
150
this.component.on({
151
'click': $.proxy(this.show, this)
152
});
153
} else {
154
this.element.on({
155
'click': $.proxy(this.show, this)
156
});
157
}
158
if (format === 'rgba' || format === 'hsla') {
159
this.picker.addClass('alpha');
160
this.alpha = this.picker.find('.colorpicker-alpha')[0].style;
161
}
162
163
if (this.component){
164
this.picker.find('.colorpicker-color').hide();
165
this.preview = this.element.find('i')[0].style;
166
} else {
167
this.preview = this.picker.find('div:last')[0].style;
168
}
169
170
this.base = this.picker.find('div:first')[0].style;
171
this.update();
172
};
173
174
Colorpicker.prototype = {
175
constructor: Colorpicker,
176
177
show: function(e) {
178
this.picker.show();
179
this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
180
this.place();
181
$(window).on('resize', $.proxy(this.place, this));
182
if (!this.isInput) {
183
if (e) {
184
e.stopPropagation();
185
e.preventDefault();
186
}
187
}
188
$(document).on({
189
'mousedown': $.proxy(this.hide, this)
190
});
191
this.element.trigger({
192
type: 'show',
193
color: this.color
194
});
195
},
196
197
update: function(){
198
this.color = new Color(this.isInput ? this.element.prop('value') : this.element.data('color'));
199
this.picker.find('i')
200
.eq(0).css({left: this.color.value.s*100, top: 100 - this.color.value.b*100}).end()
201
.eq(1).css('top', 100 * (1 - this.color.value.h)).end()
202
.eq(2).css('top', 100 * (1 - this.color.value.a));
203
this.previewColor();
204
},
205
206
setValue: function(newColor) {
207
this.color = new Color(newColor);
208
this.picker.find('i')
209
.eq(0).css({left: this.color.value.s*100, top: 100 - this.color.value.b*100}).end()
210
.eq(1).css('top', 100 * (1 - this.color.value.h)).end()
211
.eq(2).css('top', 100 * (1 - this.color.value.a));
212
this.previewColor();
213
this.element.trigger({
214
type: 'changeColor',
215
color: this.color
216
});
217
},
218
219
hide: function(){
220
this.picker.hide();
221
$(window).off('resize', this.place);
222
if (!this.isInput) {
223
$(document).off({
224
'mousedown': this.hide
225
});
226
if (this.component){
227
this.element.find('input').prop('value', this.format.call(this));
228
}
229
this.element.data('color', this.format.call(this));
230
} else {
231
//if the input value is empty, do not set any color
232
if (this.element.val() != '') {
233
this.element.prop('value', this.format.call(this));
234
}
235
}
236
this.element.trigger({
237
type: 'hide',
238
color: this.color
239
});
240
},
241
242
place: function(){
243
var offset = this.component ? this.component.offset() : this.element.offset();
244
this.picker.css({
245
top: offset.top + this.height,
246
left: offset.left
247
});
248
},
249
250
//preview color change
251
previewColor: function(){
252
try {
253
this.preview.backgroundColor = this.format.call(this);
254
} catch(e) {
255
this.preview.backgroundColor = this.color.toHex();
256
}
257
//set the color for brightness/saturation slider
258
this.base.backgroundColor = this.color.toHex(this.color.value.h, 1, 1, 1);
259
//set te color for alpha slider
260
if (this.alpha) {
261
this.alpha.backgroundColor = this.color.toHex();
262
}
263
},
264
265
pointer: null,
266
267
slider: null,
268
269
mousedown: function(e){
270
e.stopPropagation();
271
e.preventDefault();
272
273
var target = $(e.target);
274
275
//detect the slider and set the limits and callbacks
276
var zone = target.closest('div');
277
if (!zone.is('.colorpicker')) {
278
if (zone.is('.colorpicker-saturation')) {
279
this.slider = $.extend({}, CPGlobal.sliders.saturation);
280
}
281
else if (zone.is('.colorpicker-hue')) {
282
this.slider = $.extend({}, CPGlobal.sliders.hue);
283
}
284
else if (zone.is('.colorpicker-alpha')) {
285
this.slider = $.extend({}, CPGlobal.sliders.alpha);
286
} else {
287
return false;
288
}
289
var offset = zone.offset();
290
//reference to knob's style
291
this.slider.knob = zone.find('i')[0].style;
292
this.slider.left = e.pageX - offset.left;
293
this.slider.top = e.pageY - offset.top;
294
this.pointer = {
295
left: e.pageX,
296
top: e.pageY
297
};
298
//trigger mousemove to move the knob to the current position
299
$(document).on({
300
mousemove: $.proxy(this.mousemove, this),
301
mouseup: $.proxy(this.mouseup, this)
302
}).trigger('mousemove');
303
}
304
return false;
305
},
306
307
mousemove: function(e){
308
e.stopPropagation();
309
e.preventDefault();
310
var left = Math.max(
311
0,
312
Math.min(
313
this.slider.maxLeft,
314
this.slider.left + ((e.pageX||this.pointer.left) - this.pointer.left)
315
)
316
);
317
var top = Math.max(
318
0,
319
Math.min(
320
this.slider.maxTop,
321
this.slider.top + ((e.pageY||this.pointer.top) - this.pointer.top)
322
)
323
);
324
this.slider.knob.left = left + 'px';
325
this.slider.knob.top = top + 'px';
326
if (this.slider.callLeft) {
327
this.color[this.slider.callLeft].call(this.color, left/100);
328
}
329
if (this.slider.callTop) {
330
this.color[this.slider.callTop].call(this.color, top/100);
331
}
332
this.previewColor();
333
334
// Set input value on mousemove
335
try {
336
this.element.val(this.format.call(this));
337
} catch(e) {
338
this.element.val(this.color.toHex());
339
}
340
341
this.element.trigger({
342
type: 'changeColor',
343
color: this.color
344
});
345
return false;
346
},
347
348
mouseup: function(e){
349
e.stopPropagation();
350
e.preventDefault();
351
$(document).off({
352
mousemove: this.mousemove,
353
mouseup: this.mouseup
354
});
355
return false;
356
}
357
}
358
359
$.fn.colorpicker = function ( option, value ) {
360
return this.each(function () {
361
var $this = $(this),
362
data = $this.data('colorpicker'),
363
options = typeof option === 'object' && option;
364
if (!data) {
365
$this.data('colorpicker', (data = new Colorpicker(this, $.extend({}, $.fn.colorpicker.defaults,options))));
366
}
367
if (typeof option === 'string') data[option](value);
368
});
369
};
370
371
$.fn.colorpicker.defaults = {
372
};
373
374
$.fn.colorpicker.Constructor = Colorpicker;
375
376
var CPGlobal = {
377
378
// translate a format from Color object to a string
379
translateFormats: {
380
'rgb': function(){
381
var rgb = this.color.toRGB();
382
return 'rgb('+rgb.r+','+rgb.g+','+rgb.b+')';
383
},
384
385
'rgba': function(){
386
var rgb = this.color.toRGB();
387
return 'rgba('+rgb.r+','+rgb.g+','+rgb.b+','+rgb.a+')';
388
},
389
390
'hsl': function(){
391
var hsl = this.color.toHSL();
392
return 'hsl('+Math.round(hsl.h*360)+','+Math.round(hsl.s*100)+'%,'+Math.round(hsl.l*100)+'%)';
393
},
394
395
'hsla': function(){
396
var hsl = this.color.toHSL();
397
return 'hsla('+Math.round(hsl.h*360)+','+Math.round(hsl.s*100)+'%,'+Math.round(hsl.l*100)+'%,'+hsl.a+')';
398
},
399
400
'hex': function(){
401
return this.color.toHex();
402
}
403
},
404
405
sliders: {
406
saturation: {
407
maxLeft: 100,
408
maxTop: 100,
409
callLeft: 'setSaturation',
410
callTop: 'setLightness'
411
},
412
413
hue: {
414
maxLeft: 0,
415
maxTop: 100,
416
callLeft: false,
417
callTop: 'setHue'
418
},
419
420
alpha: {
421
maxLeft: 0,
422
maxTop: 100,
423
callLeft: false,
424
callTop: 'setAlpha'
425
}
426
},
427
428
// HSBtoRGB from RaphaelJS
429
// https://github.com/DmitryBaranovskiy/raphael/
430
RGBtoHSB: function (r, g, b, a){
431
r /= 255;
432
g /= 255;
433
b /= 255;
434
435
var H, S, V, C;
436
V = Math.max(r, g, b);
437
C = V - Math.min(r, g, b);
438
H = (C === 0 ? null :
439
V == r ? (g - b) / C :
440
V == g ? (b - r) / C + 2 :
441
(r - g) / C + 4
442
);
443
H = ((H + 360) % 6) * 60 / 360;
444
S = C === 0 ? 0 : C / V;
445
return {h: H||1, s: S, b: V, a: a||1};
446
},
447
448
HueToRGB: function (p, q, h) {
449
if (h < 0)
450
h += 1;
451
else if (h > 1)
452
h -= 1;
453
454
if ((h * 6) < 1)
455
return p + (q - p) * h * 6;
456
else if ((h * 2) < 1)
457
return q;
458
else if ((h * 3) < 2)
459
return p + (q - p) * ((2 / 3) - h) * 6;
460
else
461
return p;
462
},
463
464
HSLtoRGB: function (h, s, l, a)
465
{
466
if (s < 0) {
467
s = 0;
468
}
469
var q;
470
if (l <= 0.5) {
471
q = l * (1 + s);
472
} else {
473
q = l + s - (l * s);
474
}
475
476
var p = 2 * l - q;
477
478
var tr = h + (1 / 3);
479
var tg = h;
480
var tb = h - (1 / 3);
481
482
var r = Math.round(CPGlobal.HueToRGB(p, q, tr) * 255);
483
var g = Math.round(CPGlobal.HueToRGB(p, q, tg) * 255);
484
var b = Math.round(CPGlobal.HueToRGB(p, q, tb) * 255);
485
return [r, g, b, a||1];
486
},
487
488
// a set of RE's that can match strings and generate color tuples.
489
// from John Resig color plugin
490
// https://github.com/jquery/jquery-color/
491
stringParsers: [
492
{
493
re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
494
parse: function( execResult ) {
495
return [
496
execResult[ 1 ],
497
execResult[ 2 ],
498
execResult[ 3 ],
499
execResult[ 4 ]
500
];
501
}
502
}, {
503
re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
504
parse: function( execResult ) {
505
return [
506
2.55 * execResult[1],
507
2.55 * execResult[2],
508
2.55 * execResult[3],
509
execResult[ 4 ]
510
];
511
}
512
}, {
513
re: /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/,
514
parse: function( execResult ) {
515
return [
516
parseInt( execResult[ 1 ], 16 ),
517
parseInt( execResult[ 2 ], 16 ),
518
parseInt( execResult[ 3 ], 16 )
519
];
520
}
521
}, {
522
re: /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/,
523
parse: function( execResult ) {
524
return [
525
parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
526
parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
527
parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
528
];
529
}
530
}, {
531
re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
532
space: 'hsla',
533
parse: function( execResult ) {
534
return [
535
execResult[1]/360,
536
execResult[2] / 100,
537
execResult[3] / 100,
538
execResult[4]
539
];
540
}
541
}
542
],
543
template: '<div class="colorpicker dropdown-menu">'+
544
'<div class="colorpicker-saturation"><i><b></b></i></div>'+
545
'<div class="colorpicker-hue"><i></i></div>'+
546
'<div class="colorpicker-alpha"><i></i></div>'+
547
'<div class="colorpicker-color"><div /></div>'+
548
'</div>'
549
};
550
551
}( window.jQuery )
552