I thought a nice sliding accordion type menu would be nice to use on one of my sites. So I decided to use jQuery seeing as I think jQuery is rather kewl. I checked out a jQuery demo I found (http://jquery.com/blog/2006/11/14/expandable-sidebar-menu-screencast/). I liked what I saw and liked how simple it was, so I decided to base my menu on it.
So here we go, I created the definition list in just the same way, created some CSS for it and pretty much copy n pasted the code, and I was away, I had a working menu.
There was a problem though, I wanted my menu to animate alot faster, I noticed that the opening element and the closing element didn’t open and close at the exact same speed so it had a strange shuddering effect. This was unacceptable. I then decided it would be in my better interest to create my own animation using the setInterval() function, which is what I did.
I still used jQuery for its browser abstraction and ease of use, I just didn’t use animate().
// Variables are declared here so they are available in the function and in document.ready
var fullWidth; // the full width the ’slides’ must be set to (When they are this width they are fully open)
var closedPage; // the slide that is currently close and is going to be opened
var openPage; // the slide that is currently opened and is going to be closed
var int;
var running = 0;
var step = 35; // the amount of pixels to increase or decrease the width of the slides by every milisecond
var fstep;
function slide()
{
// If the width of the slide that is busying opening + the step amount is larger then the full width
// find the difference between the opening page width and the full width and then add that to the opening page width so it equals the full width
if ( (closedPage.width() + fstep) > fullWidth ) // Makes sure the slides width always ends at the exact value of fullWidth
{
diff = fullWidth – closedPage.width();
openPage.css(‘width’, openPage.width()-diff+’px’);
closedPage.css(‘width’, closedPage.width()+diff+’px’);
}
else
{
// The slide that is opening + the step is not larger then the full width so continue adding the step as usual
openPage.css(‘width’, openPage.width()-fstep+’px’);
closedPage.css(‘width’, closedPage.width()+fstep+’px’);
}
// If the opening slides width is larger or equal to the full width, this means the slide is now fully open and the other slide is full closed
// So clear the interval and set running to 0 so the whole process can start again
if (closedPage.width() >= fullWidth)
{
int = clearInterval(int);
running = 0
}
}
$(document).ready(function() {
// Width needs to be calculated depending on the number of children items, I use this code in a CMS solution so the ‘Slides’ are added dynamicly
// and can vary in number
fullWidth = Math.round($(‘.slide-tabs’).width() – ( ($(‘.slide-tabs dt’).width()) * $(‘.slide-tabs dl’).children(‘dt’).length ));
fullWidth = fullWidth – 1; // This makes it all fit nicely
$(‘.slide-tabs dd .dddiv’).css(‘width’, fullWidth+’px’);
$(‘.slide-tabs dd:first’).css(‘width’, fullWidth+’px’); // First ‘Slide’ is open on when page is loaded
$(‘.slide-tabs dt’).bind(‘mouseover’, function() {
if (!running) // Waits for timer to exit before starting a new one
{
// The line below finds the open ‘Slide’ I want this code to be fast and efficient
// so I only want one slide to open and one to close.
openPage = $(‘.slide-tabs dl’).children(‘dd’).filter( function(i) { if ($(this).width() > 0) return 1; } );
closedPage = $(this).next();
fstep = step;
int = self.setInterval(’slide()’,1);
running = 1;
}
});
});