Fade, slide, change. Content manipulation is a popular feature in modern website design.
In this series of tutorials, I have been describing how to code a relatively complex content fader and slider using the popular jQuery JavaScript library.
In "Part One" and "Part Two," I described how to prepare the HTML and CSS for the example slider/fader and described the inspiration for this series. "Part Three" focused on getting the actual images and text (which collectively I have been calling foils) moving. "Part Four" placed some foil (slide) navigation on page.
In this "Part 5" of the tutorial, I am going to continue working on the foil navigation. I will be picking up at step number six in the overall tutorial.
Step No. 6: Synchronize Foils and Foil Icons
I have four "foil icons" numbered one to four. Each icon represents a foil (large image) which is part of the main content fader. These foil icons are supposed to give a user an way to select a particular foil, disrupting — temporarily — the fading effect.
As a best practice, I should provide the user with some indication of which foil is associated with which numbered foil icon. An easy way to achieve this would be to change the background color of the icon associated with the current foil.
To make this happen, I must (1) identify the current foil, (2) associate the foils and icons, (3) add or remove a class that changed the icon background.
The first part of this task — identifying which foil is active — is more complex than you might think. My content fader is really a series of stacked div elements.
<div id="conceal"> <div id="foil-1"> <img src="foil-img-1.png" alt="Scarpa Boots are great for reaching high" /> <div class="foiled"><p>Suspendisse potenti. Donec volutpat libero a purus mattis laoreet. Donec sit amet justo orci. Aliquam erat volutpat. Sed interdum ligula eget felis laoreet consectetur. Nullam eu velit sit amet risus rhoncus tristique. Aliquam vel purus eget libero mollis tempor at in magna. Sed pulvinar scelerisque elit, ut eleifend tellus suscipit ornare. Aliquam eget lorem sodales est tristique eleifend. Aliquam mi mauris, semper id sagittis vel, semper vitae lacus. Duis quis orci est, et pharetra justo. Proin placerat vestibulum justo. Vestibulum fermentum metus et turpis adipiscing ac pharetra nibh tristique.</p></div> </div> <div id="foil-2"> <img src="foil-img-2.png" alt="High in your Skis" /> <div class="foiled"><p>Suspendisse potenti. Donec volutpat libero a purus mattis laoreet. Donec sit amet justo orci. Aliquam erat volutpat. Sed interdum ligula eget felis laoreet consectetur. Nullam eu velit sit amet risus rhoncus tristique. Aliquam vel purus eget libero mollis tempor at in magna. Sed pulvinar scelerisque elit, ut eleifend tellus suscipit ornare. Aliquam eget lorem sodales est tristique eleifend. Aliquam mi mauris, semper id sagittis vel, semper vitae lacus. Duis quis orci est, et pharetra justo. Proin placerat vestibulum justo. Vestibulum fermentum metus et turpis adipiscing ac pharetra nibh tristique.</p></div> </div> <div id="foil-3"> <img src="foil-img-3.png" alt="Arcteryz gear for real mountaineering" /> <div class="foiled"><p>Suspendisse potenti. Donec volutpat libero a purus mattis laoreet. Donec sit amet justo orci. Aliquam erat volutpat. Sed interdum ligula eget felis laoreet consectetur. Nullam eu velit sit amet risus rhoncus tristique. Aliquam vel purus eget libero mollis tempor at in magna. Sed pulvinar scelerisque elit, ut eleifend tellus suscipit ornare. Aliquam eget lorem sodales est tristique eleifend. Aliquam mi mauris, semper id sagittis vel, semper vitae lacus. Duis quis orci est, et pharetra justo. Proin placerat vestibulum justo. Vestibulum fermentum metus et turpis adipiscing ac pharetra nibh tristique.</p></div> </div> <div id="foil-4"> <img src="foil-img-4.png" alt="Hardcore mountaineering" /> <div class="foiled"><p>Suspendisse potenti. Donec volutpat libero a purus mattis laoreet. Donec sit amet justo orci. Aliquam erat volutpat. Sed interdum ligula eget felis laoreet consectetur. Nullam eu velit sit amet risus rhoncus tristique. Aliquam vel purus eget libero mollis tempor at in magna. Sed pulvinar scelerisque elit, ut eleifend tellus suscipit ornare. Aliquam eget lorem sodales est tristique eleifend. Aliquam mi mauris, semper id sagittis vel, semper vitae lacus. Duis quis orci est, et pharetra justo. Proin placerat vestibulum justo. Vestibulum fermentum metus et turpis adipiscing ac pharetra nibh tristique.</p></div> </div> </div><!--end conceal-->
When the page loads, all of the foils are visible, but the user only sees foil 4 because it is on top.
Next, foil 4 fades, revealing foil 3. Foil 3 fades, showing foil 2. Foil 2 fades to expose foil 1. Almost immediately, foil 2 starts to fade back in. This means that foil 1 is never actually animated. Why does this matter? jQuery has a great selector :animated with identifies elements currently undergoing a transition. So I can use it to help identify most of the cases, just not foil 1?
I start by creating the CSS class that will change the background color of the icon, once I have the JavaScript working.
#foil-nav .yellow-back {background: #fadf00; color: #000;}
Now when I add the class name yellow-back to one of the icons, its background will change from blue to yellow, and its text color will change from white to black.
I move on to the function fadeFoilss in order to start integrating my new foil icon background color flip. Here is how that function looks before I amend it.
function fadeFoilss(){
if(counter != 0){
$(foils[counter--] || []).delay(3600).fadeOut(1000, arguments.callee);
}
else{
newCount = 1;
showFoils();
}
}
I start at the top of the function by creating a variable that will represent the array of foil navigation icons. I make use of jQuery's powerful selector engine to get just the elements I need.
var icons = $('#foil-nav > li');
I add two lines to the function's if statement. The first calls another function, which I have yet to write, that will remove the class yellow-back, should it exist. The next set adds the class to the icon associated with the active foil.
removeIconClass();
$(icons[counter]).toggleClass('yellow-back');
Below are these new lines in context.
function fadeFoilss(){
var icons = $('#foil-nav > li');
if(counter != 0){
removeIconClass();
$(icons[counter]).toggleClass('yellow-back');
$(foils[counter--] || []).delay(3600).fadeOut(1000, arguments.callee);
}
Notice that I am using the same counter — here named "counter" — to associate the foils and foil icons. This works because my arrays are exactly the same length, thanks to the foilNavPut function I created in "Part Four."
function foilNavPut(){//places foil navigation on the page
var count = $('#conceal > div').length,
fnav = new Array;
$('#conceal').append('<ul id="foil-nav"></ul>');
if(count>0){
for(var i=0; i<count; i++){
//fnav.push(i);
fnav[i] = i+1;
$('#foil-nav').append('<li>' + fnav[i] +'</li>');
}
$('#foil-nav').bind('click', function(){foilNav(event)});
}
}
The jQuery method toggleClass adds the class name to the appropriate foil icon. I probably could have used addClass() here, too, and I may yet later when I refactor the code.
Next, I go ahead and write the removeClass function. Without this, it would be possible to have more than one icon with a yellow background at once.
function removeIconClass(){
var yellow = $('li.yellow-back');
if(yellow){
$(yellow[0]).removeClass('yellow-back')
}
}
This function uses jQuery to get an array of elements with the yellow-back class name. Since I am only applying this class to one element at a time, the array should consist of just one element. If it does exist, the function removes the class name.
So far, I have JavaScript that will add a class name to a foil icon, changing the icon's background color to yellow when the associated foil is in view. The code also removes the yellow background, when a foil fades out.
I still need to take care of the foil icon 1, which does not fade (is never animated). I handle this case in the else clause of the fadeFoils function.
else{
newCount = 1;
removeIconClass();
$(icons[0]).addClass('yellow-back');
timer = setTimeout('showFoils()', 2000);
}
If the counter is equal to zero, the fadeFoils function will move to this else clause. It first sets a new global variable, which is used to show foils in the next function down. Then it runs the removeIconClass function, turning all icon backgrounds to the default blue. Next, it adds the yellow-back class to icon 1, since this else clause is only run when icon 2 has just faded. I know this because when the counter variable is equal to 1, icon 2 is displayed. Finally, I add a timer that waits two additional seconds before starting to show the foils in order again. Without this extra time, icon 1 would change background colors too quickly — we're talking milleseconds — for the user to perceive the change.
I must now add a couple of lines to the showFoils function to again remove the yellow-back class name from the last icon in sequence and add it to the current icon in sequence.
removeIconClass();
$(icons[newCount-1]).toggleClass('yellow-back');
Here is the new code in the context of the function.
function showFoils(){
var icons = $('#foil-nav > li');
clearTimeout(timer);
if(newCount < foils.length){
removeIconClass();
$(icons[newCount-1]).toggleClass('yellow-back');
$(foils[newCount++] || []).delay(3600).fadeIn(1000, arguments.callee);
}
else{
counter = (foils.length - 1);
fadeFoils();
}
}
Now I almost have the effect I want, but one case still exists. When the page loads, none of the icons have yellow backgrounds. I can fix this by reordering the function calls in my document ready function. Below is the function before I make a change.
$(document).ready( function(){
foils = $('#conceal > div');
counter = (foils.length - 1);
fadeFoils();
foilNavPut();
});
And here it is after I made the change.
$(document).ready( function(){
foils = $('#conceal > div');
counter = (foils.length - 1);
foilNavPut();
fadeFoils();
});
In the new order of things, foilNavPut(), which creates the icons, runs before fadeFoils() so that the icons exist and, therefore, icon 4 can turn yellow.
Summing Up
In this "Part 5" of the series, I described how to synchronize icons and foils so that the icons indicate which foil is in view. I am going to need to refactor these functions soon, but first, I am going to get the effect working. In the next section of the series, I will deal with what happens when a user clicks one of the icons.
Related Articles
- Using jQuery to Make Complex Content Manipulation Easy, Part Four
- Using jQuery to Make Complex Content Manipulation Easy, Part Three
- Using jQuery to Make Complex Content Manipulation Easy, Part Two
