Subversion-Projekte lars-tiefland.cienc

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
5 lars 1
/*!
2
 * jQuery Color Animations v2.0pre
3
 * http://jquery.org/
4
 *
5
 * Copyright 2011 John Resig
6
 * Dual licensed under the MIT or GPL Version 2 licenses.
7
 * http://jquery.org/license
8
 */
9
 
10
(function( jQuery, undefined ){
11
	var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color outlineColor".split(" "),
12
 
13
		// plusequals test for += 100 -= 100
14
		rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
15
		// a set of RE's that can match strings and generate color tuples.
16
		stringParsers = [{
17
				re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
18
				parse: function( execResult ) {
19
					return [
20
						execResult[ 1 ],
21
						execResult[ 2 ],
22
						execResult[ 3 ],
23
						execResult[ 4 ]
24
					];
25
				}
26
			}, {
27
				re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
28
				parse: function( execResult ) {
29
					return [
30
						2.55 * execResult[1],
31
						2.55 * execResult[2],
32
						2.55 * execResult[3],
33
						execResult[ 4 ]
34
					];
35
				}
36
			}, {
37
				re: /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/,
38
				parse: function( execResult ) {
39
					return [
40
						parseInt( execResult[ 1 ], 16 ),
41
						parseInt( execResult[ 2 ], 16 ),
42
						parseInt( execResult[ 3 ], 16 )
43
					];
44
				}
45
			}, {
46
				re: /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/,
47
				parse: function( execResult ) {
48
					return [
49
						parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
50
						parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
51
						parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
52
					];
53
				}
54
			}, {
55
				re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
56
				space: "hsla",
57
				parse: function( execResult ) {
58
					return [
59
						execResult[1],
60
						execResult[2] / 100,
61
						execResult[3] / 100,
62
						execResult[4]
63
					];
64
				}
65
			}],
66
 
67
		// jQuery.Color( )
68
		color = jQuery.Color = function( color, green, blue, alpha ) {
69
			return new jQuery.Color.fn.parse( color, green, blue, alpha );
70
		},
71
		spaces = {
72
			rgba: {
73
				cache: "_rgba",
74
				props: {
75
					red: {
76
						idx: 0,
77
						type: "byte",
78
						empty: true
79
					},
80
					green: {
81
						idx: 1,
82
						type: "byte",
83
						empty: true
84
					},
85
					blue: {
86
						idx: 2,
87
						type: "byte",
88
						empty: true
89
					},
90
					alpha: {
91
						idx: 3,
92
						type: "percent",
93
						def: 1
94
					}
95
				}
96
			},
97
			hsla: {
98
				cache: "_hsla",
99
				props: {
100
					hue: {
101
						idx: 0,
102
						type: "degrees",
103
						empty: true
104
					},
105
					saturation: {
106
						idx: 1,
107
						type: "percent",
108
						empty: true
109
					},
110
					lightness: {
111
						idx: 2,
112
						type: "percent",
113
						empty: true
114
					}
115
				}
116
			}
117
		},
118
		propTypes = {
119
			"byte": {
120
				floor: true,
121
				min: 0,
122
				max: 255
123
			},
124
			"percent": {
125
				min: 0,
126
				max: 1
127
			},
128
			"degrees": {
129
				mod: 360,
130
				floor: true
131
			}
132
		},
133
		rgbaspace = spaces.rgba.props,
134
		support = color.support = {},
135
 
136
		// colors = jQuery.Color.names
137
		colors,
138
 
139
		// local aliases of functions called often
140
		each = jQuery.each;
141
 
142
	spaces.hsla.props.alpha = rgbaspace.alpha;
143
 
144
	function clamp( value, prop, alwaysAllowEmpty ) {
145
		var type = propTypes[ prop.type ] || {},
146
			allowEmpty = prop.empty || alwaysAllowEmpty;
147
 
148
		if ( allowEmpty && value == null ) {
149
			return null;
150
		}
151
		if ( prop.def && value == null ) {
152
			return prop.def;
153
		}
154
		if ( type.floor ) {
155
			value = ~~value;
156
		} else {
157
			value = parseFloat( value );
158
		}
159
		if ( value == null || isNaN( value ) ) {
160
			return prop.def;
161
		}
162
		if ( type.mod ) {
163
			value = value % type.mod;
164
			// -10 -> 350
165
			return value < 0 ? type.mod + value : value;
166
		}
167
 
168
		// for now all property types without mod have min and max
169
		return type.min > value ? type.min : type.max < value ? type.max : value;
170
	}
171
 
172
	function stringParse( string ) {
173
		var inst = color(),
174
			rgba = inst._rgba = [];
175
 
176
		string = string.toLowerCase();
177
 
178
		each( stringParsers, function( i, parser ) {
179
			var match = parser.re.exec( string ),
180
				values = match && parser.parse( match ),
181
				parsed,
182
				spaceName = parser.space || "rgba",
183
				cache = spaces[ spaceName ].cache;
184
 
185
 
186
			if ( values ) {
187
				parsed = inst[ spaceName ]( values );
188
 
189
				// if this was an rgba parse the assignment might happen twice
190
				// oh well....
191
				inst[ cache ] = parsed[ cache ];
192
				rgba = inst._rgba = parsed._rgba;
193
 
194
				// exit each( stringParsers ) here because we matched
195
				return false;
196
			}
197
		});
198
 
199
		// Found a stringParser that handled it
200
		if ( rgba.length !== 0 ) {
201
 
202
			// if this came from a parsed string, force "transparent" when alpha is 0
203
			// chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
204
			if ( Math.max.apply( Math, rgba ) === 0 ) {
205
				jQuery.extend( rgba, colors.transparent );
206
			}
207
			return inst;
208
		}
209
 
210
		// named colors / default - filter back through parse function
211
		if ( string = colors[ string ] ) {
212
			return string;
213
		}
214
	}
215
 
216
	color.fn = color.prototype = {
217
		constructor: color,
218
		parse: function( red, green, blue, alpha ) {
219
			if ( red === undefined ) {
220
				this._rgba = [ null, null, null, null ];
221
				return this;
222
			}
223
			if ( red instanceof jQuery || red.nodeType ) {
224
				red = red instanceof jQuery ? red.css( green ) : jQuery( red ).css( green );
225
				green = undefined;
226
			}
227
 
228
			var inst = this,
229
				type = jQuery.type( red ),
230
				rgba = this._rgba = [],
231
				source;
232
 
233
			// more than 1 argument specified - assume ( red, green, blue, alpha )
234
			if ( green !== undefined ) {
235
				red = [ red, green, blue, alpha ];
236
				type = "array";
237
			}
238
 
239
			if ( type === "string" ) {
240
				return this.parse( stringParse( red ) || colors._default );
241
			}
242
 
243
			if ( type === "array" ) {
244
				each( rgbaspace, function( key, prop ) {
245
					rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
246
				});
247
				return this;
248
			}
249
 
250
			if ( type === "object" ) {
251
				if ( red instanceof color ) {
252
					each( spaces, function( spaceName, space ) {
253
						if ( red[ space.cache ] ) {
254
							inst[ space.cache ] = red[ space.cache ].slice();
255
						}
256
					});
257
				} else {
258
					each( spaces, function( spaceName, space ) {
259
						each( space.props, function( key, prop ) {
260
							var cache = space.cache;
261
 
262
							// if the cache doesn't exist, and we know how to convert
263
							if ( !inst[ cache ] && space.to ) {
264
 
265
								// if the value was null, we don't need to copy it
266
								// if the key was alpha, we don't need to copy it either
267
								if ( red[ key ] == null || key === "alpha") {
268
									return;
269
								}
270
								inst[ cache ] = space.to( inst._rgba );
271
							}
272
 
273
							// this is the only case where we allow nulls for ALL properties.
274
							// call clamp with alwaysAllowEmpty
275
							inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
276
						});
277
					});
278
				}
279
				return this;
280
			}
281
		},
282
		is: function( compare ) {
283
			var is = color( compare ),
284
				same = true,
285
				myself = this;
286
 
287
			each( spaces, function( _, space ) {
288
				var isCache = is[ space.cache ],
289
					localCache;
290
				if (isCache) {
291
					localCache = myself[ space.cache ] || space.to && space.to( myself._rgba ) || [];
292
					each( space.props, function( _, prop ) {
293
						if ( isCache[ prop.idx ] != null ) {
294
							same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
295
							return same;
296
						}
297
					});
298
				}
299
				return same;
300
			});
301
			return same;
302
		},
303
		_space: function() {
304
			var used = [],
305
				inst = this;
306
			each( spaces, function( spaceName, space ) {
307
				if ( inst[ space.cache ] ) {
308
					used.push( spaceName );
309
				}
310
			});
311
			return used.pop();
312
		},
313
		transition: function( other, distance ) {
314
			var end = color( other ),
315
				spaceName = end._space(),
316
				space = spaces[ spaceName ],
317
				start = this[ space.cache ] || space.to( this._rgba ),
318
				result = start.slice();
319
 
320
			end = end[ space.cache ];
321
			each( space.props, function( key, prop ) {
322
				var index = prop.idx,
323
					startValue = start[ index ],
324
					endValue = end[ index ],
325
					type = propTypes[ prop.type ] || {};
326
 
327
				// if null, don't override start value
328
				if ( endValue === null ) {
329
					return;
330
				}
331
				// if null - use end
332
				if ( startValue === null ) {
333
					result[ index ] = endValue;
334
				} else {
335
					if ( type.mod ) {
336
						if ( endValue - startValue > type.mod / 2 ) {
337
							startValue += type.mod;
338
						} else if ( startValue - endValue > type.mod / 2 ) {
339
							startValue -= type.mod;
340
						}
341
					}
342
					result[ prop.idx ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
343
				}
344
			});
345
			return this[ spaceName ]( result );
346
		},
347
		blend: function( opaque ) {
348
			// if we are already opaque - return ourself
349
			if ( this._rgba[ 3 ] === 1 ) {
350
				return this;
351
			}
352
 
353
			var rgb = this._rgba.slice(),
354
				a = rgb.pop(),
355
				blend = color( opaque )._rgba;
356
 
357
			return color( jQuery.map( rgb, function( v, i ) {
358
				return ( 1 - a ) * blend[ i ] + a * v;
359
			}));
360
		},
361
		toRgbaString: function() {
362
			var prefix = "rgba(",
363
				rgba = jQuery.map( this._rgba, function( v, i ) {
364
					return v == null ? ( i > 2 ? 1 : 0 ) : v;
365
				});
366
 
367
			if ( rgba[ 3 ] === 1 ) {
368
				rgba.pop();
369
				prefix = "rgb(";
370
			}
371
 
372
			return prefix + rgba.join(",") + ")";
373
		},
374
		toHslaString: function() {
375
			var prefix = "hsla(",
376
				hsla = jQuery.map( this.hsla(), function( v, i ) {
377
					if ( v == null ) {
378
						v = i > 2 ? 1 : 0;
379
					}
380
 
381
					// catch 1 and 2
382
					if ( i && i < 3 ) {
383
						v = Math.round( v * 100 ) + "%";
384
					}
385
					return v;
386
				});
387
 
388
			if ( hsla[ 3 ] === 1 ) {
389
				hsla.pop();
390
				prefix = "hsl(";
391
			}
392
			return prefix + hsla.join(",") + ")";
393
		},
394
		toHexString: function( includeAlpha ) {
395
			var rgba = this._rgba.slice(),
396
				alpha = rgba.pop();
397
 
398
			if ( includeAlpha ) {
399
				rgba.push( ~~( alpha * 255 ) );
400
			}
401
 
402
			return "#" + jQuery.map( rgba, function( v, i ) {
403
 
404
				// default to 0 when nulls exist
405
				v = ( v || 0 ).toString( 16 );
406
				return v.length === 1 ? "0" + v : v;
407
			}).join("");
408
		},
409
		toString: function() {
410
			return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
411
		}
412
	};
413
	color.fn.parse.prototype = color.fn;
414
 
415
	// hsla conversions adapted from:
416
	// http://www.google.com/codesearch/p#OAMlx_jo-ck/src/third_party/WebKit/Source/WebCore/inspector/front-end/Color.js&d=7&l=193
417
 
418
	function hue2rgb( p, q, h ) {
419
		h = ( h + 1 ) % 1;
420
		if ( h * 6 < 1 ) {
421
			return p + (q - p) * 6 * h;
422
		}
423
		if ( h * 2 < 1) {
424
			return q;
425
		}
426
		if ( h * 3 < 2 ) {
427
			return p + (q - p) * ((2/3) - h) * 6;
428
		}
429
		return p;
430
	}
431
 
432
	spaces.hsla.to = function ( rgba ) {
433
		if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
434
			return [ null, null, null, rgba[ 3 ] ];
435
		}
436
		var r = rgba[ 0 ] / 255,
437
			g = rgba[ 1 ] / 255,
438
			b = rgba[ 2 ] / 255,
439
			a = rgba[ 3 ],
440
			max = Math.max( r, g, b ),
441
			min = Math.min( r, g, b ),
442
			diff = max - min,
443
			add = max + min,
444
			l = add * 0.5,
445
			h, s;
446
 
447
		if ( min === max ) {
448
			h = 0;
449
		} else if ( r === max ) {
450
			h = ( 60 * ( g - b ) / diff ) + 360;
451
		} else if ( g === max ) {
452
			h = ( 60 * ( b - r ) / diff ) + 120;
453
		} else {
454
			h = ( 60 * ( r - g ) / diff ) + 240;
455
		}
456
 
457
		if ( l === 0 || l === 1 ) {
458
			s = l;
459
		} else if ( l <= 0.5 ) {
460
			s = diff / add;
461
		} else {
462
			s = diff / ( 2 - add );
463
		}
464
		return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
465
	};
466
 
467
	spaces.hsla.from = function ( hsla ) {
468
		if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
469
			return [ null, null, null, hsla[ 3 ] ];
470
		}
471
		var h = hsla[ 0 ] / 360,
472
			s = hsla[ 1 ],
473
			l = hsla[ 2 ],
474
			a = hsla[ 3 ],
475
			q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
476
			p = 2 * l - q,
477
			r, g, b;
478
 
479
		return [
480
			Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
481
			Math.round( hue2rgb( p, q, h ) * 255 ),
482
			Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
483
			a
484
		];
485
	};
486
 
487
 
488
	each( spaces, function( spaceName, space ) {
489
		var props = space.props,
490
			cache = space.cache,
491
			to = space.to,
492
			from = space.from;
493
 
494
		// makes rgba() and hsla()
495
		color.fn[ spaceName ] = function( value ) {
496
 
497
			// generate a cache for this space if it doesn't exist
498
			if ( to && !this[ cache ] ) {
499
				this[ cache ] = to( this._rgba );
500
			}
501
			if ( value === undefined ) {
502
				return this[ cache ].slice();
503
			}
504
 
505
			var type = jQuery.type( value ),
506
				arr = ( type === "array" || type === "object" ) ? value : arguments,
507
				local = this[ cache ].slice(),
508
				ret;
509
 
510
			each( props, function( key, prop ) {
511
				var val = arr[ type === "object" ? key : prop.idx ];
512
				if ( val == null ) {
513
					val = local[ prop.idx ];
514
				}
515
				local[ prop.idx ] = clamp( val, prop );
516
			});
517
 
518
			if ( from ) {
519
				ret = color( from( local ) );
520
				ret[ cache ] = local;
521
				return ret;
522
			} else {
523
				return color( local );
524
			}
525
		};
526
 
527
		// makes red() green() blue() alpha() hue() saturation() lightness()
528
		each( props, function( key, prop ) {
529
			// alpha is included in more than one space
530
			if ( color.fn[ key ] ) {
531
				return;
532
			}
533
			color.fn[ key ] = function( value ) {
534
				var vtype = jQuery.type( value ),
535
					fn = ( key === 'alpha' ? ( this._hsla ? 'hsla' : 'rgba' ) : spaceName ),
536
					local = this[ fn ](),
537
					cur = local[ prop.idx ],
538
					match;
539
 
540
				if ( vtype === "undefined" ) {
541
					return cur;
542
				}
543
 
544
				if ( vtype === "function" ) {
545
					value = value.call( this, cur );
546
					vtype = jQuery.type( value );
547
				}
548
				if ( value == null && prop.empty ) {
549
					return this;
550
				}
551
				if ( vtype === "string" ) {
552
					match = rplusequals.exec( value );
553
					if ( match ) {
554
						value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
555
					}
556
				}
557
				local[ prop.idx ] = value;
558
				return this[ fn ]( local );
559
			};
560
		});
561
	});
562
 
563
	// add .fx.step functions
564
	each( stepHooks, function( i, hook ) {
565
		jQuery.cssHooks[ hook ] = {
566
			set: function( elem, value ) {
567
				var parsed, backgroundColor, curElem;
568
 
569
				if ( jQuery.type( value ) !== 'string' || ( parsed = stringParse( value ) ) )
570
				{
571
					value = color( parsed || value );
572
					if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
573
						curElem = hook === "backgroundColor" ? elem.parentNode : elem;
574
						do {
575
							backgroundColor = jQuery.curCSS( curElem, "backgroundColor" );
576
						} while (
577
							( backgroundColor === "" || backgroundColor === "transparent" ) &&
578
							( curElem = curElem.parentNode ) &&
579
							curElem.style
580
						);
581
 
582
						value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
583
							backgroundColor :
584
							"_default" );
585
					}
586
 
587
					value = value.toRgbaString();
588
				}
589
				elem.style[ hook ] = value;
590
			}
591
		};
592
		jQuery.fx.step[ hook ] = function( fx ) {
593
			if ( !fx.colorInit ) {
594
				fx.start = color( fx.elem, hook );
595
				fx.end = color( fx.end );
596
				fx.colorInit = true;
597
			}
598
			jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
599
		};
600
	});
