0

I was going to make a JSFiddle but it wasn't turning out right.

I have a table. When I want to hover/mouseover the table cells, I want to change the color of the table cell. I would like to do this by changing the opacity of the background color but this method is producing some odd behavior in IE8. I thought it might be due to the "hasLayout" issue I occasionally hear about but I can't seem to even set the hasLayout property (when I test with zoom:1 or position:relative I still get undefined for hasLayout).

I am using PHP to make this table and the colors are defined dynamically so I would like to avoid making a :hover class for each different color of cell. It would be nice if I could just alter each cell in the same way (lighten the color) on mouseover without having to actually print individual styles for each color used.

So - in IE8, my borders disappear. I have tried resetting the CSS after the opacity is rest but it's not working.

Does anyone know why this is happening, how I can fix it or an alternative that produces the same results?


This is on hover or mouseover for any browser... on hover for any browser

After hover/mouseover for IE8
after hover in in IE8

After hovering/mouseover'ing all over the table in IE8 after hovering all over the place in IE8

This is how the table appears in Chrome before and after any amount of hovering. noraml

CSS:

td.colors { 
   border:  1px solid black;  
   height:  4px; 
   padding: 0px; 
} 

td.colors_middle_row {   
   border-top:     0px; 
   border-right:   2px solid #000000;
   border-bottom:  0px;
   border-left:    2px solid #000000;
} 

td.colors_top_row {   
   border-top:     2px solid #000000;
   border-right:   2px solid #000000;
   border-bottom:  0px;
   border-left:    2px solid #000000;
} 

td.colors_bottom_row {  
   border-top:     0px;
   border-right:   2px solid #000000;
   border-bottom:  2px solid #000000; 
   border-left:    2px solid #000000;
} 

JS/JQuery:

$('td.colors').on('mouseover hover', function() { 
   $(this).css('opacity','0.3');
   $(this).css('filter','alpha(opacity=30)'); 

});

$('td.colors').on('mouseleave blur', function() { 
   $(this).css('opacity','1');
   $(this).css('filter','alpha(opacity=100)');  

   /*  --- just something I tried that didn't work ---
   if ($(this).hasClass('colors_middle_row')) 
   {
      $(this).css('border-top',    '0px'); 
      $(this).css('border-right',  '2px solid #000000'); 
      $(this).css('border-bottom', '0px'); 
      $(this).css('border-left',   '2px solid #000000');  
   } 

   else if ($(this).hasClass('colors_top_row')) 
   {
      $(this).css('border-top',    '2px solid #000000'); 
      $(this).css('border-right',  '2px solid #000000'); 
      $(this).css('border-bottom', '0px'); 
      $(this).css('border-left',   '2px solid #000000');   
   }

   else if ($(this).hasClass('colors_bottom_row')) 
   {
      $(this).css('border-top',    '0px'); 
      $(this).css('border-right',  '2px solid #000000'); 
      $(this).css('border-bottom', '2px solid #000000'); 
      $(this).css('border-left',   '2px solid #000000');   
   }
   */
});

And the HTML for the TD looks like this:

<td style="width: 12.5%; background-color: rgb(132, 245, 118); opacity: 1;" class="colors colors_middle_row" title="WED @ 8:00">   </td>

I'm not going to post any PHP because I don't think it's relevant at all... but remember, the way the table is built in PHP is the reason I do not want to use the :hover class and would prefer a method of changing the colors to the same degree for hover/mouseover. The only alternative I can think of is to maybe mess with the hex color code and add a particular number to each RGB or something... I don't know. I need the borders to stay. Here's something else that's odd - in IE, after the borders disappear, if you mouseover that same cell, the borders appear for the mouseover but disappear again after the mouseleaves.

It's like the opacity is covering the borders but I don't know how to correct it. I have tried setting it to .99 / 99 instead of 1 / 100 (and a few other values) but it still didn't do what I wanted it to...



This works in IE8 and Chrome. Basically... I used the method provided below and decided to just store the values in an object/array. I am using 2 arrays (for normal color to hover and then hover to normal color) because I was having some issues with reliably looking up an array index by value in IE8. I made some assumptions with the color changing in the code.

var colors_array = new Object(); 
var shade_colors_array = new Object(); 

$('td.colors').on('mouseover hover', function() {    
   var color = $(this).css('background-color');   
   if (color.charAt(0) != '#') color = rgb2hex(color);  

   if (typeof  colors_array == 'undefined' || typeof colors_array[color] == 'undefined' ) { 
      var sc = shadeColor(color, 15);    
      shade_colors_array[sc] = color; 
      colors_array[color] = sc;
   } 
   var shade_color = colors_array[color];   

   $(this).css('background-color',  shade_color);  
});

$('td.colors').on('mouseleave blur', function() {  
   var shade_color = $(this).css('background-color');    
   if (shade_color.charAt(0) != '#') shade_color = rgb2hex(shade_color);  

   var color = shade_colors_array[shade_color]; 
   $(this).css('background-color',  color);   
});

function shadeColor(color, percent) {    
   var num = parseInt(color.slice(1),16),  
         amt = Math.round(2.55 * percent),  
         R = (num >> 16) + amt, 
         B = (num >> 8 & 0x00FF) + amt, 
         G = (num & 0x0000FF) + amt; 

   return "#" + (0x1000000 + (R<255?R<1?0:R:255)*0x10000 + (B<255?B<1?0:B:255)*0x100 + (G<255?G<1?0:G:255)).toString(16).slice(1);
}

