PageSourceSearch

https://sandbox.csu.edu.tw/GraduateSurvey/assets/plugins/bootstrap-colorpicker/js/bootstrap-colorpicker.js

js csu.edu.tw collected 2026-10-02 04:45:15 UTC 13,966 bytes, 540 lines download raw bytes

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('.input-group-btn') : false; // modified by keenthemes for Bootstrap 3.0 support
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				this.element.prop('value', this.format.call(this));
232			}
233			this.element.trigger({
234				type: 'hide',
235				color: this.color
236			});
237		},
238		
239		place: function(){
240			var offset = this.component ? this.component.offset() : this.element.offset();
241			this.picker.css({
242				top: offset.top + this.height,
243				left: offset.left
244			});
245		},
246		
247		//preview color change
248		previewColor: function(){
249			try {
250				this.preview.backgroundColor = this.format.call(this);
251			} catch(e) {
252				this.preview.backgroundColor = this.color.toHex();
253			}
254			//set the color for brightness/saturation slider
255			this.base.backgroundColor = this.color.toHex(this.color.value.h, 1, 1, 1);
256			//set te color for alpha slider
257			if (this.alpha) {
258				this.alpha.backgroundColor = this.color.toHex();
259			}
260		},
261		
262		pointer: null,
263		
264		slider: null,
265		
266		mousedown: function(e){
267			e.stopPropagation();
268			e.preventDefault();
269			
270			var target = $(e.target);
271			
272			//detect the slider and set the limits and callbacks
273			var zone = target.closest('div');
274			if (!zone.is('.colorpicker')) {
275				if (zone.is('.colorpicker-saturation')) {
276					this.slider = $.extend({}, CPGlobal.sliders.saturation);
277				} 
278				else if (zone.is('.colorpicker-hue')) {
279					this.slider = $.extend({}, CPGlobal.sliders.hue);
280				}
281				else if (zone.is('.colorpicker-alpha')) {
282					this.slider = $.extend({}, CPGlobal.sliders.alpha);
283				} else {
284					return false;
285				}
286				var offset = zone.offset();
287				//reference to knob's style
288				this.slider.knob = zone.find('i')[0].style;
289				this.slider.left = e.pageX - offset.left;
290				this.slider.top = e.pageY - offset.top;
291				this.pointer = {
292					left: e.pageX,
293					top: e.pageY
294				};
295				//trigger mousemove to move the knob to the current position
296				$(document).on({
297					mousemove: $.proxy(this.mousemove, this),
298					mouseup: $.proxy(this.mouseup, this)
299				}).trigger('mousemove');
300			}
301			return false;
302		},
303		
304		mousemove: function(e){
305			e.stopPropagation();
306			e.preventDefault();
307			var left = Math.max(
308				0,
309				Math.min(
310					this.slider.maxLeft,
311					this.slider.left + ((e.pageX||this.pointer.left) - this.pointer.left)
312				)
313			);
314			var top = Math.max(
315				0,
316				Math.min(
317					this.slider.maxTop,
318					this.slider.top + ((e.pageY||this.pointer.top) - this.pointer.top)
319				)
320			);
321			this.slider.knob.left = left + 'px';
322			this.slider.knob.top = top + 'px';
323			if (this.slider.callLeft) {
324				this.color[this.slider.callLeft].call(this.color, left/100);
325			}
326			if (this.slider.callTop) {
327				this.color[this.slider.callTop].call(this.color, top/100);
328			}
329			this.previewColor();
330			this.element.trigger({
331				type: 'changeColor',
332				color: this.color
333			});
334			return false;
335		},
336		
337		mouseup: function(e){
338			e.stopPropagation();
339			e.preventDefault();
340			$(document).off({
341				mousemove: this.mousemove,
342				mouseup: this.mouseup
343			});
344			return false;
345		}
346	}
347
348	$.fn.colorpicker = function ( option, val ) {
349		return this.each(function () {
350			var $this = $(this),
351				data = $this.data('colorpicker'),
352				options = typeof option === 'object' && option;
353			if (!data) {
354				$this.data('colorpicker', (data = new Colorpicker(this, $.extend({}, $.fn.colorpicker.defaults,options))));
355			}
356			if (typeof option === 'string') data[option](val);
357		});
358	};
359
360	$.fn.colorpicker.defaults = {
361	};
362	
363	$.fn.colorpicker.Constructor = Colorpicker;
364	
365	var CPGlobal = {
366	
367		// translate a format from Color object to a string
368		translateFormats: {
369			'rgb': function(){
370				var rgb = this.color.toRGB();
371				return 'rgb('+rgb.r+','+rgb.g+','+rgb.b+')';
372			},
373			
374			'rgba': function(){
375				var rgb = this.color.toRGB();
376				return 'rgba('+rgb.r+','+rgb.g+','+rgb.b+','+rgb.a+')';
377			},
378			
379			'hsl': function(){
380				var hsl = this.color.toHSL();
381				return 'hsl('+Math.round(hsl.h*360)+','+Math.round(hsl.s*100)+'%,'+Math.round(hsl.l*100)+'%)';
382			},
383			
384			'hsla': function(){
385				var hsl = this.color.toHSL();
386				return 'hsla('+Math.round(hsl.h*360)+','+Math.round(hsl.s*100)+'%,'+Math.round(hsl.l*100)+'%,'+hsl.a+')';
387			},
388			
389			'hex': function(){
390				return  this.color.toHex();
391			}
392		},
393		
394		sliders: {
395			saturation: {
396				maxLeft: 100,
397				maxTop: 100,
398				callLeft: 'setSaturation',
399				callTop: 'setLightness'
400			},
401			
402			hue: {
403				maxLeft: 0,
404				maxTop: 100,
405				callLeft: false,
406				callTop: 'setHue'
407			},
408			
409			alpha: {
410				maxLeft: 0,
411				maxTop: 100,
412				callLeft: false,
413				callTop: 'setAlpha'
414			}
415		},
416		
417		// HSBtoRGB from RaphaelJS
418		// https://github.com/DmitryBaranovskiy/raphael/
419		RGBtoHSB: function (r, g, b, a){
420			r /= 255;
421			g /= 255;
422			b /= 255;
423
424			var H, S, V, C;
425			V = Math.max(r, g, b);
426			C = V - Math.min(r, g, b);
427			H = (C === 0 ? null :
428				V == r ? (g - b) / C :
429				V == g ? (b - r) / C + 2 :
430					(r - g) / C + 4
431				);
432			H = ((H + 360) % 6) * 60 / 360;
433			S = C === 0 ? 0 : C / V;
434			return {h: H||1, s: S, b: V, a: a||1};
435		},
436		
437		HueToRGB: function (p, q, h) {
438			if (h < 0)
439				h += 1;
440			else if (h > 1)
441				h -= 1;
442
443			if ((h * 6) < 1)
444				return p + (q - p) * h * 6;
445			else if ((h * 2) < 1)
446				return q;
447			else if ((h * 3) < 2)
448				return p + (q - p) * ((2 / 3) - h) * 6;
449			else
450				return p;
451		},
452	
453		HSLtoRGB: function (h, s, l, a)
454		{
455			if (s < 0) {
456				s = 0;
457			}
458			var q;
459			if (l <= 0.5) {
460				q = l * (1 + s);
461			} else {
462				q = l + s - (l * s);
463			}
464			
465			var p = 2 * l - q;
466
467			var tr = h + (1 / 3);
468			var tg = h;
469			var tb = h - (1 / 3);
470
471			var r = Math.round(CPGlobal.HueToRGB(p, q, tr) * 255);
472			var g = Math.round(CPGlobal.HueToRGB(p, q, tg) * 255);
473			var b = Math.round(CPGlobal.HueToRGB(p, q, tb) * 255);
474			return [r, g, b, a||1];
475		},
476		
477		// a set of RE's that can match strings and generate color tuples.
478		// from John Resig color plugin
479		// https://github.com/jquery/jquery-color/
480		stringParsers: [
481			{
482				re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
483				parse: function( execResult ) {
484					return [
485						execResult[ 1 ],
486						execResult[ 2 ],
487						execResult[ 3 ],
488						execResult[ 4 ]
489					];
490				}
491			}, {
492				re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
493				parse: function( execResult ) {
494					return [
495						2.55 * execResult[1],
496						2.55 * execResult[2],
497						2.55 * execResult[3],
498						execResult[ 4 ]
499					];
500				}
501			}, {
502				re: /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/,
503				parse: function( execResult ) {
504					return [
505						parseInt( execResult[ 1 ], 16 ),
506						parseInt( execResult[ 2 ], 16 ),
507						parseInt( execResult[ 3 ], 16 )
508					];
509				}
510			}, {
511				re: /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/,
512				parse: function( execResult ) {
513					return [
514						parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
515						parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
516						parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
517					];
518				}
519			}, {
520				re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
521				space: 'hsla',
522				parse: function( execResult ) {
523					return [
524						execResult[1]/360,
525						execResult[2] / 100,
526						execResult[3] / 100,
527						execResult[4]
528					];
529				}
530			}
531		],
532		template: '<div class="colorpicker dropdown-menu">'+
533							'<div class="colorpicker-saturation"><i><b></b></i></div>'+
534							'<div class="colorpicker-hue"><i></i></div>'+
535							'<div class="colorpicker-alpha"><i></i></div>'+
536							'<div class="colorpicker-color"><div /></div>'+
537						'</div>'
538	};
539
540}( window.jQuery )

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.