/*!
* CSSUtils | Luis A. Leiva | MIT license
* Some CSS utilities.
*/
/**
* @class
* @description This just documents the CommonJS/AMD/etc. module closure.
*/
;(function(module, global) {
/**
* Some CSS utilities.
* @module CSSUtils
*/
module.exports = {
/**
* Apply CSS styles to element.
* @alias module:CSSUtils.applyCSS
* @param {object} elem DOM element.
* @param {string} prop CSS property.
*/
applyCSS: function(elem, styles) {
for (var s in styles) {
elem.style[s] = styles[s];
}
},
/**
* Get the CSS style of a DOM element, after all styles are applied to the page.
* @alias module:CSSUtils.getStyle
* @param {object} elem DOM element.
* @param {string} prop CSS property.
* @return {string}
*/
getStyle: function (elem, prop) {
var value = "";
// normalize
prop = prop.toLowerCase();
if (window.getComputedStyle) { // W3C
value = window.getComputedStyle(elem, null).getPropertyValue(prop);
} else if (elem.currentStyle) { // IE: font-size -> fontSize
prop = this.dash2camel(prop);
value = elem.currentStyle[prop];
}
return value;
},
/**
* Set a CSS style for a given DOM element.
* @alias module:CSSUtils.setStyle
* @param {object} elem DOM element
* @param {string} prop CSS property
* @param {string} value CSS value
*/
setStyle: function (elem, prop, value) {
prop = prop.toLowerCase();
if (elem.style.setProperty) { // W3C & IE >= 9
// using "important" instead of null will override user-defined rules
elem.style.setProperty(prop, value, "important");
} else if (style.setAttribute) { // IE: font-size -> fontSize
prop = this.dash2camel(prop);
elem.style.setAttribute(prop, value);
}
},
/**
* Convert str with dashes to camelCaseNotation.
* @alias module:CSSUtils.dash2camel
* @param {string} str Input string.
* @return {string}
*/
dash2camel: function(str) {
return str.replace(/\-(\w)/g, function(strMatch, p1){
return p1.toUpperCase();
});
},
/**
* R,G,B array color to hexadecimal.
* @alias module:CSSUtils.rgb2hex
* @param {array} R,G,B values.
* @return {int}
*/
rgb2hex: function(rgb) {
var r = rgb[0].toString(16); if (r.length < 2) r += r;
var g = rgb[1].toString(16); if (g.length < 2) g += g;
var b = rgb[2].toString(16); if (b.length < 2) b += b;
return r+g+b;
},
/**
* R,G,B array color to decimal number.
* @alias module:CSSUtils.rgb2dec
* @param {array} R,G,B values.
* @return {int}
*/
rgb2dec: function(rgb) {
return parseInt(this.rgb2hex(rgb), 16);
},
/**
* Number to CSS color.
* @alias module:CSSUtils.cssColor
* @param {int} num Decimal number
* @return {string}
*/
cssColor: function(num) {
var str = Math.floor(num).toString(16);
// zeropad
for (var i = str.length; i < 6; ++i) {
str = "0" + str;
}
return "#" + str.toUpperCase();
},
/**
* Convert RGBA to RGB.
* @alias module:CSSUtils.rgba2rgb
* @param {int} num Decimal number
* @return {string}
*/
rgba2rgb: function(rgba) {
var col = [ rgba[0], rgba[1], rgba[2] ];
var alp = rgba[3], opa = 1 - rgba[3];
var matte = [255, 255, 255];
return [
alp * col[0] + opa * matte[0],
alp * col[1] + opa * matte[1],
alp * col[2] + opa * matte[2]
];
},
/**
* Compute difference between 2 RGB colors.
* @alias module:CSSUtils.rgbDiff
* @param {int} num Decimal number
* @return {string}
*/
rgbDiff: function(rgb1, rgb2) {
var diff = Math.abs(rgb1[0] - rgb2[0]) +
Math.abs(rgb1[1] - rgb2[1]) +
Math.abs(rgb1[2] - rgb2[2]);
return diff / (3*255);
},
// /**
// * Convert RGB to HSL.
// * @alias module:CSSUtils.rgb2hsl
// * @param {string} rgb RGB color
// * @return {string}
// */
// rgb2hsl: function(rgb) {
// var r = rgb[0]/255, g = rgb[1]/255, b = rgb[2]/255;
// var max = Math.max(r, g, b), min = Math.min(r, g, b);
// var h, s, l = (max + min) / 2;
// if (max == min) {
// h = s = 0; // achromatic
// } else {
// var d = max - min;
// s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
// switch(max){
// case r: h = (g - b) / d + (g < b ? 6 : 0); break;
// case g: h = (b - r) / d + 2; break;
// case b: h = (r - g) / d + 4; break;
// }
// h /= 6;
// }
// return [ Math.floor(h * 360), Math.floor(s * 100), Math.floor(l * 100) ];
// },
/**
* Compute color contrast.
* @alias module:CSSUtils.colorContrast
* @param {object} elem DOM element.
* @return {number}
*/
colorContrast: function(elem) {
var fgColor = this.parseColor( this.getStyle(elem, "color") )
, bgColor = this.parseColor( this.getStyle(elem, "background-color") )
, fgBright = this.brightness(fgColor)
, bgBright = this.brightness(bgColor)
// , diff = this.rgbDiff(fgColor, bgColor)
, diff = Math.abs(fgBright - bgBright)
;
return Number( diff.toFixed(2) );
},
/**
* Compute color brightness.
* @alias module:CSSUtils.brightness
* @param {string} rgb RGB color.
* @return {number}
*/
brightness: function(rgb) {
return ((rgb[0]*299) + (rgb[1]*587) + (rgb[2]*114)) / 1000;
},
/**
* Transform color to a 3 or 4 length tuple (array).
* @alias module:CSSUtils.colorTuple
* @param {string} color RGB color.
* @return {array}
*/
colorTuple: function(color) {
var tuple = [];
var fparen = color.indexOf('(');
var lparen = color.indexOf(')');
color = color.substring(fparen+1, lparen);
tuple = color.split(',');
for (var j = 0; j < tuple.length; ++j) {
tuple[j] = parseInt(tuple[j]);
}
return tuple;
},
/**
* Convert a color to an array of R,G,B values in [0, 255].
* @alias module:CSSUtils.parseColor
* @param {string} color Color definition: rgb(R,G,B) or rgba(R,G,B,A) or hsl(H,S,L) or hsl(H,S,L,A) or #RGB or # RRGGBB.
* @return {array}
*/
parseColor: function(color) {
var rgb = [];
// option 1: rgb(R,G,B) format; optionally rgba(R,G,B,A)
if (color[0] == 'r') {
rgb = this.colorTuple(color);
if (rgb.length > 3) rgb = this.rgba2rgb(rgb);
}
// option 2: hsl(H,S,L) format; optionally hsla(H,S,L,A)
else if (color[0] == 'h') {
var hsl = this.colorTuple(color);
rgb = hsl.length > 3 ? this.hsla2rgb(rgb) : this.hsl2rgb(rgb);
}
// option 3: #RRGGBB format
else if (color[0] == "#") {
// check also the shorthand notation (#F00 = #FF0000)
var start = 1;
var offset = color.length < 6 ? 1 : 2;
for (var i = 0, col = ""; i < 3; ++i) {
col = color.substr(start, offset);
if (offset == 1) col += col;
rgb[i] = parseInt(col,16);
start += offset;
}
}
// option 4: transparent
else if (color == "transparent") {
// Note: IE 7-8 supports transparent only for `background` and `border`. `color:transparent` is drawn black in IE.
rgb = [255, 255, 255];
}
// // option 5: string definition (requires colordef.js)
// else if (color in CSSColorStrings) {
// rgb = this.parseColor( CSSColorStrings[color] );
// }
// else ... bad color definition
return rgb;
},
/**
* Retrieve the parts of a dimension definition (e.g. "15px", "2.5em"...)
* @alias module:CSSUtils.parseDimension
* @param {string} dim Input dimension.
* @return {object} result
* @return {number} result.value
* @return {string} result.unit
*/
parseDimension: function(dim) {
var value = parseFloat(dim);
var parts = dim.split(value);
return { value:value, unit:parts[1] };
}
};
})('object' === typeof module ? module : {}, this);