1

I have an image slideshow with navigation, with which I want to add an animated element to highlight the active slide, using an arrow graphic which moves to the active slide as the slideshow rotates. I'm using the jQuery Cycle plugin, which adds the 'activeSlide' class to the relevant slide number and I'm trying to get the finished result to be something like the slider on http://offerpop.com/, where the arrow moves the active slide automatically, as well as on click.

I've been trying to follow what seems to be the same objective from this thread: If $(element) hasClass then .animate() not working? but so far I haven't got it to function as I'd like to, based on the suggestions of this thread.

So I would be grateful if anyone can help me out and point me in the right direction to which method would be the way to go, as I don't really know where to start. Thanks

Here's the navigation part of the code:

<div id="nav">
    <div id="navitem" class="activeSlide"><a>1</a></div>
    <div id="navitem"><a>2</a></div>
    <div id="navitem"><a>3</a></div>
    <div id="navitem"><a>4</a></div>
    <div id="navitem"><a>5</a></div>
</div>

<div id="nav"></div>    
<div id="arrow"></div>​

<script type="text/javascript">
$(document).ready(function() {  
if($('#navitem').hasClass("activeSlide")){
       $("#arrow").animate({marginLeft:"100px"}, 500);
   };
});
</script>
Community
  • 1
  • 1
mmmoustache
  • 2,273
  • 6
  • 41
  • 62

2 Answers2

1

I've gone ahead and made a working version for you, complete with comments explaining how everything works. I also corrected some errors in your HTML (multiple elements can't have the same ID.) Here is the JSfiddle: http://jsfiddle.net/e6r2e/1/.

HTML:

<div id="nav">
    <div id="1" class="navitem activeSlide"><a>1</a></div>
    <div id="2" class="navitem"><a>2</a></div>
    <div id="3" class="navitem"><a>3</a></div>
    <div id="4" class="navitem"><a>4</a></div>
    <div id="5" class="navitem"><a>5</a></div>
</div>
<div id="arrow"></div>​

CSS:

.navitem{
    display:block;
    float:left;
    padding:10px 30px;
    cursor:pointer;
}   
.activeSlide{
    background:#ccc;
}
.activeSlide a{
    color:red;
}
#arrow{
    width:10px;
    height:10px;
    background:black;
    position:absolute;
    margin-top:40px;
    left:30px;
}    ​

JavaScript:

$(document).ready(function() {
    var slideX = [30, 98, 166, 234, 302], //Define the x-position of the arrow for each slide
        currentSlide = 0; //Current slide variable. Change this to change starting slide.

    //Function to change slides. Accepts one parameter, the slide's jQuery object:
    function changeSlide(slide) {
        $('.activeSlide').removeClass('activeSlide'); //Remove previous slide's activeSlide class
        $(slide).addClass('activeSlide'); //Add activeSlide class to current slide.
        $('#arrow').clearQueue().animate({ //Animate the arrow to the correct location. clearQueue is used so that animations aren't stacked:
            'left': slideX[currentSlide] + 'px' //Animate the 'left' selector (Better than margin-left).
        }, 300); //Animation duration in milliseconds.
    }

    //Rotate through slides:
    rotate = setInterval(function() {
        //Check if we're on the last slide; if so, return to 0:
        if (currentSlide + 1 >= slideX.length) {
            currentSlide = 0;
        } else {
            currentSlide++;
        }
        //Call the changeSlide function with the slide's jQuery object as the parameter.
        changeSlide($('#' + (currentSlide + 1)));

    }, 5000); //Duration to stay on each slide in milliseconds.
    //Animate to clicked slide:
    $('.navitem').click(function() {
        currentSlide = $(this).attr('id') - 1; //Change currentSlide variable to the slide clicked. We use the slide's ID to determine which slide it is, and then subtract one since we deal with numbers starting at 0, not 1.
        changeSlide($(this)); //Call changeSlide function with the new slide's jQuery object as the parameter.
        //Clear and restart our rotate interval so that the timer is reset. Otherwise if we clicked a slide with 1 second left on the timer, it would rotate again in 1 second instead of 5:
        clearInterval(rotate);
        rotate = setInterval(function() {
            if (currentSlide + 1 >= slideX.length) {
                currentSlide = 0;
            } else {
                currentSlide++;
            }
            changeSlide($('#' + (currentSlide + 1)));
        }, 5000);

    });
});​
HellaMad
  • 5,294
  • 6
  • 31
  • 53
0

If this was me, I'd use a setInterval() to call the code you've already written. Something like this:

function moveArrow()
{
    position_of_currently_active_slide = $(".activeSlide").index("#nav > div");
    margin_based_on_active_slide = (position+1)*30; // +1 because position is 0 indexed
    $("#arrow").animate({marginLeft:margin+"px"}, 500);
}

$(document).ready(function() {  
    setInterval(moveArrow, 900);
});​

That way, there is something always looking for the div with "activeSlide". AFAIK, there is no "jquery-way" to do this.

Please note: You still need to modify your code, to figure out which "slide" is active + how much margin-left to move it.

Auston
  • 480
  • 1
  • 6
  • 13