function rgb2hex(rgb) {   
   rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/); 
   function hex(x) {
      // parseInt(x) was changed to parseInt(x,10) because 
      // i was occasionally getting unexepcted results in IE 
      return ("0" + parseInt(x,10).toString(16)).slice(-2);
   } 
   return '#' + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}

I have worked on this long enough that "color" no longer looks like a word to me

gloomy.penguin
  • 5,833
  • 6
  • 33
  • 59

2 Answers2

1

I think what you've got here is basically a bug in IE's filter styles.

Nothing new there, then.

You could try to work-around it by adding an additional layer of markup inside the <td> and styling that instead. I expect that ought to work.

Alternatively, you could try using a library like CSS3Pie, which will give you access to some additional CSS3 features that aren't normally available in old IE versions, like rgba colours, which is a much nicer way of adding transparency to your background colours than opacity and waaay better than using IE's clunky filter styles.

Hope that helps.

Spudley
  • 166,037
  • 39
  • 233
  • 307
  • It's new to me lol.... I'm not really a front end person. What do you mean by adding an additional layer of markup in the TD? Put a div in there or something? I tried to do that but even with height and width at 100%, I still got some weird gaps. – gloomy.penguin Jul 25 '13 at 16:41
  • re the extra layer - yep, that's exactly what I meant. if you tried that already and it didn't work out, then fair enough. CSS3Pie can be found at http://www.css3pie.com/ – Spudley Jul 25 '13 at 19:12
0

Since you're already using jQuery to handle the hovering, I would probably go with changing the colour to a calculated lighter version, as you mentioned:

The only alternative I can think of is to maybe mess with the hex color code and add a particular number to each RGB or something

Using one short function found here, and another found here, here's a quick demo:

http://jsfiddle.net/thirtydot/dzRnF/1/

$('td').on('mouseenter', function() {
    $(this).data('originalColor', $(this).css('background-color'));
    $(this).css('background-color', shadeColor2(rgb2hex($(this).css('background-color')), 0.6));
}).on('mouseleave', function() { 
    $(this).css('background-color', $(this).data('originalColor'));
});

function shadeColor2(color, percent) {   
    var f=parseInt(color.slice(1),16),t=percent<0?0:255,p=percent<0?percent*-1:percent,R=f>>16,G=f>>8&0x00FF,B=f&0x0000FF;
    return "#"+(0x1000000+(Math.round((t-R)*p)+R)*0x10000+(Math.round((t-G)*p)+G)*0x100+(Math.round((t-B)*p)+B)).toString(16).slice(1);
}
function rgb2hex(rgb) {
    rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
    function hex(x) {
        return ("0" + parseInt(x).toString(16)).slice(-2);
    }
    return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
Community
  • 1
  • 1
thirtydot
  • 224,678
  • 48
  • 389
  • 349
  • I need to try and avoid HTML5 so I think the data property is out... but yeah, I can calculate the original color from the `hover` color, too. I actually tried that snippet of code you posted and it wasn't giving me the proper hex numbers... 00FF00 would turn into 02550 for some reason. Maybe I did something, wrong, though. – gloomy.penguin Jul 25 '13 at 16:07
  • Using `.data()` was merely a demo, you don't have to store the original colour like that. Regardless, your comment does not really make sense. You can use `.data()` whatever doctype you have or whatever version of HTML you want to use. jQuery handles `.data()` internally. Did you use an `rgb2hex` or similar function in your attempt? Colours are returned as rgb, perhaps that's where you went wrong. – thirtydot Jul 25 '13 at 16:11
  • I tested those shadeColor and rgb2hex functions by doing this: `$('td.colors').on('mouseover hover', function() { $(this).css('background-color', shadeColor(rgb2hex($(this).css('background-color')), 60));});` and in Chrome, it turned the cells white and in IE8, there was no color change for hover but it still removed the borders. – gloomy.penguin Jul 25 '13 at 16:15
  • Maybe I should just print the styles from PHP (but it's going to be a hassle to actually have to define all those color changes, this is a very simple example of what is needed) or... maybe... I should try and the calculated color change to work. – gloomy.penguin Jul 25 '13 at 16:16
  • 1
    IE8 seems to return hex colours instead of rgb colours. Check to see if `$(this).css('background-color')` starts with a `#`, if so you don't need to pass it to `rgb2hex`. Or, modify `rgb2hex` to check if the colour passed in is already hex, if so just return it. – thirtydot Jul 25 '13 at 16:21
  • Here is a version of my demo that works in IE8: http://jsfiddle.net/pP6q4/ (http://jsfiddle.net/pP6q4/show/ to preview in IE8 if needed). Good luck... – thirtydot Jul 25 '13 at 16:43
  • ___to make those functions work___, i had to pass the base parameter to the `parseInt` function...!! `parseInt(num, 10);` – gloomy.penguin Dec 06 '13 at 21:13
  • shadeColor's second parameter is a percentage of white, not the color. Therefore, 60% = 153+R, 153+G, 153+B... 153 is added to each color, capped at 255. Try a lower percentage, 60 is alot. Also, this version of shadeColor expects a string exactly 7 characters long, starting with a #, like "#0a6bf1". It doesn't check for bad input. This function is converting hex string to rgb, then adding an incremental amount, and convert back to hex string. If you already got RGB, it could easily be optimized; removing all these double/triple conversions and rgb2hex. – Pimp Trizkit Feb 04 '14 at 01:13
  • 1
    I have just recently changed my `shadeColor` function to be more accurate. Try `shadeColor2` here: http://stackoverflow.com/questions/5560248/programmatically-lighten-or-darken-a-hex-color/13542669#13542669 – Pimp Trizkit Feb 04 '14 at 08:47