From 098df06541d22370a73447de99a3bdd2826d90c9 Mon Sep 17 00:00:00 2001 From: Jason Johnston Date: Thu, 9 Jun 2011 21:51:45 -0600 Subject: [PATCH] Enhancements to PIE.Color: handle converting hsl and hsla color values to equivalents recognizable by IE, and add a hexValue method which forces colors to 6-digit hex format (this is needed by the Glow filter as it only accepts full hex) --- sources/Color.js | 105 ++++++++++++++++++++++++++++++++++++----- tests/color-names.html | 60 ++++++++++++++++++++++- 2 files changed, 150 insertions(+), 15 deletions(-) diff --git a/sources/Color.js b/sources/Color.js index c3d55e7..454be91 100644 --- a/sources/Color.js +++ b/sources/Color.js @@ -5,6 +5,44 @@ * @param {string} val The raw CSS string value for the color */ PIE.Color = (function() { + + /* + * hsl2rgb from http://codingforums.com/showthread.php?t=11156 + * code by Jason Karl Davis (http://www.jasonkarldavis.com) + * swiped from cssSandpaper by Zoltan Hawryluk (http://www.useragentman.com/blog/csssandpaper-a-css3-javascript-library/) + * modified for formatting and size optimizations + */ + function hsl2rgb( h, s, l ) { + var m1, m2, r, g, b, + round = Math.round; + s /= 100; + l /= 100; + if ( !s ) { r = g = b = l * 255; } + else { + if ( l <= 0.5 ) { m2 = l * ( s + 1 ); } + else { m2 = l + s - l * s; } + m1 = l * 2 - m2; + h = ( h % 360 ) / 360; + r = hueToRgb( m1, m2, h + 1/3 ); + g = hueToRgb( m1, m2, h ); + b = hueToRgb( m1, m2, h - 1/3 ); + } + return { r: round( r ), g: round( g ), b: round( b ) }; + } + function hueToRgb( m1, m2, hue ) { + var v; + if ( hue < 0 ) { hue += 1; } + else if ( hue > 1 ) { hue -= 1; } + if ( 6 * hue < 1 ) { v = m1 + ( m2 - m1 ) * hue * 6; } + else if ( 2 * hue < 1 ) { v = m2; } + else if ( 3 * hue < 2 ) { v = m1 + ( m2 - m1 ) * ( 2/3 - hue ) * 6; } + else { v = m1; } + return 255 * v; + } + + + + var instances = {}; function Color( val ) { @@ -15,7 +53,8 @@ PIE.Color = (function() { * Regular expression for matching rgba colors and extracting their components * @type {RegExp} */ - Color.rgbaRE = /\s*rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d+|\d*\.\d+)\s*\)\s*/; + Color.rgbOrRgbaRE = /\s*rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(,\s*(\d+|\d*\.\d+))?\s*\)\s*/; + Color.hslOrHslaRE = /\s*hsla?\(\s*(\d*\.?\d+)\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*(,\s*(\d+|\d*\.\d+))?\s*\)\s*/; Color.names = { "aliceblue":"F0F8FF", "antiquewhite":"FAEBD7", "aqua":"0FF", @@ -74,32 +113,72 @@ PIE.Color = (function() { parse: function() { if( !this._color ) { var me = this, - v = me.val, - vLower, - m = v.match( Color.rgbaRE ); - if( m ) { - me._color = 'rgb(' + m[1] + ',' + m[2] + ',' + m[3] + ')'; - me._alpha = parseFloat( m[4] ); + color = me.val, + alpha, vLower, m, rgb; + + // RGB or RGBA colors + if( m = color.match( Color.rgbOrRgbaRE ) ) { + color = me.rgbToHex( +m[1], +m[2], +m[3] ); + alpha = ( 5 in m ) ? +m[5] : 1; + } + // HSL or HSLA colors + else if( m = color.match( Color.hslOrHslaRE ) ) { + rgb = hsl2rgb( m[1], m[2], m[3] ); + color = me.rgbToHex( rgb.r, rgb.g, rgb.b ); + alpha = ( 5 in m ) ? +m[5] : 1; } else { - if( ( vLower = v.toLowerCase() ) in Color.names ) { - v = '#' + Color.names[vLower]; + if( Color.names.hasOwnProperty( vLower = color.toLowerCase() ) ) { + color = '#' + Color.names[vLower]; } - me._color = v; - me._alpha = ( v === 'transparent' ? 0 : 1 ); + alpha = ( color === 'transparent' ? 0 : 1 ); } + me._color = color; + me._alpha = alpha; } }, + /** + * Converts RGB color channels to a hex value string + */ + rgbToHex: function( r, g, b ) { + return '#' + ( r < 16 ? '0' : '' ) + r.toString( 16 ) + + ( g < 16 ? '0' : '' ) + g.toString( 16 ) + + ( b < 16 ? '0' : '' ) + b.toString( 16 ); + }, + /** * Retrieve the value of the color in a format usable by IE natively. This will be the same as - * the raw input value, except for rgba values which will be converted to an rgb value. + * the raw input value, except for rgb(a) and hsl(a) values which will be converted to a hex value. * @param {Element} el The context element, used to get 'currentColor' keyword value. * @return {string} Color value */ colorValue: function( el ) { this.parse(); - return this._color === 'currentColor' ? el.currentStyle.color : this._color; + return this._color === 'currentColor' ? PIE.getColor( el.currentStyle.color ).colorValue( el ) : this._color; + }, + + /** + * Retrieve the value of the color in a normalized six-digit hex format. + * @param el + */ + hexValue: function( el ) { + var color = this.colorValue( el ); + // At this point the color should be either a 3- or 6-digit hex value, or the string "transparent". + + function ch( i ) { + return color.charAt( i ); + } + + // Fudge transparent to black - should be ignored anyway since its alpha will be 0 + if( color === 'transparent' ) { + color = '#000'; + } + // Expand 3-digit to 6-digit hex + if( ch(0) === '#' && color.length === 4 ) { + color = '#' + ch(1) + ch(1) + ch(2) + ch(2) + ch(3) + ch(3); + } + return color; }, /** diff --git a/tests/color-names.html b/tests/color-names.html index 8debd21..e27b803 100644 --- a/tests/color-names.html +++ b/tests/color-names.html @@ -4,6 +4,8 @@ Tests for background gradients + + + +