6 * An abstract Color implementation. Concrete Color implementations should use
7 * an instance of this function as their prototype, and implement the getRGB and
8 * getHSL functions. getRGB should return an object representing the RGB
9 * components of this Color, with the red, green, and blue components in the
10 * range [0,255] and the alpha component in the range [0,100]. getHSL should
11 * return an object representing the HSL components of this Color, with the hue
12 * component in the range [0,360), the saturation and lightness components in
13 * the range [0,100], and the alpha component in the range [0,1].
18 * Functions for Color handling and processing.
20 * http://www.safalra.com/web-design/javascript/Color-handling-and-processing/
22 * The author of this program, Safalra (Stephen Morley), irrevocably releases all
23 * rights to this program, with the intention of it becoming part of the public
24 * domain. Because this program is released into the public domain, it comes with
25 * no warranty either expressed or implied, to the extent permitted by law.
27 * For more free and public domain JavaScript code by the same author, visit:
28 * http://www.safalra.com/web-design/javascript/
31 Roo.lib.Color = function() { }
34 Roo.apply(Roo.lib.Color.prototype, {
42 * @return {Object} an object representing the RGBA components of this Color. The red,
43 * green, and blue components are converted to integers in the range [0,255].
44 * The alpha is a value in the range [0,1].
46 getIntegerRGB : function(){
48 // get the RGB components of this Color
49 var rgb = this.getRGB();
51 // return the integer components
53 'r' : Math.round(rgb.r),
54 'g' : Math.round(rgb.g),
55 'b' : Math.round(rgb.b),
63 * @return {Object} an object representing the RGBA components of this Color. The red,
64 * green, and blue components are converted to numbers in the range [0,100].
65 * The alpha is a value in the range [0,1].
67 getPercentageRGB : function(){
69 // get the RGB components of this Color
70 var rgb = this.getRGB();
72 // return the percentage components
74 'r' : 100 * rgb.r / 255,
75 'g' : 100 * rgb.g / 255,
76 'b' : 100 * rgb.b / 255,
83 * getCSSHexadecimalRGB
84 * @return {String} a string representing this Color as a CSS hexadecimal RGB Color
85 * value - that is, a string of the form #RRGGBB where each of RR, GG, and BB
86 * are two-digit hexadecimal numbers.
88 getCSSHexadecimalRGB : function()
91 // get the integer RGB components
92 var rgb = this.getIntegerRGB();
94 // determine the hexadecimal equivalents
95 var r16 = rgb.r.toString(16);
96 var g16 = rgb.g.toString(16);
97 var b16 = rgb.b.toString(16);
99 // return the CSS RGB Color value
101 + (r16.length == 2 ? r16 : '0' + r16)
102 + (g16.length == 2 ? g16 : '0' + g16)
103 + (b16.length == 2 ? b16 : '0' + b16);
109 * @return {String} a string representing this Color as a CSS integer RGB Color
110 * value - that is, a string of the form rgb(r,g,b) where each of r, g, and b
111 * are integers in the range [0,255].
113 getCSSIntegerRGB : function(){
115 // get the integer RGB components
116 var rgb = this.getIntegerRGB();
118 // return the CSS RGB Color value
119 return 'rgb(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ')';
125 * @return {String} Returns a string representing this Color as a CSS integer RGBA Color
126 * value - that is, a string of the form rgba(r,g,b,a) where each of r, g, and
127 * b are integers in the range [0,255] and a is in the range [0,1].
129 getCSSIntegerRGBA : function(){
131 // get the integer RGB components
132 var rgb = this.getIntegerRGB();
134 // return the CSS integer RGBA Color value
135 return 'rgb(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + rgb.a + ')';
140 * getCSSPercentageRGB
141 * @return {String} a string representing this Color as a CSS percentage RGB Color
142 * value - that is, a string of the form rgb(r%,g%,b%) where each of r, g, and
143 * b are in the range [0,100].
145 getCSSPercentageRGB : function(){
147 // get the percentage RGB components
148 var rgb = this.getPercentageRGB();
150 // return the CSS RGB Color value
151 return 'rgb(' + rgb.r + '%,' + rgb.g + '%,' + rgb.b + '%)';
156 * getCSSPercentageRGBA
157 * @return {String} a string representing this Color as a CSS percentage RGBA Color
158 * value - that is, a string of the form rgba(r%,g%,b%,a) where each of r, g,
159 * and b are in the range [0,100] and a is in the range [0,1].
161 getCSSPercentageRGBA : function(){
163 // get the percentage RGB components
164 var rgb = this.getPercentageRGB();
166 // return the CSS percentage RGBA Color value
167 return 'rgb(' + rgb.r + '%,' + rgb.g + '%,' + rgb.b + '%,' + rgb.a + ')';
173 * @return {String} a string representing this Color as a CSS HSL Color value - that
174 * is, a string of the form hsl(h,s%,l%) where h is in the range [0,100] and
175 * s and l are in the range [0,100].
177 getCSSHSL : function(){
179 // get the HSL components
180 var hsl = this.getHSL();
182 // return the CSS HSL Color value
183 return 'hsl(' + hsl.h + ',' + hsl.s + '%,' + hsl.l + '%)';
189 * @return {String} a string representing this Color as a CSS HSLA Color value - that
190 * is, a string of the form hsla(h,s%,l%,a) where h is in the range [0,100],
191 * s and l are in the range [0,100], and a is in the range [0,1].
193 getCSSHSLA : function(){
195 // get the HSL components
196 var hsl = this.getHSL();
198 // return the CSS HSL Color value
199 return 'hsl(' + hsl.h + ',' + hsl.s + '%,' + hsl.l + '%,' + hsl.a + ')';
204 * Sets the Color of the specified node to this Color. This functions sets
205 * the CSS 'color' property for the node. The parameter is:
207 * @param {DomElement} node - the node whose Color should be set
209 setNodeColor : function(node){
211 // set the Color of the node
212 node.style.color = this.getCSSHexadecimalRGB();
217 * Sets the background Color of the specified node to this Color. This
218 * functions sets the CSS 'background-color' property for the node. The
221 * @param {DomElement} node - the node whose background Color should be set
223 setNodeBackgroundColor : function(node){
225 // set the background Color of the node
226 node.style.backgroundColor = this.getCSSHexadecimalRGB();
229 // convert between formats..
232 var r = this.getIntegerRGB();
233 return new Roo.lib.RGBColor(r.r,r.g,r.b,r.a);
238 var hsl = this.getHSL();
239 // return the CSS HSL Color value
240 return new Roo.lib.HSLColor(hsl.h, hsl.s, hsl.l , hsl.a );
246 var rgb = this.toRGB();
247 var hsv = rgb.getHSV();
248 // return the CSS HSL Color value
249 return new Roo.lib.HSVColor(hsv.h, hsv.s, hsv.v , hsv.a );
253 // modify v = 0 ... 1 (eg. 0.5)
254 saturate : function(v)
256 var rgb = this.toRGB();
257 var hsv = rgb.getHSV();
258 return new Roo.lib.HSVColor(hsv.h, hsv.s * v, hsv.v , hsv.a );
266 * @return {Object} the RGB and alpha components of this Color as an object with r,
267 * g, b, and a properties. r, g, and b are in the range [0,255] and a is in
272 // return the RGB components
284 * @return {Object} the HSV and alpha components of this Color as an object with h,
285 * s, v, and a properties. h is in the range [0,360), s and v are in the range
286 * [0,100], and a is in the range [0,1].
291 // calculate the HSV components if necessary
292 if (this.hsv == null) {
296 // return the HSV components
308 * @return {Object} the HSL and alpha components of this Color as an object with h,
309 * s, l, and a properties. h is in the range [0,360), s and l are in the range
310 * [0,100], and a is in the range [0,1].
315 // calculate the HSV components if necessary
316 if (this.hsl == null) { this.calculateHSL(); }
318 // return the HSL components
333 * @class Roo.lib.RGBColor
334 * @extends Roo.lib.Color
335 * Creates a Color specified in the RGB Color space, with an optional alpha
336 * component. The parameters are:
340 * @param {Number} r - the red component, clipped to the range [0,255]
341 * @param {Number} g - the green component, clipped to the range [0,255]
342 * @param {Number} b - the blue component, clipped to the range [0,255]
343 * @param {Number} a - the alpha component, clipped to the range [0,1] - this parameter is
344 * optional and defaults to 1
346 Roo.lib.RGBColor = function (r, g, b, a){
348 // store the alpha component after clipping it if necessary
349 this.alpha = (a === undefined ? 1 : Math.max(0, Math.min(1, a)));
351 // store the RGB components after clipping them if necessary
354 'r' : Math.max(0, Math.min(255, r)),
355 'g' : Math.max(0, Math.min(255, g)),
356 'b' : Math.max(0, Math.min(255, b))
359 // initialise the HSV and HSL components to null
363 * //private returns the HSV or HSL hue component of this RGBColor. The hue is in the
364 * range [0,360). The parameters are:
366 * maximum - the maximum of the RGB component values
367 * range - the range of the RGB component values
372 // this does an 'exteds'
373 Roo.extend(Roo.lib.RGBColor, Roo.lib.Color, {
376 getHue : function(maximum, range)
380 // check whether the range is zero
383 // set the hue to zero (any hue is acceptable as the Color is grey)
388 // determine which of the components has the highest value and set the hue
391 // red has the highest value
393 var hue = (rgb.g - rgb.b) / range * 60;
394 if (hue < 0) { hue += 360; }
397 // green has the highest value
399 var hue = (rgb.b - rgb.r) / range * 60 + 120;
402 // blue has the highest value
404 var hue = (rgb.r - rgb.g) / range * 60 + 240;
416 /* //private Calculates and stores the HSV components of this RGBColor so that they can
417 * be returned be the getHSV function.
419 calculateHSV : function(){
421 // get the maximum and range of the RGB component values
422 var maximum = Math.max(rgb.r, rgb.g, rgb.b);
423 var range = maximum - Math.min(rgb.r, rgb.g, rgb.b);
425 // store the HSV components
428 'h' : this.getHue(maximum, range),
429 's' : (maximum == 0 ? 0 : 100 * range / maximum),
435 /* //private Calculates and stores the HSL components of this RGBColor so that they can
436 * be returned be the getHSL function.
438 calculateHSL : function(){
440 // get the maximum and range of the RGB component values
441 var maximum = Math.max(rgb.r, rgb.g, rgb.b);
442 var range = maximum - Math.min(rgb.r, rgb.g, rgb.b);
444 // determine the lightness in the range [0,1]
445 var l = maximum / 255 - range / 510;
447 // store the HSL components
450 'h' : this.getHue(maximum, range),
451 's' : (range == 0 ? 0 : range / 2.55 / (l < 0.5 ? l * 2 : 2 - l * 2)),
460 * @class Roo.lib.HSVColor
461 * @extends Roo.lib.Color
462 * Creates a Color specified in the HSV Color space, with an optional alpha
463 * component. The parameters are:
466 * @param {Number} h - the hue component, wrapped to the range [0,360)
467 * @param {Number} s - the saturation component, clipped to the range [0,100]
468 * @param {Number} v - the value component, clipped to the range [0,100]
469 * @param {Number} a - the alpha component, clipped to the range [0,1] - this parameter is
470 * optional and defaults to 1
472 Roo.lib.HSVColor = function (h, s, v, a){
474 // store the alpha component after clipping it if necessary
475 this.alpha = (a === undefined ? 1 : Math.max(0, Math.min(1, a)));
477 // store the HSV components after clipping or wrapping them if necessary
480 'h' : (h % 360 + 360) % 360,
481 's' : Math.max(0, Math.min(100, s)),
482 'v' : Math.max(0, Math.min(100, v))
485 // initialise the RGB and HSL components to null
490 Roo.extend(Roo.lib.HSVColor, Roo.lib.Color, {
491 /* Calculates and stores the RGB components of this HSVColor so that they can
492 * be returned be the getRGB function.
494 calculateRGB: function ()
497 // check whether the saturation is zero
500 // set the Color to the appropriate shade of grey
507 // set some temporary values
508 var f = hsv.h / 60 - Math.floor(hsv.h / 60);
509 var p = hsv.v * (1 - hsv.s / 100);
510 var q = hsv.v * (1 - hsv.s / 100 * f);
511 var t = hsv.v * (1 - hsv.s / 100 * (1 - f));
513 // set the RGB Color components to their temporary values
514 switch (Math.floor(hsv.h / 60)){
515 case 0: var r = hsv.v; var g = t; var b = p; break;
516 case 1: var r = q; var g = hsv.v; var b = p; break;
517 case 2: var r = p; var g = hsv.v; var b = t; break;
518 case 3: var r = p; var g = q; var b = hsv.v; break;
519 case 4: var r = t; var g = p; var b = hsv.v; break;
520 case 5: var r = hsv.v; var g = p; var b = q; break;
525 // store the RGB components
535 /* Calculates and stores the HSL components of this HSVColor so that they can
536 * be returned be the getHSL function.
538 calculateHSL : function (){
541 // determine the lightness in the range [0,100]
542 var l = (2 - hsv.s / 100) * hsv.v / 2;
544 // store the HSL components
548 's' : hsv.s * hsv.v / (l < 50 ? l * 2 : 200 - l * 2),
552 // correct a division-by-zero error
553 if (isNaN(hsl.s)) { hsl.s = 0; }
562 * @class Roo.lib.HSLColor
563 * @extends Roo.lib.Color
566 * Creates a Color specified in the HSL Color space, with an optional alpha
567 * component. The parameters are:
569 * @param {Number} h - the hue component, wrapped to the range [0,360)
570 * @param {Number} s - the saturation component, clipped to the range [0,100]
571 * @param {Number} l - the lightness component, clipped to the range [0,100]
572 * @param {Number} a - the alpha component, clipped to the range [0,1] - this parameter is
573 * optional and defaults to 1
576 Roo.lib.HSLColor = function(h, s, l, a){
578 // store the alpha component after clipping it if necessary
579 this.alpha = (a === undefined ? 1 : Math.max(0, Math.min(1, a)));
581 // store the HSL components after clipping or wrapping them if necessary
584 'h' : (h % 360 + 360) % 360,
585 's' : Math.max(0, Math.min(100, s)),
586 'l' : Math.max(0, Math.min(100, l))
589 // initialise the RGB and HSV components to null
592 Roo.extend(Roo.lib.HSLColor, Roo.lib.Color, {
594 /* Calculates and stores the RGB components of this HSLColor so that they can
595 * be returned be the getRGB function.
597 calculateRGB: function (){
599 // check whether the saturation is zero
600 if (this.hsl.s == 0){
602 // store the RGB components representing the appropriate shade of grey
605 'r' : this.hsl.l * 2.55,
606 'g' : this.hsl.l * 2.55,
607 'b' : this.hsl.l * 2.55
612 // set some temporary values
613 var p = this.hsl.l < 50
614 ? this.hsl.l * (1 + hsl.s / 100)
615 : this.hsl.l + hsl.s - hsl.l * hsl.s / 100;
616 var q = 2 * hsl.l - p;
618 // initialise the RGB components
621 'r' : (h + 120) / 60 % 6,
623 'b' : (h + 240) / 60 % 6
626 // loop over the RGB components
627 for (var key in this.rgb){
629 // ensure that the property is not inherited from the root object
630 if (this.rgb.hasOwnProperty(key)){
632 // set the component to its value in the range [0,100]
633 if (this.rgb[key] < 1){
634 this.rgb[key] = q + (p - q) * this.rgb[key];
635 }else if (this.rgb[key] < 3){
637 }else if (this.rgb[key] < 4){
638 this.rgb[key] = q + (p - q) * (4 - this.rgb[key]);
643 // set the component to its value in the range [0,255]
644 this.rgb[key] *= 2.55;
654 /* Calculates and stores the HSV components of this HSLColor so that they can
655 * be returned be the getHSL function.
657 calculateHSV : function(){
659 // set a temporary value
660 var t = this.hsl.s * (this.hsl.l < 50 ? this.hsl.l : 100 - this.hsl.l) / 100;
662 // store the HSV components
666 's' : 200 * t / (this.hsl.l + t),
670 // correct a division-by-zero error
671 if (isNaN(this.hsv.s)) { this.hsv.s = 0; }