Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Enhancements to PIE.Color: handle converting hsl and hsla color value…

…s 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)
  • Loading branch information...
commit 098df06541d22370a73447de99a3bdd2826d90c9 1 parent 28d18b5
Jason Johnston authored
Showing with 150 additions and 15 deletions.
  1. +92 −13 sources/Color.js
  2. +58 −2 tests/color-names.html
View
105 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;
},
/**
View
60 tests/color-names.html
@@ -4,6 +4,8 @@
<head>
<title>Tests for background gradients</title>
+ <script type="text/javascript" src="../build/PIE_uncompressed.js"></script>
+
<style type="text/css">
html { -pie-load-path: "../build"; }
@@ -16,17 +18,71 @@
border-radius: 10px;
border: 3px solid;
margin: 5px;
- behavior: url(../build/PIE.htc);
}
</style>
</head>
<body>
+ <div style="display: none; color: red;" id="currentColorTester">tester for currentColor</div>
+
<script type="text/javascript">
+ // Some simple unit tests of color parsing
+ var colorValueTests = {
+ 'aqua': '#0FF',
+ 'beige': '#F5F5DC',
+ '#123456': '#123456',
+ '#123': '#123',
+ 'rgb(0, 0, 255)': '#0000ff',
+ 'rgba(0, 0, 255, 0.5)': '#0000ff',
+ 'rgba(0, 0, 255, .5)': '#0000ff',
+ 'hsl(0, 100%, 50%)': '#ff0000',
+ 'hsla(0, 100%, 50%, 0.5)': '#ff0000',
+ 'hsla(0, 100%, 50%, .5)': '#ff0000',
+ 'currentColor': '#F00',
+ 'transparent': 'transparent'
+ },
+ hexValueTests = {
+ 'aqua': '#00FFFF',
+ 'beige': '#F5F5DC',
+ '#123456': '#123456',
+ '#123': '#112233',
+ 'rgb(0, 0, 255)': '#0000ff',
+ 'rgba(0, 0, 255, 0.5)': '#0000ff',
+ 'rgba(0, 0, 255, .5)': '#0000ff',
+ 'hsl(0, 100%, 50%)': '#ff0000',
+ 'hsla(0, 100%, 50%, 0.5)': '#ff0000',
+ 'hsla(0, 100%, 50%, .5)': '#ff0000',
+ 'currentColor': '#FF0000',
+ 'transparent': '#000000'
+ },
+ currentColorTester = document.getElementById('currentColorTester'),
+ failed = false,
+ c, val;
+ for (c in colorValueTests) {
+ val = PIE.getColor( c ).colorValue( currentColorTester );
+ if ( val !== colorValueTests[ c ] ) {
+ document.write('<p style="color:red">PIE.Color#colorValue() failed for "' + c + '": got "' + val + '", expected "' + colorValueTests[c] + '"</p>')
+ failed = true;
+ }
+ }
+ for (c in hexValueTests) {
+ val = PIE.getColor( c ).hexValue( currentColorTester );
+ if ( val !== hexValueTests[ c ] ) {
+ document.write('<p style="color:red">PIE.Color#hexValue() failed for "' + c + '": got "' + val + '", expected "' + hexValueTests[c] + '"</p>')
+ failed = true;
+ }
+ }
+ if (!failed) {
+ document.write('<p style="color:#090">Color parsing tests all passed</p>')
+ }
+
+
+ // Visual test of color names
var colors = ["aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige", "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown", "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue", "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod", "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen", "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen", "darkslateblue", "darkslategray", "darkturquoise", "darkviolet", "deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick", "floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite", "gold", "goldenrod", "gray", "green", "greenyellow", "honeydew", "hotpink", "indianred", "indigo", "ivory", "khaki", "lavender", "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral", "lightcyan", "lightgoldenrodyellow", "lightgreen", "lightgrey", "lightpink", "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta", "maroon", "mediumauqamarine", "mediumblue", "mediumorchid", "mediumpurple", "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise", "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin", "navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered", "orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred", "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue", "purple", "red", "rosybrown", "royalblue", "saddlebrown", "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue", "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan", "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white", "whitesmoke", "yellow", "yellowgreen"];
for( var i=0, len=colors.length; i < len; i++ ) {
- document.write('<div class="test" style="border-color:' + colors[i] + ';">' + colors[i] + '</div>');
+ document.write('<div class="test" id="test' + i + '" style="border-color:' + colors[i] + ';">' + colors[i] + '</div>');
+ PIE.attach( document.getElementById('test' + i) );
}
</script>
Please sign in to comment.
Something went wrong with that request. Please try again.