/**
* @class Roo.lib.Color
* @constructor
* An abstract Color implementation. Concrete Color implementations should use
* an instance of this function as their prototype, and implement the getRGB and
* getHSL functions. getRGB should return an object representing the RGB
* components of this Color, with the red, green, and blue components in the
* range [0,255] and the alpha component in the range [0,100]. getHSL should
* return an object representing the HSL components of this Color, with the hue
* component in the range [0,360), the saturation and lightness components in
* the range [0,100], and the alpha component in the range [0,1].
*
*
* Color.js
*
* Functions for Color handling and processing.
*
* http://www.safalra.com/web-design/javascript/Color-handling-and-processing/
*
* The author of this program, Safalra (Stephen Morley), irrevocably releases all
* rights to this program, with the intention of it becoming part of the public
* domain. Because this program is released into the public domain, it comes with
* no warranty either expressed or implied, to the extent permitted by law.
*
* For more free and public domain JavaScript code by the same author, visit:
* http://www.safalra.com/web-design/javascript/
*
*/
Roo.lib.Color = function() { }
Roo.apply(Roo.lib.Color.prototype, {
rgb : null,
hsv : null,
hsl : null,
/**
* getIntegerRGB
* @return {Object} an object representing the RGBA components of this Color. The red,
* green, and blue components are converted to integers in the range [0,255].
* The alpha is a value in the range [0,1].
*/
getIntegerRGB : function(){
// get the RGB components of this Color
var rgb = this.getRGB();
// return the integer components
return {
'r' : Math.round(rgb.r),
'g' : Math.round(rgb.g),
'b' : Math.round(rgb.b),
'a' : rgb.a
};
},
/**
* getPercentageRGB
* @return {Object} an object representing the RGBA components of this Color. The red,
* green, and blue components are converted to numbers in the range [0,100].
* The alpha is a value in the range [0,1].
*/
getPercentageRGB : function(){
// get the RGB components of this Color
var rgb = this.getRGB();
// return the percentage components
return {
'r' : 100 * rgb.r / 255,
'g' : 100 * rgb.g / 255,
'b' : 100 * rgb.b / 255,
'a' : rgb.a
};
},
/**
* getCSSHexadecimalRGB
* @return {String} a string representing this Color as a CSS hexadecimal RGB Color
* value - that is, a string of the form #RRGGBB where each of RR, GG, and BB
* are two-digit hexadecimal numbers.
*/
getCSSHexadecimalRGB : function()
{
// get the integer RGB components
var rgb = this.getIntegerRGB();
// determine the hexadecimal equivalents
var r16 = rgb.r.toString(16);
var g16 = rgb.g.toString(16);
var b16 = rgb.b.toString(16);
// return the CSS RGB Color value
return '#'
+ (r16.length == 2 ? r16 : '0' + r16)
+ (g16.length == 2 ? g16 : '0' + g16)
+ (b16.length == 2 ? b16 : '0' + b16);
},
/**
* getCSSIntegerRGB
* @return {String} a string representing this Color as a CSS integer RGB Color
* value - that is, a string of the form rgb(r,g,b) where each of r, g, and b
* are integers in the range [0,255].
*/
getCSSIntegerRGB : function(){
// get the integer RGB components
var rgb = this.getIntegerRGB();
// return the CSS RGB Color value
return 'rgb(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ')';
},
/**
* getCSSIntegerRGBA
* @return {String} Returns a string representing this Color as a CSS integer RGBA Color
* value - that is, a string of the form rgba(r,g,b,a) where each of r, g, and
* b are integers in the range [0,255] and a is in the range [0,1].
*/
getCSSIntegerRGBA : function(){
// get the integer RGB components
var rgb = this.getIntegerRGB();
// return the CSS integer RGBA Color value
return 'rgb(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + rgb.a + ')';
},
/**
* getCSSPercentageRGB
* @return {String} a string representing this Color as a CSS percentage RGB Color
* value - that is, a string of the form rgb(r%,g%,b%) where each of r, g, and
* b are in the range [0,100].
*/
getCSSPercentageRGB : function(){
// get the percentage RGB components
var rgb = this.getPercentageRGB();
// return the CSS RGB Color value
return 'rgb(' + rgb.r + '%,' + rgb.g + '%,' + rgb.b + '%)';
},
/**
* getCSSPercentageRGBA
* @return {String} a string representing this Color as a CSS percentage RGBA Color
* value - that is, a string of the form rgba(r%,g%,b%,a) where each of r, g,
* and b are in the range [0,100] and a is in the range [0,1].
*/
getCSSPercentageRGBA : function(){
// get the percentage RGB components
var rgb = this.getPercentageRGB();
// return the CSS percentage RGBA Color value
return 'rgb(' + rgb.r + '%,' + rgb.g + '%,' + rgb.b + '%,' + rgb.a + ')';
},
/**
* getCSSHSL
* @return {String} a string representing this Color as a CSS HSL Color value - that
* is, a string of the form hsl(h,s%,l%) where h is in the range [0,100] and
* s and l are in the range [0,100].
*/
getCSSHSL : function(){
// get the HSL components
var hsl = this.getHSL();
// return the CSS HSL Color value
return 'hsl(' + hsl.h + ',' + hsl.s + '%,' + hsl.l + '%)';
},
/**
* getCSSHSLA
* @return {String} a string representing this Color as a CSS HSLA Color value - that
* is, a string of the form hsla(h,s%,l%,a) where h is in the range [0,100],
* s and l are in the range [0,100], and a is in the range [0,1].
*/
getCSSHSLA : function(){
// get the HSL components
var hsl = this.getHSL();
// return the CSS HSL Color value
return 'hsl(' + hsl.h + ',' + hsl.s + '%,' + hsl.l + '%,' + hsl.a + ')';
},
/**
* Sets the Color of the specified node to this Color. This functions sets
* the CSS 'color' property for the node. The parameter is:
*
* @param {DomElement} node - the node whose Color should be set
*/
setNodeColor : function(node){
// set the Color of the node
node.style.color = this.getCSSHexadecimalRGB();
},
/**
* Sets the background Color of the specified node to this Color. This
* functions sets the CSS 'background-color' property for the node. The
* parameter is:
*
* @param {DomElement} node - the node whose background Color should be set
*/
setNodeBackgroundColor : function(node){
// set the background Color of the node
node.style.backgroundColor = this.getCSSHexadecimalRGB();
},
// convert between formats..
toRGB: function()
{
var r = this.getIntegerRGB();
return new Roo.lib.RGBColor(r.r,r.g,r.b,r.a);
},
toHSL : function()
{
var hsl = this.getHSL();
// return the CSS HSL Color value
return new Roo.lib.HSLColor(hsl.h, hsl.s, hsl.l , hsl.a );
},
toHSV : function()
{
var rgb = this.toRGB();
var hsv = rgb.getHSV();
// return the CSS HSL Color value
return new Roo.lib.HSVColor(hsv.h, hsv.s, hsv.v , hsv.a );
},
// modify v = 0 ... 1 (eg. 0.5)
saturate : function(v)
{
var rgb = this.toRGB();
var hsv = rgb.getHSV();
return new Roo.lib.HSVColor(hsv.h, hsv.s * v, hsv.v , hsv.a );
},
/**
* getRGB
* @return {Object} the RGB and alpha components of this Color as an object with r,
* g, b, and a properties. r, g, and b are in the range [0,255] and a is in
* the range [0,1].
*/
getRGB: function(){
// return the RGB components
return {
'r' : this.rgb.r,
'g' : this.rgb.g,
'b' : this.rgb.b,
'a' : this.alpha
};
},
/**
* getHSV
* @return {Object} the HSV and alpha components of this Color as an object with h,
* s, v, and a properties. h is in the range [0,360), s and v are in the range
* [0,100], and a is in the range [0,1].
*/
getHSV : function()
{
// calculate the HSV components if necessary
if (this.hsv == null) {
this.calculateHSV();
}
// return the HSV components
return {
'h' : this.hsv.h,
's' : this.hsv.s,
'v' : this.hsv.v,
'a' : this.alpha
};
},
/**
* getHSL
* @return {Object} the HSL and alpha components of this Color as an object with h,
* s, l, and a properties. h is in the range [0,360), s and l are in the range
* [0,100], and a is in the range [0,1].
*/
getHSL : function(){
// calculate the HSV components if necessary
if (this.hsl == null) { this.calculateHSL(); }
// return the HSL components
return {
'h' : this.hsl.h,
's' : this.hsl.s,
'l' : this.hsl.l,
'a' : this.alpha
};
}
});
/**
* @class Roo.lib.RGBColor
* @extends Roo.lib.Color
* Creates a Color specified in the RGB Color space, with an optional alpha
* component. The parameters are:
* @constructor
*
* @param {Number} r - the red component, clipped to the range [0,255]
* @param {Number} g - the green component, clipped to the range [0,255]
* @param {Number} b - the blue component, clipped to the range [0,255]
* @param {Number} a - the alpha component, clipped to the range [0,1] - this parameter is
* optional and defaults to 1
*/
Roo.lib.RGBColor = function (r, g, b, a){
// store the alpha component after clipping it if necessary
this.alpha = (a === undefined ? 1 : Math.max(0, Math.min(1, a)));
// store the RGB components after clipping them if necessary
this.rgb =
{
'r' : Math.max(0, Math.min(255, r)),
'g' : Math.max(0, Math.min(255, g)),
'b' : Math.max(0, Math.min(255, b))
};
// initialise the HSV and HSL components to null
/*
* //private returns the HSV or HSL hue component of this RGBColor. The hue is in the
* range [0,360). The parameters are:
*
* maximum - the maximum of the RGB component values
* range - the range of the RGB component values
*/
}
// this does an 'exteds'
Roo.extend(Roo.lib.RGBColor, Roo.lib.Color, {
getHue : function(maximum, range)
{
var rgb = this.rgb;
// check whether the range is zero
if (range == 0){
// set the hue to zero (any hue is acceptable as the Color is grey)
var hue = 0;
}else{
// determine which of the components has the highest value and set the hue
switch (maximum){
// red has the highest value
case rgb.r:
var hue = (rgb.g - rgb.b) / range * 60;
if (hue < 0) { hue += 360; }
break;
// green has the highest value
case rgb.g:
var hue = (rgb.b - rgb.r) / range * 60 + 120;
break;
// blue has the highest value
case rgb.b:
var hue = (rgb.r - rgb.g) / range * 60 + 240;
break;
}
}
// return the hue
return hue;
},
/* //private Calculates and stores the HSV components of this RGBColor so that they can
* be returned be the getHSV function.
*/
calculateHSV : function(){
var rgb = this.rgb;
// get the maximum and range of the RGB component values
var maximum = Math.max(rgb.r, rgb.g, rgb.b);
var range = maximum - Math.min(rgb.r, rgb.g, rgb.b);
// store the HSV components
this.hsv =
{
'h' : this.getHue(maximum, range),
's' : (maximum == 0 ? 0 : 100 * range / maximum),
'v' : maximum / 2.55
};
},
/* //private Calculates and stores the HSL components of this RGBColor so that they can
* be returned be the getHSL function.
*/
calculateHSL : function(){
var rgb = this.rgb;
// get the maximum and range of the RGB component values
var maximum = Math.max(rgb.r, rgb.g, rgb.b);
var range = maximum - Math.min(rgb.r, rgb.g, rgb.b);
// determine the lightness in the range [0,1]
var l = maximum / 255 - range / 510;
// store the HSL components
this.hsl =
{
'h' : this.getHue(maximum, range),
's' : (range == 0 ? 0 : range / 2.55 / (l < 0.5 ? l * 2 : 2 - l * 2)),
'l' : 100 * l
};
}
});
/**
* @class Roo.lib.HSVColor
* @extends Roo.lib.Color
* Creates a Color specified in the HSV Color space, with an optional alpha
* component. The parameters are:
* @constructor
*
* @param {Number} h - the hue component, wrapped to the range [0,360)
* @param {Number} s - the saturation component, clipped to the range [0,100]
* @param {Number} v - the value component, clipped to the range [0,100]
* @param {Number} a - the alpha component, clipped to the range [0,1] - this parameter is
* optional and defaults to 1
*/
Roo.lib.HSVColor = function (h, s, v, a){
// store the alpha component after clipping it if necessary
this.alpha = (a === undefined ? 1 : Math.max(0, Math.min(1, a)));
// store the HSV components after clipping or wrapping them if necessary
this.hsv =
{
'h' : (h % 360 + 360) % 360,
's' : Math.max(0, Math.min(100, s)),
'v' : Math.max(0, Math.min(100, v))
};
// initialise the RGB and HSL components to null
this.rgb = null;
this.hsl = null;
}
Roo.extend(Roo.lib.HSVColor, Roo.lib.Color, {
/* Calculates and stores the RGB components of this HSVColor so that they can
* be returned be the getRGB function.
*/
calculateRGB: function ()
{
var hsv = this.hsv;
// check whether the saturation is zero
if (hsv.s == 0){
// set the Color to the appropriate shade of grey
var r = hsv.v;
var g = hsv.v;
var b = hsv.v;
}else{
// set some temporary values
var f = hsv.h / 60 - Math.floor(hsv.h / 60);
var p = hsv.v * (1 - hsv.s / 100);
var q = hsv.v * (1 - hsv.s / 100 * f);
var t = hsv.v * (1 - hsv.s / 100 * (1 - f));
// set the RGB Color components to their temporary values
switch (Math.floor(hsv.h / 60)){
case 0: var r = hsv.v; var g = t; var b = p; break;
case 1: var r = q; var g = hsv.v; var b = p; break;
case 2: var r = p; var g = hsv.v; var b = t; break;
case 3: var r = p; var g = q; var b = hsv.v; break;
case 4: var r = t; var g = p; var b = hsv.v; break;
case 5: var r = hsv.v; var g = p; var b = q; break;
}
}
// store the RGB components
this.rgb =
{
'r' : r * 2.55,
'g' : g * 2.55,
'b' : b * 2.55
};
},
/* Calculates and stores the HSL components of this HSVColor so that they can
* be returned be the getHSL function.
*/
calculateHSL : function (){
var hsv = this.hsv;
// determine the lightness in the range [0,100]
var l = (2 - hsv.s / 100) * hsv.v / 2;
// store the HSL components
this.hsl =
{
'h' : hsv.h,
's' : hsv.s * hsv.v / (l < 50 ? l * 2 : 200 - l * 2),
'l' : l
};
// correct a division-by-zero error
if (isNaN(hsl.s)) { hsl.s = 0; }
}
});
/**
* @class Roo.lib.HSLColor
* @extends Roo.lib.Color
*
* @constructor
* Creates a Color specified in the HSL Color space, with an optional alpha
* component. The parameters are:
*
* @param {Number} h - the hue component, wrapped to the range [0,360)
* @param {Number} s - the saturation component, clipped to the range [0,100]
* @param {Number} l - the lightness component, clipped to the range [0,100]
* @param {Number} a - the alpha component, clipped to the range [0,1] - this parameter is
* optional and defaults to 1
*/
Roo.lib.HSLColor = function(h, s, l, a){
// store the alpha component after clipping it if necessary
this.alpha = (a === undefined ? 1 : Math.max(0, Math.min(1, a)));
// store the HSL components after clipping or wrapping them if necessary
this.hsl =
{
'h' : (h % 360 + 360) % 360,
's' : Math.max(0, Math.min(100, s)),
'l' : Math.max(0, Math.min(100, l))
};
// initialise the RGB and HSV components to null
}
Roo.extend(Roo.lib.HSLColor, Roo.lib.Color, {
/* Calculates and stores the RGB components of this HSLColor so that they can
* be returned be the getRGB function.
*/
calculateRGB: function (){
// check whether the saturation is zero
if (this.hsl.s == 0){
// store the RGB components representing the appropriate shade of grey
this.rgb =
{
'r' : this.hsl.l * 2.55,
'g' : this.hsl.l * 2.55,
'b' : this.hsl.l * 2.55
};
}else{
// set some temporary values
var p = this.hsl.l < 50
? this.hsl.l * (1 + hsl.s / 100)
: this.hsl.l + hsl.s - hsl.l * hsl.s / 100;
var q = 2 * hsl.l - p;
// initialise the RGB components
this.rgb =
{
'r' : (h + 120) / 60 % 6,
'g' : h / 60,
'b' : (h + 240) / 60 % 6
};
// loop over the RGB components
for (var key in this.rgb){
// ensure that the property is not inherited from the root object
if (this.rgb.hasOwnProperty(key)){
// set the component to its value in the range [0,100]
if (this.rgb[key] < 1){
this.rgb[key] = q + (p - q) * this.rgb[key];
}else if (this.rgb[key] < 3){
this.rgb[key] = p;
}else if (this.rgb[key] < 4){
this.rgb[key] = q + (p - q) * (4 - this.rgb[key]);
}else{
this.rgb[key] = q;
}
// set the component to its value in the range [0,255]
this.rgb[key] *= 2.55;
}
}
}
},
/* Calculates and stores the HSV components of this HSLColor so that they can
* be returned be the getHSL function.
*/
calculateHSV : function(){
// set a temporary value
var t = this.hsl.s * (this.hsl.l < 50 ? this.hsl.l : 100 - this.hsl.l) / 100;
// store the HSV components
this.hsv =
{
'h' : this.hsl.h,
's' : 200 * t / (this.hsl.l + t),
'v' : t + this.hsl.l
};
// correct a division-by-zero error
if (isNaN(this.hsv.s)) { this.hsv.s = 0; }
}
});