tags:

views:

86

answers:

6

In the following markup, "image 3" would the only visible div if all .image divs were positioned absolutely and with no z-index. I could "reshuffle" the deck, so to speak, by adjusting the z-index of all elements, or I could reshuffle it by manually placing the last .image div before the first, making the sequence "image 3, image 1, image 2."

<div id="images">
  <div class="image">...image 1...</div>
  <div class="image">...image 2...</div>
  <div class="image">...image 3...</div>
</div>

Suppose I would like the elements to fade, one to the other, every few seconds. I'd like to start by showing "image 3," and have it fade out only to appear after "image 1" has been displayed. I can accomplish that by giving it a lower z-index than "image 1" has, or by manually moving it before "image 1" after it's completely faded out.

Problems with z-index...

My reservation with using the z-index route is the need to examine all of the .image divs just to find the div having the highest z-index, so I can fade it out. This would be much easier if I were manually moving them, I could merely ask for $("div.image:last"). Furthermore, I would have to re-write the z-indexes, setting "image 3" to z-index:0; after it's been displayed, and incrementing all others to i+1.

Problems with manually moving elements...

This seems really sloppy, but as pointed out in the previous paragraph it appears to be the easiest solution. I'm not sure what effect it would have on screen-readers and other tools that require solid markup to function properly.

Which of these two methods is best for a carousel-type script, and why? Or is there a third option I'm not considering?

A: 

Could you not just download and use one of the several jquery carousel plugins?

Paddy
-1. Definitely not a good answer to the question.
rahul
@Paddy: I could, but that's not very "educational." :)
Jonathan Sampson
Sorry 'bout that. Personally, I'm of the opinion that there's no need to reinvent the wheel if someone's already done it and made it available. Didn't realise you were trying to be edumecated :)
Paddy
A: 

I'm gonna have to agree with Steerpike...

Set them all to display:none; Then you can hide whichever image is set to :visible using jQuery, and get the next image and show it...

peirix
+2  A: 

To build on what peirix and Steerpike suggested. Add display:none to your image class and set your first div to display:block. You can then find the visible div with the :visible selector and cross-fade with the next div:

function rotate() {
    // fade out the current div
    var activeEl = $("#images div:visible");
    $(activeEl).fadeOut("slow");

    // fade in the next div in the loop
    if ($(activeEl).next().length) {
        $(activeEl).next().fadeIn("slow");
    } else {
        $($(activeEl).siblings()[0]).fadeIn("slow");
    }

    setTimeout(rotate, 1000);
}

$(document).ready(function() {
    rotate();
});
Chris Pebble
This is essentially what I ended up doing.
Jonathan Sampson
+2  A: 

If you fade one image out then fade the next in, the fades occur at the same time. I did this on http://broburysports.com/casino - click the tabs to see the result.

Here's my stripped-down code if it helps:

$("#casinoTabs li").click( function() {
 // get clicked tab
 var tab = $(this).attr("class");

 // make tab content active
 $("#casinoGames li").fadeOut("slow");
 $("#casinoGames li."+tab).fadeIn("slow");
});

Note: the HTML is two lists: one for the tabs (#casinoTabs) and one for the tab contents (#casinoGames).

DisgruntledGoat
A: 

I use a z-index solution that I found somewhere that basically uses 3 levels for the z-index: The lowest value for the images (80 for example), the highest value for the active image (100) and a middle value for the previous active image (90).

Keeping track of the active and the previous active image, applying the appropriate classes and playing with the visibility in jQuery, results in a simple and logical way to rotate the images.

Edit: Code

js

var slide_show_speed = 1000;
var slide_duration = 5000;
var slide_interval;

$(document).ready(function() {
    var $first = $('#slideshow img:first');
    $first.css({opacity: 0.0})
        .addClass('active')
        .animate({opacity: 1.0}, slide_show_speed);
});

$(window).load(function() {
    slide_interval = setInterval( "slideSwitch()", slide_duration );
});

function slideSwitch() {
    var $active = $('#slideshow img.active');

    var $next =  $active.next().length ? $active.next() : $('#slideshow img:first');

    $active.addClass('last-active');

    $next.css({opacity: 0.0})
        .addClass('active')
        .animate({opacity: 1.0}, slide_show_speed, function() {
            $active.removeClass('active last-active');
    });
}

css

#slideshow {
    width: 400px;
    height: 300px;
    position: relative;
}
#slideshow img {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 80;
    opacity: 0.0;
    border: none;
    /* ie bugs */
    -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
    filter: alpha(opacity=0);
}
    #slideshow img.active {
    z-index: 100;
    opacity: 1.0;
}
    #slideshow img.last-active {
    z-index: 90;
}
jeroen
A: 

Why not simply have two classes .currently_visible and .next_in_line and set the z-index of both of those?

.currently_visible, .next_in_line {
  display: block;
}

.currently_visible {
z-index: 100;
}
. next_in_line{
z-index: 1;
}

Then use jQuery:

Stealing Chris' code:

function rotate() {
    // fade out the current div
    var activeEl = $("#images div.currently_visible");
    $(activeEl).fadeOut("slow", function(activeEl) {
      $(activeEl).removeClass("currently_visible");
      if ($(activeEl).next().length) {
        var next_element = $(activeEl).next();
       } else {
         var next_element = $($(activeEl).siblings()[0]);
       }
      // Finds the new next_in_line element.
      if ($(activeEl).next().next().length) {
        var following_element = $(activeEl).next().next();
       } else {
         var following_element = $($(activeEl).siblings()[1]);
       }
        $(next_element).removeClass("next_in_line");
        $(next_element).addClass("currently_visible);
        $(following_element).addClass("next_in_line);
    });
    // change the class on the element below the current image.


    setTimeout(rotate, 1000);
}

$(document).ready(function() {
    rotate();
});
Sean Vieira