In the last week I decided to add some flair to my site, as I am spending a lot of time in various communities be they online, like StackOverflow, or offline, like InformationWorker - so I wanted to add flair for those communities to my website.
However the problem is that I’m in a lot of them and don’t want a page that just scrolls and scrolls so I decided to make a rotating flair block, i.e. it shows a piece of flair for a few seconds and then rotates to another one. Thankfully I already have jQuery setup on my site so this was fairly easy. One thing that caused some headache was getting away from the idea of having a loop, where I’d show one flair then wait then hide it and show the next one. This is a very bad idea because it means that it runs forever which is what I want - but not an endless loop because browsers will detect that and stop the script. Also from a performance point of view JavaScript in a loop tends to make a browser run slowly.
The solution is to use events and kick them off in a staggered fashion - thankfully JavaScript natively has a function for that: setTimeout which takes a string which it will execute and an integer which is the milliseconds delay to wait for. Then on it’s turn show it, wait (using setTimeout again), then hide it and lastly wait again to show it. Because that cycle is the same for each item the staggering ensures that they do not overlap and you get a nice, smooth flowing and non-loop loop :)
The technical bits
My HTML is made up of a lot of divs - each one for a flair:
<div class="flair-badge"> <div class="flair-title"> <a class="flair-title" href="http://www.stackoverflow.com">StackOverflow.com</a></div> <iframe src="http://stackoverflow.com/users/flair/53236.html" marginwidth="0" marginheight="0" frameborder="0" scrolling="no" width="210px" height="60px"></iframe> </div>
A dash of CSS for the styling, most importantly hiding all of them initially.
And the JavaScript:
var interval = 5000; $(document).ready(function() { var badges = $(".flair-badge").length; var counter = 0; for (var counter = 0; counter<badges; counter++) { setTimeout('BadgeRotate(' + counter + ',' + badges + ')', counter * interval); } }); function BadgeRotate(badge, badgeCount) { $(".flair-badge:nth(" + badge + ")").fadeIn("slow"); setTimeout('BadgeRotateEnd(' + badge + ',' + badgeCount + ')', interval); } function BadgeRotateEnd(badge, badgeCount) { $(".flair-badge:nth(" + badge + ")").hide(); setTimeout('BadgeRotate(' + badge + ',' + badgeCount + ')', (badgeCount * interval) - interval); }