PageSourceSearch

https://www.stonebalancing.com/js/jquery/jquery.miniColors/jquery.miniColors.js

js stonebalancing.com collected 2026-10-04 00:30:52 UTC 16,431 bytes, 647 lines download raw bytes

1/*
2 * jQuery miniColors: A small color selector
3 *
4 * Copyright 2011 Cory LaViska for A Beautiful Site, LLC. (http://abeautifulsite.net/)
5 *
6 * Dual licensed under the MIT or GPL Version 2 licenses
7 *
8 *
9 * Usage:
10 *
11 *	1. Link to jQuery: <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>
12 *
13 *  2. Link to miniColors: <script type="text/javascript" src="jquery.miniColors.js"></script>
14 *
15 *  3. Include miniColors stylesheet: <link type="text/css" rel="stylesheet" href="jquery.miniColors.css" />
16 *
17 *	4. Apply $([selector]).miniColors() to one or more INPUT elements
18 *
19 *
20 * Options:
21 *
22 *	disabled		[true|false]
23 *	readonly		[true|false]
24 *
25 *
26 *  Specify options on creation:
27 *
28 *		$([selector]).miniColors({
29 *
30 *			optionName: value,
31 *			optionName: value,
32 *			...
33 *
34 *		});
35 *
36 *
37 * Methods:
38 *
39 *	Call a method using: $([selector]).miniColors('methodName', [value]);
40 *
41 *	disabled		[true|false]
42 *	readonly		[true|false]
43 *	value			[hex value]
44 *	destroy
45 *
46 *
47 * Events:
48 *
49 *	Attach events on creation:
50 *
51 *		$([selector]).miniColors({
52 *
53 *			change: function(hex, rgb) { ... }
54 *
55 *		});
56 *
57 *	change(hex, rgb)	called when the color value changes; 'this' will refer to the original input element;
58 *                      hex is the string hex value of the selected color; rgb is an object with the RGB values
59 *
60 *
61 * Change log:
62 *
63 *	- v0.1 (2011-02-24) - Initial release
64 *
65 *
66 * Attribution:
67 *
68 *	- The color picker icon is based on an icon from the amazing Fugue icon set: 
69 *    http://p.yusukekamiyamane.com/
70 *
71 *	- The gradient image, the hue image, and the math functions are courtesy of 
72 *    the eyecon.co jQuery color picker: http://www.eyecon.ro/colorpicker/
73 *
74 *
75*/
76if(jQuery) (function($) {
77	
78	$.extend($.fn, {
79		
80		miniColors: function(o, data) {
81			
82			
83			var create = function(input, o, data) {
84				
85				//
86				// Creates a new instance of the miniColors selector
87				//
88				
89				// Determine initial color (defaults to white)
90				var color = cleanHex(input.val());
91				if( !color ) color = 'FFFFFF';
92				var hsb = hex2hsb(color);
93				
94				// Create trigger
95				var trigger = $('<a class="miniColors-trigger" style="background-color: #' + color + '" href="#"></a>');
96				trigger.insertAfter(input);
97				
98				// Add necessary attributes
99				input.addClass('miniColors').attr('maxlength', 7).attr('autocomplete', 'off');
100				
101				// Set input data
102				input.data('trigger', trigger);
103				input.data('hsb', hsb);
104				if( o.change ) input.data('change', o.change);
105				
106				// Handle options
107				if( o.readonly ) input.attr('readonly', true);
108				if( o.disabled ) disable(input);
109				
110				// Show selector when trigger is clicked
111				trigger.bind('click.miniColors', function(event) {
112					event.preventDefault();
113					input.trigger('focus');
114				});
115				
116				// Show selector when input receives focus
117				input.bind('focus.miniColors', function(event) {
118					show(input);
119				});
120				
121				// Hide on blur
122				input.bind('blur.miniColors', function(event) {
123					var hex = cleanHex(input.val());
124					input.val( hex ? '#' + hex : '' );
125				});
126				
127				// Hide when tabbing out of the input
128				input.bind('keydown.miniColors', function(event) {
129					if( event.keyCode === 9 ) hide(input);
130				});
131				
132				// Update when color is typed in
133				input.bind('keyup.miniColors', function(event) {
134					// Remove non-hex characters
135					var filteredHex = input.val().replace(/[^A-F0-9#]/ig, '');
136					input.val(filteredHex);
137					if( !setColorFromInput(input) ) {
138						// Reset trigger color when color is invalid
139						input.data('trigger').css('backgroundColor', '#FFF');
140					}
141				});
142				
143				// Handle pasting
144				input.bind('paste.miniColors', function(event) {
145					// Short pause to wait for paste to complete
146					setTimeout( function() {
147						input.trigger('keyup');
148					}, 5);
149				});
150				
151			};
152			
153			
154			var destroy = function(input) {
155				
156				//
157				// Destroys an active instance of the miniColors selector
158				//
159				
160				hide();
161				
162				input = $(input);
163				input.data('trigger').remove();
164				input.removeAttr('autocomplete');
165				input.removeData('trigger');
166				input.removeData('selector');
167				input.removeData('hsb');
168				input.removeData('huePicker');
169				input.removeData('colorPicker');
170				input.removeData('mousebutton');
171				input.removeData('moving');
172				input.unbind('click.miniColors');
173				input.unbind('focus.miniColors');
174				input.unbind('blur.miniColors');
175				input.unbind('keyup.miniColors');
176				input.unbind('keydown.miniColors');
177				input.unbind('paste.miniColors');
178				$(document).unbind('mousedown.miniColors');
179				$(document).unbind('mousemove.miniColors');
180				
181			};
182			
183			
184			var enable = function(input) {
185				
186				//
187				// Disables the input control and the selector
188				//
189				
190				input.attr('disabled', false);
191				input.data('trigger').css('opacity', 1);
192				
193			};
194			
195			
196			var disable = function(input) {
197				
198				//
199				// Disables the input control and the selector
200				//
201				
202				hide(input);
203				input.attr('disabled', true);
204				input.data('trigger').css('opacity', .5);
205				
206			};
207			
208			
209			var show = function(input) {
210				
211				//
212				// Shows the miniColors selector
213				//
214				
215				if( input.attr('disabled') ) return false;
216				
217				// Hide all other instances 
218				hide();				
219				
220				// Generate the selector
221				var selector = $('<div class="miniColors-selector"></div>');
222				selector.append('<div class="miniColors-colors" style="background-color: #FFF;"><div class="miniColors-colorPicker"></div></div>');
223				selector.append('<div class="miniColors-hues"><div class="miniColors-huePicker"></div></div>');
224				selector.css({
225					top: input.is(':visible') ? input.offset().top + input.outerHeight() : input.data('trigger').offset().top + input.data('trigger').outerHeight(),
226					left: input.is(':visible') ? input.offset().left : input.data('trigger').offset().left,
227					display: 'none'
228				}).addClass( input.attr('class') );
229				
230				// Set background for colors
231				var hsb = input.data('hsb');
232				selector.find('.miniColors-colors').css('backgroundColor', '#' + hsb2hex({ h: hsb.h, s: 100, b: 100 }));
233				
234				// Set colorPicker position
235				var colorPosition = input.data('colorPosition');
236				if( !colorPosition ) colorPosition = getColorPositionFromHSB(hsb);
237				selector.find('.miniColors-colorPicker').css('top', colorPosition.y + 'px').css('left', colorPosition.x + 'px');
238				
239				// Set huePicker position
240				var huePosition = input.data('huePosition');
241				if( !huePosition ) huePosition = getHuePositionFromHSB(hsb);
242				selector.find('.miniColors-huePicker').css('top', huePosition.y + 'px');
243				
244				
245				// Set input data
246				input.data('selector', selector);
247				input.data('huePicker', selector.find('.miniColors-huePicker'));
248				input.data('colorPicker', selector.find('.miniColors-colorPicker'));
249				input.data('mousebutton', 0);
250				
251				$('BODY').append(selector);
252				selector.fadeIn(100);
253				
254				// Prevent text selection in IE
255				selector.bind('selectstart', function() { return false; });
256				
257				$(document).bind('mousedown.miniColors', function(event) {
258					input.data('mousebutton', 1);
259					
260					if( $(event.target).parents().andSelf().hasClass('miniColors-colors') ) {
261						event.preventDefault();
262						input.data('moving', 'colors');
263						moveColor(input, event);
264					}
265					
266					if( $(event.target).parents().andSelf().hasClass('miniColors-hues') ) {
267						event.preventDefault();
268						input.data('moving', 'hues');
269						moveHue(input, event);
270					}
271					
272					if( $(event.target).parents().andSelf().hasClass('miniColors-selector') ) {
273						event.preventDefault();
274						return;
275					}
276					
277					if( $(event.target).parents().andSelf().hasClass('miniColors') ) return;
278					
279					hide(input);
280				});
281				
282				$(document).bind('mouseup.miniColors', function(event) {
283					input.data('mousebutton', 0);
284					input.removeData('moving');
285				});
286				
287				$(document).bind('mousemove.miniColors', function(event) {
288					if( input.data('mousebutton') === 1 ) {
289						if( input.data('moving') === 'colors' ) moveColor(input, event);
290						if( input.data('moving') === 'hues' ) moveHue(input, event);
291					}
292				});
293				
294			};
295			
296			
297			var hide = function(input) {
298				
299				//
300				// Hides one or more miniColors selectors
301				//
302				
303				// Hide all other instances if input isn't specified
304				if( !input ) input = '.miniColors';
305				
306				$(input).each( function() {
307					var selector = $(this).data('selector');
308					$(this).removeData('selector');
309					$(selector).fadeOut(100, function() {
310						$(this).remove();
311					});
312				});
313				
314				$(document).unbind('mousedown.miniColors');
315				$(document).unbind('mousemove.miniColors');
316				
317			};
318			
319			
320			var moveColor = function(input, event) {
321				
322				var colorPicker = input.data('colorPicker');
323				
324				colorPicker.hide();
325				
326				var position = {
327					x: event.clientX - input.data('selector').find('.miniColors-colors').offset().left + $(document).scrollLeft() - 5,
328					y: event.clientY - input.data('selector').find('.miniColors-colors').offset().top + $(document).scrollTop() - 5
329				};
330				
331				if( position.x <= -5 ) position.x = -5;
332				if( position.x >= 144 ) position.x = 144;
333				if( position.y <= -5 ) position.y = -5;
334				if( position.y >= 144 ) position.y = 144;
335				input.data('colorPosition', position);
336				colorPicker.css('left', position.x).css('top', position.y).show();
337				
338				// Calculate saturation
339				var s = Math.round((position.x + 5) * .67);
340				if( s < 0 ) s = 0;
341				if( s > 100 ) s = 100;
342				
343				// Calculate brightness
344				var b = 100 - Math.round((position.y + 5) * .67);
345				if( b < 0 ) b = 0;
346				if( b > 100 ) b = 100;
347				
348				// Update HSB values
349				var hsb = input.data('hsb');
350				hsb.s = s;
351				hsb.b = b;
352				
353				// Set color
354				setColor(input, hsb, true);
355				
356			};
357			
358			
359			var moveHue = function(input, event) {
360				
361				var huePicker = input.data('huePicker');
362				
363				huePicker.hide();
364				
365				var position = {
366					y: event.clientY - input.data('selector').find('.miniColors-colors').offset().top + $(document).scrollTop() - 1
367				};
368				
369				if( position.y <= -1 ) position.y = -1;
370				if( position.y >= 149 ) position.y = 149;
371				input.data('huePosition', position);
372				huePicker.css('top', position.y).show();
373				
374				// Calculate hue
375				var h = Math.round((150 - position.y - 1) * 2.4);
376				if( h < 0 ) h = 0;
377				if( h > 360 ) h = 360;
378				
379				// Update HSB values
380				var hsb = input.data('hsb');
381				hsb.h = h;
382				
383				// Set color
384				setColor(input, hsb, true);
385				
386			};
387			
388			
389			var setColor = function(input, hsb, updateInputValue) {
390				
391				input.data('hsb', hsb);
392				var hex = hsb2hex(hsb);	
393				if( updateInputValue ) input.val('#' + hex);
394				input.data('trigger').css('backgroundColor', '#' + hex);
395				if( input.data('selector') ) input.data('selector').find('.miniColors-colors').css('backgroundColor', '#' + hsb2hex({ h: hsb.h, s: 100, b: 100 }));
396				
397				if( input.data('change') ) {
398					input.data('change').call(input, '#' + hex, hsb2rgb(hsb));
399				}
400				
401			};
402			
403			
404			var setColorFromInput = function(input) {
405				
406				// Don't update if the hex color is invalid
407				var hex = cleanHex(input.val());
408				if( !hex ) return false;
409				
410				// Get HSB equivalent
411				var hsb = hex2hsb(hex);
412				
413				// If color is the same, no change required
414				var currentHSB = input.data('hsb');
415				if( hsb.h === currentHSB.h && hsb.s === currentHSB.s && hsb.b === currentHSB.b ) return true;
416				
417				// Set colorPicker position
418				var colorPosition = getColorPositionFromHSB(hsb);
419				var colorPicker = $(input.data('colorPicker'));
420				colorPicker.css('top', colorPosition.y + 'px').css('left', colorPosition.x + 'px');
421				
422				// Set huePosition position
423				var huePosition = getHuePositionFromHSB(hsb);
424				var huePicker = $(input.data('huePicker'));
425				huePicker.css('top', huePosition.y + 'px');
426				
427				setColor(input, hsb, false);
428				
429				return true;
430				
431			};
432			
433			
434			var getColorPositionFromHSB = function(hsb) {
435				
436				var x = Math.ceil(hsb.s / .67);
437				if( x < 0 ) x = 0;
438				if( x > 150 ) x = 150;
439				
440				var y = 150 - Math.ceil(hsb.b / .67);
441				if( y < 0 ) y = 0;
442				if( y > 150 ) y = 150;
443				
444				return { x: x - 5, y: y - 5 };
445				
446			}
447			
448			
449			var getHuePositionFromHSB = function(hsb) {
450				
451				var y = 150 - (hsb.h / 2.4);
452				if( y < 0 ) h = 0;
453				if( y > 150 ) h = 150;				
454				
455				return { y: y - 1 };
456				
457			}
458			
459			
460			var cleanHex = function(hex) {
461				
462				//
463				// Turns a dirty hex string into clean, 6-character hex color
464				//
465				
466				hex = hex.replace(/[^A-Fa-f0-9]/, '');
467				
468				if( hex.length == 3 ) {
469					hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
470				}
471				
472				return hex.length === 6 ? hex : null;
473				
474			};			
475			
476			
477			var hsb2rgb = function(hsb) {
478				var rgb = {};
479				var h = Math.round(hsb.h);
480				var s = Math.round(hsb.s*255/100);
481				var v = Math.round(hsb.b*255/100);
482				if(s == 0) {
483					rgb.r = rgb.g = rgb.b = v;
484				} else {
485					var t1 = v;
486					var t2 = (255 - s) * v / 255;
487					var t3 = (t1 - t2) * (h % 60) / 60;
488					if( h == 360 ) h = 0;
489					if( h < 60 ) { rgb.r = t1; rgb.b = t2; rgb.g = t2 + t3; }
490					else if( h<120 ) {rgb.g = t1; rgb.b = t2; rgb.r = t1 - t3; }
491					else if( h<180 ) {rgb.g = t1; rgb.r = t2; rgb.b = t2 + t3; }
492					else if( h<240 ) {rgb.b = t1; rgb.r = t2; rgb.g = t1 - t3; }
493					else if( h<300 ) {rgb.b = t1; rgb.g = t2; rgb.r = t2 + t3; }
494					else if( h<360 ) {rgb.r = t1; rgb.g = t2; rgb.b = t1 - t3; }
495					else { rgb.r = 0; rgb.g = 0; rgb.b = 0; }
496				}
497				return {
498					r: Math.round(rgb.r),
499					g: Math.round(rgb.g),
500					b: Math.round(rgb.b)
501				};
502			};
503			
504			
505			var rgb2hex = function(rgb) {
506				
507				var hex = [
508					rgb.r.toString(16),
509					rgb.g.toString(16),
510					rgb.b.toString(16)
511				];
512				$.each(hex, function(nr, val) {
513					if (val.length == 1) hex[nr] = '0' + val;
514				});
515				
516				return hex.join('');
517			};
518			
519			
520			var hex2rgb = function(hex) {
521				var hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16);
522				
523				return {
524					r: hex >> 16,
525					g: (hex & 0x00FF00) >> 8,
526					b: (hex & 0x0000FF)
527				};
528			};
529			
530			
531			var rgb2hsb = function(rgb) {
532				var hsb = { h: 0, s: 0, b: 0 };
533				var min = Math.min(rgb.r, rgb.g, rgb.b);
534				var max = Math.max(rgb.r, rgb.g, rgb.b);
535				var delta = max - min;
536				hsb.b = max;
537				hsb.s = max != 0 ? 255 * delta / max : 0;
538				if( hsb.s != 0 ) {
539					if( rgb.r == max ) {
540						hsb.h = (rgb.g - rgb.b) / delta;
541					} else if( rgb.g == max ) {
542						hsb.h = 2 + (rgb.b - rgb.r) / delta;
543					} else {
544						hsb.h = 4 + (rgb.r - rgb.g) / delta;
545					}
546				} else {
547					hsb.h = -1;
548				}
549				hsb.h *= 60;
550				if( hsb.h < 0 ) {
551					hsb.h += 360;
552				}
553				hsb.s *= 100/255;
554				hsb.b *= 100/255;
555				return hsb;
556			};			
557			
558			
559			var hex2hsb = function(hex) {
560				var hsb = rgb2hsb(hex2rgb(hex));
561				// Zero out hue marker for black, white, and grays (saturation === 0)
562				if( hsb.s === 0 ) hsb.h = 360;
563				return hsb;
564			};
565			
566			
567			var hsb2hex = function(hsb) {
568				return rgb2hex(hsb2rgb(hsb));
569			};
570
571			
572			//
573			// Handle calls to $([selector]).miniColors()
574			//
575			switch(o) {
576			
577				case 'readonly':
578					
579					$(this).each( function() {
580						$(this).attr('readonly', data);
581					});
582					
583					return $(this);
584					
585					break;
586				
587				case 'disabled':
588					
589					$(this).each( function() {
590						if( data ) {
591							disable($(this));
592						} else {
593							enable($(this));
594						}
595					});
596										
597					return $(this);
598			
599				case 'value':
600					
601					$(this).each( function() {
602						$(this).val(data).trigger('keyup');
603					});
604					
605					return $(this);
606					
607					break;
608					
609				case 'destroy':
610					
611					$(this).each( function() {
612						destroy($(this));
613					});
614										
615					return $(this);
616				
617				default:
618					
619					if( !o ) o = {};
620					
621					$(this).each( function() {
622						
623						// Must be called on an input element
624						if( $(this)[0].tagName.toLowerCase() !== 'input' ) return;
625						
626						// If a trigger is present, the control was already created
627						if( $(this).data('trigger') ) return;
628						
629						// Create the control
630						create($(this), o, data);
631						
632					});
633										
634					return $(this);
635					
636			}
637			
638			
639		}
640
641			
642	});
643	
644})(jQuery);
645
646
647

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.