chain effects in jQuery
I'm coding a website that has a menu with this markup:
<div id="grafico-wrapper">
<h2>Gráfico</h2>
<ul id="grafico-categories" class="categories-menu">
<li><a href="#" rel="cat1">Category1</a></li>
<li><a href="#" rel="cat2">Category2</a></li>
<li><a href="#" rel="cat3">Category3</a></li>
</ul>
<ul id="grafico-projects" class="projects-menu">
<li><a href="#" class="slider-link" rel="cat2,cat1">Project1</a></li>
<li><a href="#" class="slider-link" rel="cat2,cat1">Project2</a></li>
<li><a href="#" class="slider-link" rel="cat1">Project3</a></li>
<li><a href="#" class="slider-link" rel="cat2">Project4</a></li>
<li><a href="#" class="slider-link" rel="cat1,cat3">Project5</a></li>
<li><a href="#" class="slider-link" rel="cat1">Project6</a></li>
<li><a href="#" class="slider-link" rel="cat3">Project7</a></li>
</ul>
</div>
<div id="producto-wrapper">
<h2>Producto</h2>
<ul id="producto-categories" class="categories-menu">
<li><a href="#" rel="cat1">Category1</a></li>
<li><a href="#" rel="cat2">Category2</a></li>
<li><a href="#" rel="cat3">Category3</a></li>
</ul>
<ul id="producto-projects" class="projects-menu">
<li><a href="#" class="slider-link" rel="cat2,cat1">Project1</a></li>
<li><a href="#" class="slider-link" rel="cat1,cat3">Project2</a></li>
<li><a href="#" class="slider-link" rel="cat1">Project3</a></li>
<li><a href="#" class="slider-link" rel="cat2,cat3">Project4</a></li>
<li><a href="#" class="slider-link" rel="cat2">Project5</a></li>
<li><a href="#" class="slider-link" rel="cat3">Project6</a></li>
</ul>
</div>
Basically 2 main categories ("grafico" and "producto") each one with its sub-categories (ul.categories-menu
) and its projects (ul.projects-menu
).
Also each one of the sub-categories has a sort of "id" in the rel
attribute and each project has in the rel
attribute a comma-separated list of the sub-categories it belongs to.
So, what I want to achieve is that, when clicking a sub-category link, all the projects of this category c开发者_StackOverflow中文版ontaining in its rel
the sub-category rel
value get "highlighted" (turned into another color), but in a "cascade" fashion (from up to down, the projects will be changing their color), and when, after that, another sub-category link is clicked, all the projects will turn to the original color, and the highlight cascade starts again with the projects belonging to the new clicked sub-category.
I'm also using the xcolor plugin to allow the animate()
function to do a smooth change of color for the highlights.
This is my (simplified) code so far:
highlight: function(elem) {
//clear previous highlights
this.clearHighlight();
elem = $(elem);
var rel = elem.attr('rel');
var highlight_color = '#6666F0';
var highlightSpeed = 400;
var highlightDelay = 100;
//we highlight the sub-category element
elem.animate({color: highlight_color}, highlightSpeed).addClass('highlighted');
//we find the projects matching the rel attribute and we highlight them
elem.parents('ul.categories-menu')
.nextAll('ul.projects-menu')
.find('a[rel*=' + rel + ']')
.each(function(i, elem) {
$(elem).delay(i * highlightDelay).animate({color: highlight_color}, highlightSpeed).addClass('highlighted');
});
},
clearHighlight: function() {
var defColor = '#BABABA';
var highlightSpeed = 400;
$('#menu').animate({color: defColor}, highlightSpeed).removeClass('highlighted');
}
This code works quite well, but the "cascade" effect is not totally working, for example: when projects 1, 3, 4 and 6 are highlighted (first cascade works nice) and then you click another sub-category that should highlight projects 1, 4, 5 and 6 (note 1 and 4 are common),
- what I want is: all projects are set back to their default color, and then projects 1, 4, 5 and 6 are highlighted one after the other with the little delay
- what I get is: all projects are set back to their default color, and then projects 5, 6, 1 and 4 are highlighted one after the other with the little delay (1 and 4 are highlighted later because they first take some time getting back to the old state)
I hope I explained my problem ok, can someone point me in the right direction to solve this little issue?
Thank you
In every animation in jQuery you can specify a success handler.
Seems to me you need to wait for 1 & 4 to be reset before triggering the new animation, you can do this through the success handler of the reset-animation for 1 & 4. This will give a delay for starting the new animation tho, and that can become annoying for the user since the interface will feel laggy.
A better way would probably be to animate 1 & 4 directly from whatever color they have to the new one, instead of resetting them first, ie. only reset 3 & 6 since they don't need to animate again right away.
You could also only animate the reset of 3 & 6, and the directly reset 1 & 4 so they are ready to animate to the new color right away - since they will be animating it might not matter if the reset is animated, but that is a ui-design decision.
Update:
In the case where you have multiple animations running (which you should try to avoid) and only wish to start the new set of animations when they all are finished, just keep count on what is running and what isn't.
You can do this multiple ways:
keep count manually: increase a counter everytime you start an animation and decrease it everytime you end one - in the successhandler that decreases the count check for zero count and start the new animations. CaveAt: there is a possible racecondition here, but that can be handled with a little care :)
poll the jQuery effects queue to see if animations are still running - this has a certain overhead that can make your animations laggy if you don't take care (but then all animations are doomed to be slow and laggy if you don't take care - multiple parallel running animation are generally a bad idea for performance)
精彩评论