Search code examples
jqueryinternet-explorer-8css-float

IE8, jquery carousel. changing item width with javascript


I ran into a problem when making a carousel with jQuery. It works just fine with Chrome, FF, IE7 and IE9. IE8 is the only one with problems.

The carousel has items floating side by side, and when an item is clicked, its width is extended to show the content. And if clicked again, it retracts back to its original width.

The problem is that when I click one of the items (item1) it doesn't work. And when I take a look at it with IE's dev tools, I can clearly see that it is in fact open. It just doesn't render the change. Then if I click the element right of the item1 (item2), item1 jumps to the extented width without animating. If I click item1 again, it retracts back to original width and this is where the problem occurs. Item2 is still far to the right when it should be right next to item1.

I replicated this problem with a much simpler example than my original project, since it's quite big. Full html/css/js source pasted lower.

How to replicate (test with other browsers first to see how it is supposed to work):

  1. scroll the pane to the right so that you can see the third (yellow) and the fourth (gray) element
  2. click the yellow element
  3. click the gray element
  4. click the yellow element again

Now you should see black (the color of the items' parent element) on the right side of the yellow element. And if you scroll to the right, you can see the gray element there.

And my question is, has anyone had this problem before and is there a solution for it?

Source:

<!DOCTYPE html> 
<html> 
<head><title>ie testing</title> 
 
<style type="text/css"> 
    
    #test {height: 150px; background-color: black; overflow:auto;position:relative;width:700px;border: 1px solid black;}
    #pane {width: 5000px;position:relative;}
    .item {width: 240px; height: 150px; float:left; overflow: hidden; position:relative;}
    #item1 {background-color: red;}
    #item2 {background-color: blue;}
    #item3 {background-color: yellow;}
    #item4 {background-color: gray;}
    #item5 {background-color: pink;}
    #item6 {background-color: white;}
    .item-content { height: 150px; width: 2px;} /* this didn't seem to affect anything */
 
</style> 
 
</head> 
<body> 
 
  <div id="test"> 
    <div id="pane"> 
        <div id="item1" class="item"><div class="item-content"> </div></div> 
        <div id="item2" class="item"><div class="item-content"> </div></div> 
        <div id="item3" class="item"><div class="item-content"> </div></div> 
        <div id="item4" class="item"><div class="item-content"> </div></div> 
        <div id="item5" class="item"><div class="item-content"> </div></div> 
        <div id="item6" class="item"><div class="item-content"> </div></div> 
        <div style="clear:both; float:none;"> </div> 
    </div> 
  </div> 
 
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> 
<script type="text/javascript"> 
    t = $("#test");
    $pane = $("#pane");
    $items = $(".item", $pane);
    startw = $($items[0]).width();
 
    $(".item", $pane).click(function() {
        $t = $(this);
        if ($t.width() == startw) {
            $t.animate({width:700}, 200);
        } else {
            $t.animate({width:startw}, 200);
        }
    });
 
    asd1 = $("#item1");
    asd2 = $("#item2");
    asd3 = $("#item3");
    asd4 = $("#item4");
    asd5 = $("#item5");
    asd6 = $("#item6");
    
</script> 
</body> 
</html> 

Solution

  • Some kind of solution found by deadeye536 at facepunch.com.

    Looks like IE8 is failing to redraw.

    This is a very ugly solution, but it's the only one I could come up with.

    $(".item", $pane).click(function() {
        $t = $(this);
        if ($t.width() == startw) {
            $t.animate({width:700}, 200);
        } else {
            $t.animate({width:startw}, 200);
        }
    window.setTimeout(function() {
        if ($.browser.msie&&$.browser.version.slice(0,1)=="8") {
            $('.item').each(function() {
                this.style.cssText = this.style.cssText;
            });
        }
    }, 205);
    });
    

    So it basically resets the items' CSS. It still doesn't look perfect, but I can live with that. At least it works now.