601
 
602
	// detect rgba support
603
	jQuery(function() {
604
		var div = document.createElement( "div" ),
605
			div_style = div.style;
606
 
607
		div_style.cssText = "background-color:rgba(1,1,1,.5)";
608
		support.rgba = div_style.backgroundColor.indexOf( "rgba" ) > -1;
609
	});
610
 
611
	// Some named colors to work with
612
	// From Interface by Stefan Petre
613
	// http://interface.eyecon.ro/
614
	colors = jQuery.Color.names = {
615
		aqua: "#00ffff",
616
		azure: "#f0ffff",
617
		beige: "#f5f5dc",
618
		black: "#000000",
619
		blue: "#0000ff",
620
		brown: "#a52a2a",
621
		cyan: "#00ffff",
622
		darkblue: "#00008b",
623
		darkcyan: "#008b8b",
624
		darkgrey: "#a9a9a9",
625
		darkgreen: "#006400",
626
		darkkhaki: "#bdb76b",
627
		darkmagenta: "#8b008b",
628
		darkolivegreen: "#556b2f",
629
		darkorange: "#ff8c00",
630
		darkorchid: "#9932cc",
631
		darkred: "#8b0000",
632
		darksalmon: "#e9967a",
633
		darkviolet: "#9400d3",
634
		fuchsia: "#ff00ff",
635
		gold: "#ffd700",
636
		green: "#008000",
637
		indigo: "#4b0082",
638
		khaki: "#f0e68c",
639
		lightblue: "#add8e6",
640
		lightcyan: "#e0ffff",
641
		lightgreen: "#90ee90",
642
		lightgrey: "#d3d3d3",
643
		lightpink: "#ffb6c1",
644
		lightyellow: "#ffffe0",
645
		lime: "#00ff00",
646
		magenta: "#ff00ff",
647
		maroon: "#800000",
648
		navy: "#000080",
649
		olive: "#808000",
650
		orange: "#ffa500",
651
		pink: "#ffc0cb",
652
		purple: "#800080",
653
		violet: "#800080",
654
		red: "#ff0000",
655
		silver: "#c0c0c0",
656
		white: "#ffffff",
657
		yellow: "#ffff00",
658
		transparent: [ null, null, null, 0 ],
659
		_default: "#ffffff"
660
	};
661
})( jQuery );