smoothGallery: IE Issues with Multiple Galleries on a Page
update: The true source of this problem has been found and explained here. So I’d ignore my hack. :)
disclaimer: I’m no JavaScript guru, so be gentle if you find some fatal flaws in my code… And I’m sorry there’s a lot of setup to the code solution, but everything is related, I promise.
Today has been One Of Those Days as a web programmer: debugging for Internet Explorer. Oh, OH, what a joy. To make matters worse it hasn’t just been a CSS bug, but an issue with the smoothGallery extension of the mootools JavaScript framework. As the disclaimer above emphasises, JS is not my bag, baby, so it’s been a particularly onerous struggle. Still, I may have come out victorious…
Problem #1
The smoothGallery extension is a fantastic use of mootools to create beautiful, elegant photo slideshows on a website. It’s possibilities and features are nearly endless, and customizing it to your visual tastes is as easy as a few lines of CSS. Genius.
For a project I’m working on, we wanted to place multiple slideshows on the same page. Not a problem I say; big problem says IE. As it turns out, IE (6 & 7) will only display the final slideshow on your page. This behaviour has been documented by a few community users on the smoothgallery forums. What makes matters more frustrating is that if you visit the page with multiple galleries, visit another page, and then navigate back (using your browser’s back button) to the multi-gallery page, they all display fine.
One member on the forum thread mentioned above was able to debug it enough to determine that the gallery objects were not successfully calling their respective startSlideShow() methods. His solution was to build a “wait” function to load his second gallery after a certain delay. This was fine in theory, but I was dealing with any number of galleries on a page, and didn’t want to code a series of “wait” functions for each gallery.
I continued to scour the internets, but came up dry. After a while, I gave up and moved on.
Problem #2 (not really a problem)
What documentation exists for smoothGallery always illustrates passing an element by ID to create a new smoothGallery. However I’m putting together a Wordpress blog installation, and could potentially have a smoothGallery embedded in every post, and thought the idea of writing a script to parse each post and generate dynamic JavaScript just to create each gallery seemed a bit overkill. Similarly, forcing the Wordpress blogger to embed delicate JavaScript into the post body seemed full of flaws.
What I really wanted was to create a smoothGallery instance for any containing element of a specific class. mootools can easily retrieve a number of DOM elements by class value, and can also iterate through said object with it’s custom $each function.
Solution: Killing Two Birds With One Stone
So here I am, hell-bent on iterating through a bunch of DOM elements, creating smoothGalleries on the fly, so it seemed the perfect opportunity to also iterate through said galleries and force a call to their startSlideShow() methods. Could it possibly work?
What follows is the complete code that will:
- iterate through the DOM, creating smoothGalleries based on element & class value criteria;
- store each smoothGallery instance in an array (only if we’re in IE);
-
loop through the array of smoothGallery instances, calling
startSlideShow()each time (again, only if we’re in IE).<script type=”text/javascript”>
var allGalleries = []; function startGalleries() { $each($ES('div.smoothGallery'), function(galleryElement, index) { aGallery = new gallery(galleryElement, { // your options here }); if(window.ie) { allGalleries.push(aGallery); }; }); if(window.ie) { var delayFor = 0; $each(allGalleries, function(ieElement, index) { ieElement.startSlideShow.delay(delayFor, ieElement); delayFor = delayFor + 500; }); }; }; window.addEvent('domready', startGalleries); </script>
Code Explaination
It’d be a bit tedious to go through everything, so I’ll highlight the goodies:
var allGalleries = [];-
This creates an empty array that may old our gallery instances if we’re in IE
$each($ES('div.smoothGallery'), function(galleryElement, index) {...}-
Here we use mootools’ $each function to iterate through a collection of DOM elements that match the ‘div.smoothGallery’ target. This takes each element in turn, and passes it as
galleryElementto the function we’re creating. if(window.ie) { allGalleries.push(aGallery); };-
This basically says, “if we’re in IE, add the new gallery instance to our
allGalleriesarray. if(window.ie) {...}-
This begins the real “hack”. Again, if we’re in IE, step into this block of code and do the following:
-
1-Start a delay of 0 seconds
-
2-Using
$eachagain, iterate through ourallGalleriesarray -
3-Force a call to
gallery:startSlideShow(), using the mootools delay function that is available to any other framework function. -
4-Add 500 miliseconds to our delay before looping again (this should stagger the
gallery:startSlideShow()calls)
Further Thoughts
While this has seemed to work for me, I’ve also looked into moving the last chunk of code into it’s own function, and rather than calling it when the DOM is ready (window.addEvent('domready', functionName)), to call it once the whole page has loaded (window.addEvent('load', functionName)). My fear with this approach of course is that some element on the page fails to load for some reason, and the function never gets called. I’d like to hear from others whether one way worked and another didn’t.
This hasn’t been strongly tested, but will in the coming weeks; this code solution is being used on a Wordpress installation that will soon get tons of posts on a daily basis. There will be a section of the site dedicated to only reading blog posts that contain image galleries. So this will soon be put through the ringer.
Looking forward to feedback, suggestions, improvements.