708f49017fd08d8f697f47546d2e5da2aa648cd2
5 See <http://mochikit.com/> for documentation, downloads, license, etc.
7 (c) 2005 Bob Ippolito and others. All rights Reserved.
11 if (typeof(dojo
) != 'undefined') {
12 dojo
.provide('MochiKit.Color');
13 dojo
.require('MochiKit.Base');
14 dojo
.require('MochiKit.DOM');
15 dojo
.require('MochiKit.Style');
18 if (typeof(JSAN
) != 'undefined') {
19 JSAN
.use("MochiKit.Base", []);
20 JSAN
.use("MochiKit.DOM", []);
21 JSAN
.use("MochiKit.Style", []);
25 if (typeof(MochiKit
.Base
) == 'undefined') {
29 throw "MochiKit.Color depends on MochiKit.Base";
33 if (typeof(MochiKit
.DOM
) == 'undefined') {
37 throw "MochiKit.Color depends on MochiKit.DOM";
41 if (typeof(MochiKit
.Style
) == 'undefined') {
45 throw "MochiKit.Color depends on MochiKit.Style";
48 if (typeof(MochiKit
.Color
) == "undefined") {
52 MochiKit
.Color
.NAME
= "MochiKit.Color";
53 MochiKit
.Color
.VERSION
= "1.4";
55 MochiKit
.Color
.__repr__
= function () {
56 return "[" + this.NAME
+ " " + this.VERSION
+ "]";
59 MochiKit
.Color
.toString
= function () {
60 return this.__repr__();
64 /** @id MochiKit.Color.Color */
65 MochiKit
.Color
.Color
= function (red
, green
, blue
, alpha
) {
66 if (typeof(alpha
) == 'undefined' || alpha
=== null) {
80 MochiKit
.Color
.Color
.prototype = {
82 __class__
: MochiKit
.Color
.Color
,
84 /** @id MochiKit.Color.Color.prototype.colorWithAlpha */
85 colorWithAlpha
: function (alpha
) {
87 var m
= MochiKit
.Color
;
88 return m
.Color
.fromRGB(rgb
.r
, rgb
.g
, rgb
.b
, alpha
);
91 /** @id MochiKit.Color.Color.prototype.colorWithHue */
92 colorWithHue
: function (hue
) {
93 // get an HSL model, and set the new hue...
94 var hsl
= this.asHSL();
96 var m
= MochiKit
.Color
;
97 // convert back to RGB...
98 return m
.Color
.fromHSL(hsl
);
101 /** @id MochiKit.Color.Color.prototype.colorWithSaturation */
102 colorWithSaturation
: function (saturation
) {
103 // get an HSL model, and set the new hue...
104 var hsl
= this.asHSL();
106 var m
= MochiKit
.Color
;
107 // convert back to RGB...
108 return m
.Color
.fromHSL(hsl
);
111 /** @id MochiKit.Color.Color.prototype.colorWithLightness */
112 colorWithLightness
: function (lightness
) {
113 // get an HSL model, and set the new hue...
114 var hsl
= this.asHSL();
116 var m
= MochiKit
.Color
;
117 // convert back to RGB...
118 return m
.Color
.fromHSL(hsl
);
121 /** @id MochiKit.Color.Color.prototype.darkerColorWithLevel */
122 darkerColorWithLevel
: function (level
) {
123 var hsl
= this.asHSL();
124 hsl
.l
= Math
.max(hsl
.l
- level
, 0);
125 var m
= MochiKit
.Color
;
126 return m
.Color
.fromHSL(hsl
);
129 /** @id MochiKit.Color.Color.prototype.lighterColorWithLevel */
130 lighterColorWithLevel
: function (level
) {
131 var hsl
= this.asHSL();
132 hsl
.l
= Math
.min(hsl
.l
+ level
, 1);
133 var m
= MochiKit
.Color
;
134 return m
.Color
.fromHSL(hsl
);
137 /** @id MochiKit.Color.Color.prototype.blendedColor */
138 blendedColor
: function (other
, /* optional */ fraction
) {
139 if (typeof(fraction
) == 'undefined' || fraction
=== null) {
142 var sf
= 1.0 - fraction
;
146 return MochiKit
.Color
.Color
.fromRGB(
147 (s
.r
* sf
) + (d
.r
* df
),
148 (s
.g
* sf
) + (d
.g
* df
),
149 (s
.b
* sf
) + (d
.b
* df
),
150 (s
.a
* sf
) + (d
.a
* df
)
154 /** @id MochiKit.Color.Color.prototype.compareRGB */
155 compareRGB
: function (other
) {
156 var a
= this.asRGB();
157 var b
= other
.asRGB();
158 return MochiKit
.Base
.compare(
159 [a
.r
, a
.g
, a
.b
, a
.a
],
164 /** @id MochiKit.Color.Color.prototype.isLight */
165 isLight
: function () {
166 return this.asHSL().b
> 0.5;
169 /** @id MochiKit.Color.Color.prototype.isDark */
170 isDark
: function () {
171 return (!this.isLight());
174 /** @id MochiKit.Color.Color.prototype.toHSLString */
175 toHSLString
: function () {
176 var c
= this.asHSL();
177 var ccc
= MochiKit
.Color
.clampColorComponent
;
178 var rval
= this._hslString
;
181 ccc(c
.h
, 360).toFixed(0)
182 + "," + ccc(c
.s
, 100).toPrecision(4) + "%"
183 + "," + ccc(c
.l
, 100).toPrecision(4) + "%"
188 rval
= "hsl(" + mid
+ ")";
193 rval
= "hsla(" + mid
+ "," + a
+ ")";
195 this._hslString
= rval
;
200 /** @id MochiKit.Color.Color.prototype.toRGBString */
201 toRGBString
: function () {
203 var ccc
= MochiKit
.Color
.clampColorComponent
;
204 var rval
= this._rgbString
;
207 ccc(c
.r
, 255).toFixed(0)
208 + "," + ccc(c
.g
, 255).toFixed(0)
209 + "," + ccc(c
.b
, 255).toFixed(0)
212 rval
= "rgba(" + mid
+ "," + c
.a
+ ")";
214 rval
= "rgb(" + mid
+ ")";
216 this._rgbString
= rval
;
221 /** @id MochiKit.Color.Color.prototype.asRGB */
223 return MochiKit
.Base
.clone(this.rgb
);
226 /** @id MochiKit.Color.Color.prototype.toHexString */
227 toHexString
: function () {
228 var m
= MochiKit
.Color
;
230 var ccc
= MochiKit
.Color
.clampColorComponent
;
231 var rval
= this._hexString
;
234 m
.toColorPart(ccc(c
.r
, 255)) +
235 m
.toColorPart(ccc(c
.g
, 255)) +
236 m
.toColorPart(ccc(c
.b
, 255))
238 this._hexString
= rval
;
243 /** @id MochiKit.Color.Color.prototype.asHSV */
247 if (typeof(hsv
) == 'undefined' || hsv
=== null) {
248 hsv
= MochiKit
.Color
.rgbToHSV(this.rgb
);
251 return MochiKit
.Base
.clone(hsv
);
254 /** @id MochiKit.Color.Color.prototype.asHSL */
258 if (typeof(hsl
) == 'undefined' || hsl
=== null) {
259 hsl
= MochiKit
.Color
.rgbToHSL(this.rgb
);
262 return MochiKit
.Base
.clone(hsl
);
265 /** @id MochiKit.Color.Color.prototype.toString */
266 toString
: function () {
267 return this.toRGBString();
270 /** @id MochiKit.Color.Color.prototype.repr */
273 var col
= [c
.r
, c
.g
, c
.b
, c
.a
];
274 return this.__class__
.NAME
+ "(" + col
.join(", ") + ")";
279 // Constructor methods
281 MochiKit
.Base
.update(MochiKit
.Color
.Color
, {
282 /** @id MochiKit.Color.Color.fromRGB */
283 fromRGB
: function (red
, green
, blue
, alpha
) {
284 // designated initializer
285 var Color
= MochiKit
.Color
.Color
;
286 if (arguments
.length
== 1) {
291 if (typeof(rgb
.a
) == 'undefined') {
297 return new Color(red
, green
, blue
, alpha
);
300 /** @id MochiKit.Color.Color.fromHSL */
301 fromHSL
: function (hue
, saturation
, lightness
, alpha
) {
302 var m
= MochiKit
.Color
;
303 return m
.Color
.fromRGB(m
.hslToRGB
.apply(m
, arguments
));
306 /** @id MochiKit.Color.Color.fromHSV */
307 fromHSV
: function (hue
, saturation
, value
, alpha
) {
308 var m
= MochiKit
.Color
;
309 return m
.Color
.fromRGB(m
.hsvToRGB
.apply(m
, arguments
));
312 /** @id MochiKit.Color.Color.fromName */
313 fromName
: function (name
) {
314 var Color
= MochiKit
.Color
.Color
;
315 // Opera 9 seems to "quote" named colors(?!)
316 if (name
.charAt(0) == '"') {
317 name
= name
.substr(1, name
.length
- 2);
319 var htmlColor
= Color
._namedColors
[name
.toLowerCase()];
320 if (typeof(htmlColor
) == 'string') {
321 return Color
.fromHexString(htmlColor
);
322 } else if (name
== "transparent") {
323 return Color
.transparentColor();
328 /** @id MochiKit.Color.Color.fromString */
329 fromString
: function (colorString
) {
330 var self
= MochiKit
.Color
.Color
;
331 var three
= colorString
.substr(0, 3);
332 if (three
== "rgb") {
333 return self
.fromRGBString(colorString
);
334 } else if (three
== "hsl") {
335 return self
.fromHSLString(colorString
);
336 } else if (colorString
.charAt(0) == "#") {
337 return self
.fromHexString(colorString
);
339 return self
.fromName(colorString
);
343 /** @id MochiKit.Color.Color.fromHexString */
344 fromHexString
: function (hexCode
) {
345 if (hexCode
.charAt(0) == '#') {
346 hexCode
= hexCode
.substring(1);
350 if (hexCode
.length
== 3) {
351 for (i
= 0; i
< 3; i
++) {
352 hex
= hexCode
.substr(i
, 1);
353 components
.push(parseInt(hex
+ hex
, 16) / 255.0);
356 for (i
= 0; i
< 6; i
+= 2) {
357 hex
= hexCode
.substr(i
, 2);
358 components
.push(parseInt(hex
, 16) / 255.0);
361 var Color
= MochiKit
.Color
.Color
;
362 return Color
.fromRGB
.apply(Color
, components
);
366 _fromColorString
: function (pre
, method
, scales
, colorCode
) {
367 // parses either HSL or RGB
368 if (colorCode
.indexOf(pre
) === 0) {
369 colorCode
= colorCode
.substring(colorCode
.indexOf("(", 3) + 1, colorCode
.length
- 1);
371 var colorChunks
= colorCode
.split(/\s*,\s*/);
372 var colorFloats
= [];
373 for (var i
= 0; i
< colorChunks
.length
; i
++) {
374 var c
= colorChunks
[i
];
376 var three
= c
.substring(c
.length
- 3);
377 if (c
.charAt(c
.length
- 1) == '%') {
378 val
= 0.01 * parseFloat(c
.substring(0, c
.length
- 1));
379 } else if (three
== "deg") {
380 val
= parseFloat(c
) / 360.0;
381 } else if (three
== "rad") {
382 val
= parseFloat(c
) / (Math
.PI
* 2);
384 val
= scales
[i
] * parseFloat(c
);
386 colorFloats
.push(val
);
388 return this[method
].apply(this, colorFloats
);
391 /** @id MochiKit.Color.Color.fromComputedStyle */
392 fromComputedStyle
: function (elem
, style
) {
393 var d
= MochiKit
.DOM
;
394 var cls
= MochiKit
.Color
.Color
;
395 for (elem
= d
.getElement(elem
); elem
; elem
= elem
.parentNode
) {
396 var actualColor
= MochiKit
.Style
.getStyle
.apply(d
, arguments
);
400 var color
= cls
.fromString(actualColor
);
404 if (color
.asRGB().a
> 0) {
411 /** @id MochiKit.Color.Color.fromBackground */
412 fromBackground
: function (elem
) {
413 var cls
= MochiKit
.Color
.Color
;
414 return cls
.fromComputedStyle(
415 elem
, "backgroundColor", "background-color") || cls
.whiteColor();
418 /** @id MochiKit.Color.Color.fromText */
419 fromText
: function (elem
) {
420 var cls
= MochiKit
.Color
.Color
;
421 return cls
.fromComputedStyle(
422 elem
, "color", "color") || cls
.blackColor();
425 /** @id MochiKit.Color.Color.namedColors */
426 namedColors
: function () {
427 return MochiKit
.Base
.clone(MochiKit
.Color
.Color
._namedColors
);
432 // Module level functions
434 MochiKit
.Base
.update(MochiKit
.Color
, {
435 /** @id MochiKit.Color.clampColorComponent */
436 clampColorComponent
: function (v
, scale
) {
440 } else if (v
> scale
) {
447 _hslValue
: function (n1
, n2
, hue
) {
450 } else if (hue
< 0.0) {
455 val
= n1
+ (n2
- n1
) * hue
;
456 } else if (hue
< 3.0) {
458 } else if (hue
< 4.0) {
459 val
= n1
+ (n2
- n1
) * (4.0 - hue
);
466 /** @id MochiKit.Color.hsvToRGB */
467 hsvToRGB
: function (hue
, saturation
, value
, alpha
) {
468 if (arguments
.length
== 1) {
478 if (saturation
=== 0) {
483 var i
= Math
.floor(hue
* 6);
484 var f
= (hue
* 6) - i
;
485 var p
= value
* (1 - saturation
);
486 var q
= value
* (1 - (saturation
* f
));
487 var t
= value
* (1 - (saturation
* (1 - f
)));
489 case 1: red
= q
; green
= value
; blue
= p
; break;
490 case 2: red
= p
; green
= value
; blue
= t
; break;
491 case 3: red
= p
; green
= q
; blue
= value
; break;
492 case 4: red
= t
; green
= p
; blue
= value
; break;
493 case 5: red
= value
; green
= p
; blue
= q
; break;
494 case 6: // fall through
495 case 0: red
= value
; green
= t
; blue
= p
; break;
506 /** @id MochiKit.Color.hslToRGB */
507 hslToRGB
: function (hue
, saturation
, lightness
, alpha
) {
508 if (arguments
.length
== 1) {
518 if (saturation
=== 0) {
524 if (lightness
<= 0.5) {
525 m2
= lightness
* (1.0 + saturation
);
527 m2
= lightness
+ saturation
- (lightness
* saturation
);
529 var m1
= (2.0 * lightness
) - m2
;
530 var f
= MochiKit
.Color
._hslValue
;
532 red
= f(m1
, m2
, h6
+ 2);
533 green
= f(m1
, m2
, h6
);
534 blue
= f(m1
, m2
, h6
- 2);
544 /** @id MochiKit.Color.rgbToHSV */
545 rgbToHSV
: function (red
, green
, blue
, alpha
) {
546 if (arguments
.length
== 1) {
553 var max
= Math
.max(Math
.max(red
, green
), blue
);
554 var min
= Math
.min(Math
.min(red
, green
), blue
);
562 var delta
= (max
- min
);
563 saturation
= delta
/ max
;
566 hue
= (green
- blue
) / delta
;
567 } else if (green
== max
) {
568 hue
= 2 + ((blue
- red
) / delta
);
570 hue
= 4 + ((red
- green
) / delta
);
588 /** @id MochiKit.Color.rgbToHSL */
589 rgbToHSL
: function (red
, green
, blue
, alpha
) {
590 if (arguments
.length
== 1) {
597 var max
= Math
.max(red
, Math
.max(green
, blue
));
598 var min
= Math
.min(red
, Math
.min(green
, blue
));
601 var lightness
= (max
+ min
) / 2.0;
602 var delta
= max
- min
;
607 if (lightness
<= 0.5) {
608 saturation
= delta
/ (max
+ min
);
610 saturation
= delta
/ (2 - max
- min
);
613 hue
= (green
- blue
) / delta
;
614 } else if (green
== max
) {
615 hue
= 2 + ((blue
- red
) / delta
);
617 hue
= 4 + ((red
- green
) / delta
);
636 /** @id MochiKit.Color.toColorPart */
637 toColorPart
: function (num
) {
638 num
= Math
.round(num
);
639 var digits
= num
.toString(16);
646 __new__
: function () {
647 var m
= MochiKit
.Base
;
648 /** @id MochiKit.Color.fromRGBString */
649 this.Color
.fromRGBString
= m
.bind(
650 this.Color
._fromColorString
, this.Color
, "rgb", "fromRGB",
651 [1.0/255.0, 1.0/255.0, 1.0/255.0, 1]
653 /** @id MochiKit.Color.fromHSLString */
654 this.Color
.fromHSLString
= m
.bind(
655 this.Color
._fromColorString
, this.Color
, "hsl", "fromHSL",
656 [1.0/360.0, 0.01, 0.01, 1]
659 var third
= 1.0 / 3.0;
660 /** @id MochiKit.Color.colors */
662 // NSColor colors plus transparent
663 /** @id MochiKit.Color.blackColor */
665 /** @id MochiKit.Color.blueColor */
667 /** @id MochiKit.Color.brownColor */
668 brown
: [0.6, 0.4, 0.2],
669 /** @id MochiKit.Color.cyanColor */
671 /** @id MochiKit.Color.darkGrayColor */
672 darkGray
: [third
, third
, third
],
673 /** @id MochiKit.Color.grayColor */
674 gray
: [0.5, 0.5, 0.5],
675 /** @id MochiKit.Color.greenColor */
677 /** @id MochiKit.Color.lightGrayColor */
678 lightGray
: [2 * third
, 2 * third
, 2 * third
],
679 /** @id MochiKit.Color.magentaColor */
681 /** @id MochiKit.Color.orangeColor */
683 /** @id MochiKit.Color.purpleColor */
684 purple
: [0.5, 0, 0.5],
685 /** @id MochiKit.Color.redColor */
687 /** @id MochiKit.Color.transparentColor */
688 transparent
: [0, 0, 0, 0],
689 /** @id MochiKit.Color.whiteColor */
691 /** @id MochiKit.Color.yellowColor */
695 var makeColor
= function (name
, r
, g
, b
, a
) {
696 var rval
= this.fromRGB(r
, g
, b
, a
);
697 this[name
] = function () { return rval
; };
701 for (var k
in colors
) {
702 var name
= k
+ "Color";
703 var bindArgs
= m
.concat(
704 [makeColor
, this.Color
, name
],
707 this.Color
[name
] = m
.bind
.apply(null, bindArgs
);
710 var isColor
= function () {
711 for (var i
= 0; i
< arguments
.length
; i
++) {
712 if (!(arguments
[i
] instanceof Color
)) {
719 var compareColor
= function (a
, b
) {
720 return a
.compareRGB(b
);
723 m
.nameFunctions(this);
725 m
.registerComparator(this.Color
.NAME
, isColor
, compareColor
);
728 ":common": this.EXPORT
,
729 ":all": m
.concat(this.EXPORT
, this.EXPORT_OK
)
735 MochiKit
.Color
.EXPORT
= [
739 MochiKit
.Color
.EXPORT_OK
= [
740 "clampColorComponent",
748 MochiKit
.Color
.__new__();
750 MochiKit
.Base
._exportSymbols(this, MochiKit
.Color
);
752 // Full table of css3 X11 colors <http://www.w3.org/TR
/css3-color/#X11COLORS
>
754 MochiKit
.Color
.Color
._namedColors
= {
755 aliceblue
: "#f0f8ff",
756 antiquewhite
: "#faebd7",
758 aquamarine
: "#7fffd4",
763 blanchedalmond
: "#ffebcd",
765 blueviolet
: "#8a2be2",
767 burlywood
: "#deb887",
768 cadetblue
: "#5f9ea0",
769 chartreuse
: "#7fff00",
770 chocolate
: "#d2691e",
772 cornflowerblue
: "#6495ed",
778 darkgoldenrod
: "#b8860b",
780 darkgreen
: "#006400",
782 darkkhaki
: "#bdb76b",
783 darkmagenta
: "#8b008b",
784 darkolivegreen
: "#556b2f",
785 darkorange
: "#ff8c00",
786 darkorchid
: "#9932cc",
788 darksalmon
: "#e9967a",
789 darkseagreen
: "#8fbc8f",
790 darkslateblue
: "#483d8b",
791 darkslategray
: "#2f4f4f",
792 darkslategrey
: "#2f4f4f",
793 darkturquoise
: "#00ced1",
794 darkviolet
: "#9400d3",
796 deepskyblue
: "#00bfff",
799 dodgerblue
: "#1e90ff",
800 firebrick
: "#b22222",
801 floralwhite
: "#fffaf0",
802 forestgreen
: "#228b22",
804 gainsboro
: "#dcdcdc",
805 ghostwhite
: "#f8f8ff",
807 goldenrod
: "#daa520",
810 greenyellow
: "#adff2f",
814 indianred
: "#cd5c5c",
819 lavenderblush
: "#fff0f5",
820 lawngreen
: "#7cfc00",
821 lemonchiffon
: "#fffacd",
822 lightblue
: "#add8e6",
823 lightcoral
: "#f08080",
824 lightcyan
: "#e0ffff",
825 lightgoldenrodyellow
: "#fafad2",
826 lightgray
: "#d3d3d3",
827 lightgreen
: "#90ee90",
828 lightgrey
: "#d3d3d3",
829 lightpink
: "#ffb6c1",
830 lightsalmon
: "#ffa07a",
831 lightseagreen
: "#20b2aa",
832 lightskyblue
: "#87cefa",
833 lightslategray
: "#778899",
834 lightslategrey
: "#778899",
835 lightsteelblue
: "#b0c4de",
836 lightyellow
: "#ffffe0",
838 limegreen
: "#32cd32",
842 mediumaquamarine
: "#66cdaa",
843 mediumblue
: "#0000cd",
844 mediumorchid
: "#ba55d3",
845 mediumpurple
: "#9370db",
846 mediumseagreen
: "#3cb371",
847 mediumslateblue
: "#7b68ee",
848 mediumspringgreen
: "#00fa9a",
849 mediumturquoise
: "#48d1cc",
850 mediumvioletred
: "#c71585",
851 midnightblue
: "#191970",
852 mintcream
: "#f5fffa",
853 mistyrose
: "#ffe4e1",
855 navajowhite
: "#ffdead",
859 olivedrab
: "#6b8e23",
861 orangered
: "#ff4500",
863 palegoldenrod
: "#eee8aa",
864 palegreen
: "#98fb98",
865 paleturquoise
: "#afeeee",
866 palevioletred
: "#db7093",
867 papayawhip
: "#ffefd5",
868 peachpuff
: "#ffdab9",
872 powderblue
: "#b0e0e6",
875 rosybrown
: "#bc8f8f",
876 royalblue
: "#4169e1",
877 saddlebrown
: "#8b4513",
879 sandybrown
: "#f4a460",
885 slateblue
: "#6a5acd",
886 slategray
: "#708090",
887 slategrey
: "#708090",
889 springgreen
: "#00ff7f",
890 steelblue
: "#4682b4",
895 turquoise
: "#40e0d0",
899 whitesmoke
: "#f5f5f5",
901 yellowgreen
: "#9acd32"