Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chrome 20.x issue (bug?) with classes applied/removed at intervals via jQuery

Here's a fun one for those of you who love to bang your heads against the computer keyboard.

Site: http://blduke.com.php53-27.dfw1-2.websitetestlink.com

Fun little jQuery thing going on right below the navigation here. It's actually a radial menu (plugin). The plugin includes functions that will trigger the rotation clockwise and counterclockwise, and by default the radial menu isn't shown. So I've got the code to initialize the radial menu, the code to show it immediately, and code to trigger the next rotation at intervals. Finally I've used the plugin's API to hook into the afterAnimation option to make sure that an "active" class is applied to the "active" menu item - I'm going to use it to do some fun CSS stuff, rotate some to the right of this graphic, etc. You can see that the "active" class on the list items right now just adds a red background.

This works absolutely perfectly in IE8+, Firefox, Safari, and versions 17.0-19.0 of Chrome. In Chrome 20.x it breaks in a weird way.

The active class still swaps to the appropriate list item when it should, but the browser is doing something weird, like delaying the rendering of the active class on the new item, or skipping it entirely at some points, or showing it on two items (the item it was last on, and the next one)

No script errors, and I'm baffled, as is the plugin dev. Anyone have any ideas, insight?

My Code:

jQuery(document).ready(function($) {
    $("#radial_container").radmenu({
        listClass: 'list', // the list class to look within for items
        itemClass: 'item', // the items - NOTE: the HTML inside the item is copied     into the menu item
        radius: 130, // radius in pixels
        animSpeed:400, // animation speed in millis
        centerX: 0, // the center x axis offset
        centerY: 0, // the center y axis offset
        angleOffset: 30, // in degrees,
        afterAnimation: function($m){ // after the animation triggers, grab the     "active" menu item (object) to recieve the "active" class
            $("#radial_container").radmenu(2); 
        }
   }).radmenu("show"); // Show the menu straight off, we don't need to trigger with a click

    setInterval(function() { // automatically rotate the menu at intervals
        $('#radial_container').radmenu('next');
    }, 4000);

});
like image 516
rentageekmom Avatar asked Jul 15 '12 00:07

rentageekmom


2 Answers

Why do you need a plugin for that? You are just animating top and left of three simple elements. Why not write it manually. It won't be longer that the sample code you provided for sure.

function setPosition(element, position) {
   var placements = [[100,100], [200, 200], [0, 200]] ; //for instance

   $(element).stop().animate({left: placements[position][0]+ 'px', top: placements[position][1] + 'px'});

   if (position == 0) { $(element).addClass('activeMenuItem');}
}

var state = 0;

function rotateMenu(direction) {
    state += direction;
    if (state < 0) state = 2;
    if (state > 2) state = 0;

    $('.menuItem').removeClass('activeMenuItem');

    setPosition('#item0', state  % 3);
    setPosition('#item1', (state + 1) % 3);
    setPosition('#item2', (state + 2) % 3);
}

That's it. rotateMenu(1) rotates to one direction while rotateMenu(-1) rotates it another direction.

Your menu items will have class="menuItem" and id="item".

Here is jsFiddle for a little demo.

like image 62
darksky Avatar answered Oct 10 '22 23:10

darksky


I edited your code slightly while testing locally:

setInterval(function() { // automatically rotate the menu at intervals
    $('.radial_div div').removeClass('active'); //add this line
    $('#radial_container').radmenu('next');
}, 4000);

Tested on Chrome 20 and FF16a.

This will ensure that all divs lose the active class when you call the rotation plugin, and it is properly added back to the top item when the afterAnimation function runs.


Then new issue seems quite hard to debug, as I can't get it to happen constantly. However, try this:

afterAnimation: function($m){ // after the animation triggers, grab the "active" menu item (object) to recieve the "active" class
    setTimeout(function() {
        $("#radial_container").radmenu(2);
    }, 0); 
}

This will ensure that the radmenu function is only called after the current function stack has finished processing, I watched it for a couple minutes and it didn't bug even once.

Also, if you want to start the top item with the active class already, you can just add:

$('.radial_div div:nth-child(3)').addClass('active');

Anywhere inside the .ready function.

like image 28
Fabrício Matté Avatar answered Oct 10 '22 23:10

Fabrício Matté