Search code examples
jqueryimagesliderjquery-selectors

Select next image in jQuery


I have the following HTML markup.

<div class="caption">
    <img class='active' alt='My Caption' src='path/to/image' />
    <div>My Caption</div>
</div>
<div class="caption">
    <img alt='My Caption 2' src='path/to/image' />
    <div>My Caption 2</div>
</div>

The captions are being placed inside those DIVs from the alt tags with some JS.

        $('#slider img').each(function() {
            $(this).wrap('<div class="caption"></div>').after('<div>' + $(this).attr('alt') + '</div>');
            $('.caption').width($(this).width()).children('div').each(function() {
                $(this).css({width: $(this).siblings('#slider img').width() -10, opacity: 0.5, display: 'block'});
            });
        });

The problem I'm having is when trying to make my images 'slide', it worked fine before but now I've added the captions I'm having some trouble.

Here is what is supposed to happen:
It goes through each image setting the class to active and fading the image in, it worked fine without captions but now that I have captions it is putting the active class on the div that has the caption in it.

Here is my JS

function simpleSlider(){
    var $active = $('#slider img.active');

    if($active.length == 0) $active = $('#slideshow img:last');

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

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

How would I make it select the next image, instead of the div saying My Caption?

Sorry if this doesn't make much sense.


Solution

  • When you are saying:

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

    it assumes that the next image is a direct neighbor (so that $active.next('img').length will always be 0 in your case as there are no images around). But since you have wrapped your images inside a container element you will now have to use a different approach for traversing.

    I would do it the following way:

    function simpleSlider() {
    
    
        var $active = $('.caption.active');
    
        if ($active.length == 0) $active = $('.caption:last');
    
        var $next = $active.next('.caption').length ? $active.next() : $('.caption:first');
    
        $next.css({
            opacity: 0.0
        }).addClass('active').animate({
            opacity: 1.0
        }, 1000, function() {
            $active.removeClass('active');
            $active.css({
                opacity: 0.0
            });
        })
    }
    

    See a working demo

    EDIT:

    In case these images are overlaid and the hidden image should always fade over the already shown image you can fix this easily by doing:

    a. move the line $active.removeClass('active') outside of the callback

    and

    b. add the following CSS:

    .caption{
    z-index: 100;
    }
    .caption:not(.active){
    z-index: 0;
    }
    

    Note that the :not() pseudo selector does not work in all browsers (i.e. old IEs), but you'll get the idea.

    Here's another fiddle