I am trying to build a slideshow using the jQuery Cycle plugin that contains another level of nested slideshows within some of the top-level slides.
The main "container" slides slide horizontally, and then—for "container" slides that contain more than one image on the left-hand side—those images slide up vertically.
Sample here, because I imagine it's hard to visualize: http://dl.dropbox.com/u/2890872/js-test/index.html
You'll only get to the second top-level slide before it stops, even thought there are six top-level slides (which is my issue—the second slide only contains one left-hand inner image, which stops the script), but you can see what the intended transitions are and check out the entire code.
The problem is that not all of the secondary slideshows have more than one image, and jQuery Cycle terminates itself if there is one or less images in a slideshow. This termination also terminates the top-level slideshow, since it is stopped and started based on when the secondary slideshow ends. Since the secondary slideshow terminates due to only one "slide", then the next outer top-level slide never gets called. I'm not sure how to adapt the code to get around this.
The js:
<script type="text/javascript">
$(function(){
// init and stop the inner slideshows
var inners = $('.slide-up').cycle().cycle('stop');
var slideshow = $('#home-slides').cycle({
fx: 'scrollHorz',
speed: 300,
timeout: 0,
before: function() {
// stop all inner slideshows
inners.cycle('stop');
// start the new slide's slideshow
$(this).children().cycle({
fx: 'scrollUp',
timeout: 2000,
autostop: true,
end: function() {
// when inner slideshow ends, advance the outer slideshow
slideshow.cycle('next');
}
});
}
});
});
</script>
A sample of the html:
<div id="home-slides">
<div>
<div class="slide-up">
<img src="i/home/slideshow/1l-1.jpg" alt="" width="284" height="420" />
<img src="i/home/slideshow/1l-2.jpg" alt="" width="284" height="420" />
<img src="i/home/slideshow/1l-3.jpg" alt="" width="284" height="420" />
</div>
<img src="i/home/slideshow/1r.png" alt="" width="291" height="420" />
</div>
<div>
<div>
<img src="i/home/slideshow/2l-1.jpg" alt="" width="284" height="420" />
</div>
<img src="i/home/slideshow/2r.jpg" alt="" width="291" height="420" />
</div>
<div>
<div class="slide-up">
<img src="i/home/slideshow/3l-1.jpg" alt="" width="284" height="420" />
<img src="i/home/slideshow/3l-2.jpg" alt="" width="284" height="420" />
</div>
<img src="i/home/slideshow/3r.png" alt="" width="291" height="420" />
</div>
<div>
…additional slides…
</div>
</div>
The slideshow terminates at the second #home-slides > div because there is only one image. I've tried removing the nesting and the "slide-up" class from the slides with no inner-slideshow, but that doesn't help.
Again, full working version with all relevant code can be found here: http://dl.dropbox.com/u/2890872/js-test/index.html
----------- EDITED 4/10 - Minor Updates and possibly a lead ----------
I've edited the code here and on the example link just to add some details that elmininate the first thoughts for troubleshooting. Now, only the the slides with secondary slideshows use the class "slide-up".
- I've tried specifying the '.slide-up' class in the function for the "end" callback ('$(this).children('.slide-up').cycle
…'), which does prevent cycle from terminating for too few slides, but that only makes it terminate for unmatched elements!
The closest I've gotten is by adding a conditional check to the function in the end callback: (I'm using length to check the existence of a slide-up div. If there's a better way, let me know)
before: function() {
if ( $(this).children('.slide-up').length != 0 ) {
// stop all inner slideshows
inners.cycle('stop');
// start the new slide's slideshow
$(this).children('.slide-up').cycle({
fx: 'scrollUp',
timeout: 2000,
autostop: true,
end: function() {
// when inner slideshow ends, advance the outer slideshow
slideshow.cycle('next');
}
});
} else alert('NO INNER SLIDESHOW!');
This eliminates all errors and terminations directly from jQuery Cycle, but the main slideshow still stops at the slide without a secondary slideshow. I think need to put something in the "else" statement related to firing up "slideshow.cycle('next');", but I haven't figured out the proper syntax to get that to work.
----------- EDIT #2 4/10 - ----------
most recent working example: http://dl.dropbox.com/u/2890872/js-test/index2.html
Moving the before function into its own named function to keep things cleaner.
function onBefore(currSlideElement, nextSlideElement, options, forwardFlag) {
if ( $(this).children('.slide-up').length != 0 ) {
// stop all inner slideshows
//inners.cycle('stop');
// start the new slide's slideshow
$(this).children('.slide-up').cycle({
fx: 'scrollUp',
timeout: 2000,
autostop: true,
end: function() {
// when inner slideshow ends, advance the outer slideshow
slideshow.cycle('next');
}
});
}
// else null;
else $(this).parent().cycle({
end: function() { slideshow.cycle('next'); }
});
}
This (else statement) allows the slideshow to progress, but it doesn't preserve the original 'slideshow' options, and just starts playing the top-level slides with default out-of-the-box options (fades from one slide to the next, instead of sliding, stops playing secondary slides).
I don't understand: 1) How to preserve the options. (I thought that was why the var "slideshow" was created in the first place)
2) Why an else statement is even necessary—I don't understand why the outer slides are stopping at all when the conditional '.slide-up' statement isn't executed— I would think the outer slideshow would just continue as normal.
A facebook friend solved it! Thanks, facebook friend!
var slideshow = $('#home-slides').cycle({
fx: 'scrollHorz',
speed: 300,
timeout: 0,
before: function(curElement, nextElement, options, forwardFlag) {
if($(nextElement).children('.slide-up').length != 0) {
$(nextElement).children('.slide-up').cycle({
fx: 'scrollUp',
timeout: 2000,
autostop: true,
end: function() { slideshow.cycle('next'); }
});
}
else {
setTimeout(function(){ slideshow.cycle('next'); }, 2000);
}
}
});
Working example here: http://dl.dropbox.com/u/2890872/js-test/index3.html I need to study Cycle a bit more and the changes he's made to fully understand the role of 'nextElement' in this code, but it most certainly works!