213b6f8d0bd98f70c488d04a7974f7bd743a3692
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');
16 if (typeof(JSAN
) != 'undefined') {
17 JSAN
.use("MochiKit.Base", []);
21 if (typeof(MochiKit
.Base
) == 'undefined') {
25 throw "MochiKit.Color depends on MochiKit.Base";
28 if (typeof(MochiKit
.Color
) == "undefined") {
32 MochiKit
.Color
.NAME
= "MochiKit.Color";
33 MochiKit
.Color
.VERSION
= "1.4";
35 MochiKit
.Color
.__repr__
= function () {
36 return "[" + this.NAME
+ " " + this.VERSION
+ "]";
39 MochiKit
.Color
.toString
= function () {
40 return this.__repr__();
44 /** @id MochiKit.Color.Color */
45 MochiKit
.Color
.Color
= function (red
, green
, blue
, alpha
) {
46 if (typeof(alpha
) == 'undefined' || alpha
=== null) {
60 MochiKit
.Color
.Color
.prototype = {
62 __class__
: MochiKit
.Color
.Color
,
64 /** @id MochiKit.Color.Color.prototype.colorWithAlpha */
65 colorWithAlpha
: function (alpha
) {
67 var m
= MochiKit
.Color
;
68 return m
.Color
.fromRGB(rgb
.r
, rgb
.g
, rgb
.b
, alpha
);
71 /** @id MochiKit.Color.Color.prototype.colorWithHue */
72 colorWithHue
: function (hue
) {
73 // get an HSL model, and set the new hue...
74 var hsl
= this.asHSL();
76 var m
= MochiKit
.Color
;
77 // convert back to RGB...
78 return m
.Color
.fromHSL(hsl
);
81 /** @id MochiKit.Color.Color.prototype.colorWithSaturation */
82 colorWithSaturation
: function (saturation
) {
83 // get an HSL model, and set the new hue...
84 var hsl
= this.asHSL();
86 var m
= MochiKit
.Color
;
87 // convert back to RGB...
88 return m
.Color
.fromHSL(hsl
);
91 /** @id MochiKit.Color.Color.prototype.colorWithLightness */
92 colorWithLightness
: function (lightness
) {
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.darkerColorWithLevel */
102 darkerColorWithLevel
: function (level
) {
103 var hsl
= this.asHSL();
104 hsl
.l
= Math
.max(hsl
.l
- level
, 0);
105 var m
= MochiKit
.Color
;
106 return m
.Color
.fromHSL(hsl
);
109 /** @id MochiKit.Color.Color.prototype.lighterColorWithLevel */
110 lighterColorWithLevel
: function (level
) {
111 var hsl
= this.asHSL();
112 hsl
.l
= Math
.min(hsl
.l
+ level
, 1);
113 var m
= MochiKit
.Color
;
114 return m
.Color
.fromHSL(hsl
);
117 /** @id MochiKit.Color.Color.prototype.blendedColor */
118 blendedColor
: function (other
, /* optional */ fraction
) {
119 if (typeof(fraction
) == 'undefined' || fraction
=== null) {
122 var sf
= 1.0 - fraction
;
126 return MochiKit
.Color
.Color
.fromRGB(
127 (s
.r
* sf
) + (d
.r
* df
),
128 (s
.g
* sf
) + (d
.g
* df
),
129 (s
.b
* sf
) + (d
.b
* df
),
130 (s
.a
* sf
) + (d
.a
* df
)
134 /** @id MochiKit.Color.Color.prototype.compareRGB */
135 compareRGB
: function (other
) {
136 var a
= this.asRGB();
137 var b
= other
.asRGB();
138 return MochiKit
.Base
.compare(
139 [a
.r
, a
.g
, a
.b
, a
.a
],
144 /** @id MochiKit.Color.Color.prototype.isLight */
145 isLight
: function () {
146 return this.asHSL().b
> 0.5;
149 /** @id MochiKit.Color.Color.prototype.isDark */
150 isDark
: function () {
151 return (!this.isLight());
154 /** @id MochiKit.Color.Color.prototype.toHSLString */
155 toHSLString
: function () {
156 var c
= this.asHSL();
157 var ccc
= MochiKit
.Color
.clampColorComponent
;
158 var rval
= this._hslString
;
161 ccc(c
.h
, 360).toFixed(0)
162 + "," + ccc(c
.s
, 100).toPrecision(4) + "%"
163 + "," + ccc(c
.l
, 100).toPrecision(4) + "%"
168 rval
= "hsl(" + mid
+ ")";
173 rval
= "hsla(" + mid
+ "," + a
+ ")";
175 this._hslString
= rval
;
180 /** @id MochiKit.Color.Color.prototype.toRGBString */
181 toRGBString
: function () {
183 var ccc
= MochiKit
.Color
.clampColorComponent
;
184 var rval
= this._rgbString
;
187 ccc(c
.r
, 255).toFixed(0)
188 + "," + ccc(c
.g
, 255).toFixed(0)
189 + "," + ccc(c
.b
, 255).toFixed(0)
192 rval
= "rgba(" + mid
+ "," + c
.a
+ ")";
194 rval
= "rgb(" + mid
+ ")";
196 this._rgbString
= rval
;
201 /** @id MochiKit.Color.Color.prototype.asRGB */
203 return MochiKit
.Base
.clone(this.rgb
);
206 /** @id MochiKit.Color.Color.prototype.toHexString */
207 toHexString
: function () {
208 var m
= MochiKit
.Color
;
210 var ccc
= MochiKit
.Color
.clampColorComponent
;
211 var rval
= this._hexString
;
214 m
.toColorPart(ccc(c
.r
, 255)) +
215 m
.toColorPart(ccc(c
.g
, 255)) +
216 m
.toColorPart(ccc(c
.b
, 255))
218 this._hexString
= rval
;
223 /** @id MochiKit.Color.Color.prototype.asHSV */
227 if (typeof(hsv
) == 'undefined' || hsv
=== null) {
228 hsv
= MochiKit
.Color
.rgbToHSV(this.rgb
);
231 return MochiKit
.Base
.clone(hsv
);
234 /** @id MochiKit.Color.Color.prototype.asHSL */
238 if (typeof(hsl
) == 'undefined' || hsl
=== null) {
239 hsl
= MochiKit
.Color
.rgbToHSL(this.rgb
);
242 return MochiKit
.Base
.clone(hsl
);
245 /** @id MochiKit.Color.Color.prototype.toString */
246 toString
: function () {
247 return this.toRGBString();
250 /** @id MochiKit.Color.Color.prototype.repr */
253 var col
= [c
.r
, c
.g
, c
.b
, c
.a
];
254 return this.__class__
.NAME
+ "(" + col
.join(", ") + ")";
259 // Constructor methods
261 MochiKit
.Base
.update(MochiKit
.Color
.Color
, {
262 /** @id MochiKit.Color.Color.fromRGB */
263 fromRGB
: function (red
, green
, blue
, alpha
) {
264 // designated initializer
265 var Color
= MochiKit
.Color
.Color
;
266 if (arguments
.length
== 1) {
271 if (typeof(rgb
.a
) == 'undefined') {
277 return new Color(red
, green
, blue
, alpha
);
280 /** @id MochiKit.Color.Color.fromHSL */
281 fromHSL
: function (hue
, saturation
, lightness
, alpha
) {
282 var m
= MochiKit
.Color
;
283 return m
.Color
.fromRGB(m
.hslToRGB
.apply(m
, arguments
));
286 /** @id MochiKit.Color.Color.fromHSV */
287 fromHSV
: function (hue
, saturation
, value
, alpha
) {
288 var m
= MochiKit
.Color
;
289 return m
.Color
.fromRGB(m
.hsvToRGB
.apply(m
, arguments
));
292 /** @id MochiKit.Color.Color.fromName */
293 fromName
: function (name
) {
294 var Color
= MochiKit
.Color
.Color
;
295 // Opera 9 seems to "quote" named colors(?!)
296 if (name
.charAt(0) == '"') {
297 name
= name
.substr(1, name
.length
- 2);
299 var htmlColor
= Color
._namedColors
[name
.toLowerCase()];
300 if (typeof(htmlColor
) == 'string') {
301 return Color
.fromHexString(htmlColor
);
302 } else if (name
== "transparent") {
303 return Color
.transparentColor();
308 /** @id MochiKit.Color.Color.fromString */
309 fromString
: function (colorString
) {
310 var self
= MochiKit
.Color
.Color
;
311 var three
= colorString
.substr(0, 3);
312 if (three
== "rgb") {
313 return self
.fromRGBString(colorString
);
314 } else if (three
== "hsl") {
315 return self
.fromHSLString(colorString
);
316 } else if (colorString
.charAt(0) == "#") {
317 return self
.fromHexString(colorString
);
319 return self
.fromName(colorString
);
323 /** @id MochiKit.Color.Color.fromHexString */
324 fromHexString
: function (hexCode
) {
325 if (hexCode
.charAt(0) == '#') {
326 hexCode
= hexCode
.substring(1);
330 if (hexCode
.length
== 3) {
331 for (i
= 0; i
< 3; i
++) {
332 hex
= hexCode
.substr(i
, 1);
333 components
.push(parseInt(hex
+ hex
, 16) / 255.0);
336 for (i
= 0; i
< 6; i
+= 2) {
337 hex
= hexCode
.substr(i
, 2);
338 components
.push(parseInt(hex
, 16) / 255.0);
341 var Color
= MochiKit
.Color
.Color
;
342 return Color
.fromRGB
.apply(Color
, components
);
346 _fromColorString
: function (pre
, method
, scales
, colorCode
) {
347 // parses either HSL or RGB
348 if (colorCode
.indexOf(pre
) === 0) {
349 colorCode
= colorCode
.substring(colorCode
.indexOf("(", 3) + 1, colorCode
.length
- 1);
351 var colorChunks
= colorCode
.split(/\s*,\s*/);
352 var colorFloats
= [];
353 for (var i
= 0; i
< colorChunks
.length
; i
++) {
354 var c
= colorChunks
[i
];
356 var three
= c
.substring(c
.length
- 3);
357 if (c
.charAt(c
.length
- 1) == '%') {
358 val
= 0.01 * parseFloat(c
.substring(0, c
.length
- 1));
359 } else if (three
== "deg") {
360 val
= parseFloat(c
) / 360.0;
361 } else if (three
== "rad") {
362 val
= parseFloat(c
) / (Math
.PI
* 2);
364 val
= scales
[i
] * parseFloat(c
);
366 colorFloats
.push(val
);
368 return this[method
].apply(this, colorFloats
);
371 /** @id MochiKit.Color.Color.fromBackground */
372 fromBackground
: function (elem
) {
373 var cls
= MochiKit
.Color
.Color
;
374 return cls
.fromComputedStyle(
375 elem
, "backgroundColor", "background-color") || cls
.whiteColor();
378 /** @id MochiKit.Color.Color.fromText */
379 fromText
: function (elem
) {
380 var cls
= MochiKit
.Color
.Color
;
381 return cls
.fromComputedStyle(
382 elem
, "color", "color") || cls
.blackColor();
385 /** @id MochiKit.Color.Color.namedColors */
386 namedColors
: function () {
387 return MochiKit
.Base
.clone(MochiKit
.Color
.Color
._namedColors
);
392 // Module level functions
394 MochiKit
.Base
.update(MochiKit
.Color
, {
395 /** @id MochiKit.Color.clampColorComponent */
396 clampColorComponent
: function (v
, scale
) {
400 } else if (v
> scale
) {
407 _hslValue
: function (n1
, n2
, hue
) {
410 } else if (hue
< 0.0) {
415 val
= n1
+ (n2
- n1
) * hue
;
416 } else if (hue
< 3.0) {
418 } else if (hue
< 4.0) {
419 val
= n1
+ (n2
- n1
) * (4.0 - hue
);
426 /** @id MochiKit.Color.hsvToRGB */
427 hsvToRGB
: function (hue
, saturation
, value
, alpha
) {
428 if (arguments
.length
== 1) {
438 if (saturation
=== 0) {
443 var i
= Math
.floor(hue
* 6);
444 var f
= (hue
* 6) - i
;
445 var p
= value
* (1 - saturation
);
446 var q
= value
* (1 - (saturation
* f
));
447 var t
= value
* (1 - (saturation
* (1 - f
)));
449 case 1: red
= q
; green
= value
; blue
= p
; break;
450 case 2: red
= p
; green
= value
; blue
= t
; break;
451 case 3: red
= p
; green
= q
; blue
= value
; break;
452 case 4: red
= t
; green
= p
; blue
= value
; break;
453 case 5: red
= value
; green
= p
; blue
= q
; break;
454 case 6: // fall through
455 case 0: red
= value
; green
= t
; blue
= p
; break;
466 /** @id MochiKit.Color.hslToRGB */
467 hslToRGB
: function (hue
, saturation
, lightness
, alpha
) {
468 if (arguments
.length
== 1) {
478 if (saturation
=== 0) {
484 if (lightness
<= 0.5) {
485 m2
= lightness
* (1.0 + saturation
);
487 m2
= lightness
+ saturation
- (lightness
* saturation
);
489 var m1
= (2.0 * lightness
) - m2
;
490 var f
= MochiKit
.Color
._hslValue
;
492 red
= f(m1
, m2
, h6
+ 2);
493 green
= f(m1
, m2
, h6
);
494 blue
= f(m1
, m2
, h6
- 2);
504 /** @id MochiKit.Color.rgbToHSV */
505 rgbToHSV
: function (red
, green
, blue
, alpha
) {
506 if (arguments
.length
== 1) {
513 var max
= Math
.max(Math
.max(red
, green
), blue
);
514 var min
= Math
.min(Math
.min(red
, green
), blue
);
522 var delta
= (max
- min
);
523 saturation
= delta
/ max
;
526 hue
= (green
- blue
) / delta
;
527 } else if (green
== max
) {
528 hue
= 2 + ((blue
- red
) / delta
);
530 hue
= 4 + ((red
- green
) / delta
);
548 /** @id MochiKit.Color.rgbToHSL */
549 rgbToHSL
: function (red
, green
, blue
, alpha
) {
550 if (arguments
.length
== 1) {
557 var max
= Math
.max(red
, Math
.max(green
, blue
));
558 var min
= Math
.min(red
, Math
.min(green
, blue
));
561 var lightness
= (max
+ min
) / 2.0;
562 var delta
= max
- min
;
567 if (lightness
<= 0.5) {
568 saturation
= delta
/ (max
+ min
);
570 saturation
= delta
/ (2 - max
- min
);
573 hue
= (green
- blue
) / delta
;
574 } else if (green
== max
) {
575 hue
= 2 + ((blue
- red
) / delta
);
577 hue
= 4 + ((red
- green
) / delta
);
596 /** @id MochiKit.Color.toColorPart */
597 toColorPart
: function (num
) {
598 num
= Math
.round(num
);
599 var digits
= num
.toString(16);
606 __new__
: function () {
607 var m
= MochiKit
.Base
;
608 /** @id MochiKit.Color.fromRGBString */
609 this.Color
.fromRGBString
= m
.bind(
610 this.Color
._fromColorString
, this.Color
, "rgb", "fromRGB",
611 [1.0/255.0, 1.0/255.0, 1.0/255.0, 1]
613 /** @id MochiKit.Color.fromHSLString */
614 this.Color
.fromHSLString
= m
.bind(
615 this.Color
._fromColorString
, this.Color
, "hsl", "fromHSL",
616 [1.0/360.0, 0.01, 0.01, 1]
619 var third
= 1.0 / 3.0;
620 /** @id MochiKit.Color.colors */
622 // NSColor colors plus transparent
623 /** @id MochiKit.Color.blackColor */
625 /** @id MochiKit.Color.blueColor */
627 /** @id MochiKit.Color.brownColor */
628 brown
: [0.6, 0.4, 0.2],
629 /** @id MochiKit.Color.cyanColor */
631 /** @id MochiKit.Color.darkGrayColor */
632 darkGray
: [third
, third
, third
],
633 /** @id MochiKit.Color.grayColor */
634 gray
: [0.5, 0.5, 0.5],
635 /** @id MochiKit.Color.greenColor */
637 /** @id MochiKit.Color.lightGrayColor */
638 lightGray
: [2 * third
, 2 * third
, 2 * third
],
639 /** @id MochiKit.Color.magentaColor */
641 /** @id MochiKit.Color.orangeColor */
643 /** @id MochiKit.Color.purpleColor */
644 purple
: [0.5, 0, 0.5],
645 /** @id MochiKit.Color.redColor */
647 /** @id MochiKit.Color.transparentColor */
648 transparent
: [0, 0, 0, 0],
649 /** @id MochiKit.Color.whiteColor */
651 /** @id MochiKit.Color.yellowColor */
655 var makeColor
= function (name
, r
, g
, b
, a
) {
656 var rval
= this.fromRGB(r
, g
, b
, a
);
657 this[name
] = function () { return rval
; };
661 for (var k
in colors
) {
662 var name
= k
+ "Color";
663 var bindArgs
= m
.concat(
664 [makeColor
, this.Color
, name
],
667 this.Color
[name
] = m
.bind
.apply(null, bindArgs
);
670 var isColor
= function () {
671 for (var i
= 0; i
< arguments
.length
; i
++) {
672 if (!(arguments
[i
] instanceof Color
)) {
679 var compareColor
= function (a
, b
) {
680 return a
.compareRGB(b
);
683 m
.nameFunctions(this);
685 m
.registerComparator(this.Color
.NAME
, isColor
, compareColor
);
688 ":common": this.EXPORT
,
689 ":all": m
.concat(this.EXPORT
, this.EXPORT_OK
)
695 MochiKit
.Color
.EXPORT
= [
699 MochiKit
.Color
.EXPORT_OK
= [
700 "clampColorComponent",
708 MochiKit
.Color
.__new__();
710 MochiKit
.Base
._exportSymbols(this, MochiKit
.Color
);
712 // Full table of css3 X11 colors <http://www.w3.org/TR
/css3-color/#X11COLORS
>
714 MochiKit
.Color
.Color
._namedColors
= {
715 aliceblue
: "#f0f8ff",
716 antiquewhite
: "#faebd7",
718 aquamarine
: "#7fffd4",
723 blanchedalmond
: "#ffebcd",
725 blueviolet
: "#8a2be2",
727 burlywood
: "#deb887",
728 cadetblue
: "#5f9ea0",
729 chartreuse
: "#7fff00",
730 chocolate
: "#d2691e",
732 cornflowerblue
: "#6495ed",
738 darkgoldenrod
: "#b8860b",
740 darkgreen
: "#006400",
742 darkkhaki
: "#bdb76b",
743 darkmagenta
: "#8b008b",
744 darkolivegreen
: "#556b2f",
745 darkorange
: "#ff8c00",
746 darkorchid
: "#9932cc",
748 darksalmon
: "#e9967a",
749 darkseagreen
: "#8fbc8f",
750 darkslateblue
: "#483d8b",
751 darkslategray
: "#2f4f4f",
752 darkslategrey
: "#2f4f4f",
753 darkturquoise
: "#00ced1",
754 darkviolet
: "#9400d3",
756 deepskyblue
: "#00bfff",
759 dodgerblue
: "#1e90ff",
760 firebrick
: "#b22222",
761 floralwhite
: "#fffaf0",
762 forestgreen
: "#228b22",
764 gainsboro
: "#dcdcdc",
765 ghostwhite
: "#f8f8ff",
767 goldenrod
: "#daa520",
770 greenyellow
: "#adff2f",
774 indianred
: "#cd5c5c",
779 lavenderblush
: "#fff0f5",
780 lawngreen
: "#7cfc00",
781 lemonchiffon
: "#fffacd",
782 lightblue
: "#add8e6",
783 lightcoral
: "#f08080",
784 lightcyan
: "#e0ffff",
785 lightgoldenrodyellow
: "#fafad2",
786 lightgray
: "#d3d3d3",
787 lightgreen
: "#90ee90",
788 lightgrey
: "#d3d3d3",
789 lightpink
: "#ffb6c1",
790 lightsalmon
: "#ffa07a",
791 lightseagreen
: "#20b2aa",
792 lightskyblue
: "#87cefa",
793 lightslategray
: "#778899",
794 lightslategrey
: "#778899",
795 lightsteelblue
: "#b0c4de",
796 lightyellow
: "#ffffe0",
798 limegreen
: "#32cd32",
802 mediumaquamarine
: "#66cdaa",
803 mediumblue
: "#0000cd",
804 mediumorchid
: "#ba55d3",
805 mediumpurple
: "#9370db",
806 mediumseagreen
: "#3cb371",
807 mediumslateblue
: "#7b68ee",
808 mediumspringgreen
: "#00fa9a",
809 mediumturquoise
: "#48d1cc",
810 mediumvioletred
: "#c71585",
811 midnightblue
: "#191970",
812 mintcream
: "#f5fffa",
813 mistyrose
: "#ffe4e1",
815 navajowhite
: "#ffdead",
819 olivedrab
: "#6b8e23",
821 orangered
: "#ff4500",
823 palegoldenrod
: "#eee8aa",
824 palegreen
: "#98fb98",
825 paleturquoise
: "#afeeee",
826 palevioletred
: "#db7093",
827 papayawhip
: "#ffefd5",
828 peachpuff
: "#ffdab9",
832 powderblue
: "#b0e0e6",
835 rosybrown
: "#bc8f8f",
836 royalblue
: "#4169e1",
837 saddlebrown
: "#8b4513",
839 sandybrown
: "#f4a460",
845 slateblue
: "#6a5acd",
846 slategray
: "#708090",
847 slategrey
: "#708090",
849 springgreen
: "#00ff7f",
850 steelblue
: "#4682b4",
855 turquoise
: "#40e0d0",
859 whitesmoke
: "#f5f5f5",
861 yellowgreen
: "#9acd32"