Arrowcatch
Arrowcatch

Reputation: 1652

Scrolling to the next element

I'm struggling with a jquery or javascript problem.

It already got annoying which tells me I might think too complicated on this one.

So my markup (simplyfied) looks like this:

<div class="container">
    My Content
<a href="#" class="button">scroll down</a>
</div>


<div class="container">
    My Content
<a href="#" class="button">scroll down</a>
</div>


<div class="container">
    My Content
<a href="#" class="button">scroll down</a>
</div>


<div class="container">
    My Content
<a href="#" class="button">scroll down</a>
</div>

Basically just some containers.

Each one contains different content and a button.


The Plan:

1) After a click on a button the window should scroll down to the next container.

2) The last button scrolls to the first container again. So I need a loop.

3) The numbers of containers may change from page to page.

EDIT: 4) The containers may not always be direct siblings to each other (see markup below)


The Problem:

I could get this to work by giving each container a unique ID as a target for the scroll effect.

The problem with that is that it gets too messy quickly.

Cant I just somehow target "the next object with the class: container", and scroll to that?


I'm not sure if js or jquery is the right approach. My knowledge in both is somewhat limited.

I would be really grateful for a push in the right direction.


EDIT: The containers may not always be direct siblings of each other.

<div class="row">
        <div class="container">
            My Content
        <a href="#" class="button">scroll down</a>
        </div>


        <div class="container">
            My Content
        <a href="#" class="button">scroll down</a>
        </div>
</div>        

        <div class="container">
            My Content
        <a href="#" class="button">scroll down</a>
        </div>


        <div class="container">
            My Content
        <a href="#" class="button">scroll down</a>
        </div>

<div class="row">
        <div class="container">
            My Content
        <a href="#" class="button">scroll down</a>
        </div>


        <div class="container">
            My Content
        <a href="#" class="button">scroll down</a>
        </div>
</div>  

Upvotes: 4

Views: 28307

Answers (3)

ronalchn
ronalchn

Reputation: 12335

Simple solution:

To get the next container, try using next().

Basically, the <div> containers are siblings of each other, so calling .next() on one div container will give you the next.

$(".button").on("click", function(e) {
    $(document).scrollTop($(this).parent().next().offset().top);
    // $(this).parent().next() // this is the next div container.
    return false; // prevent anchor
});

http://jsfiddle.net/Pm3cj/1/

You just use $(this) to get the link object, .parent() to get the parent of the link, which is the <div>, then .next() to get the next sibling (note it will wrap automatically, so the sibling after the last <div> is the first <div>!),.offset()to get its position relative to the page,.top` to get it relative to the top border.

Then you just use $(document).scrollTop() to scroll to that location.


For a completely general solution, use:

$(".button").on("click", function(e) {
    container = $(this).parent();

    // if I am the last .container in my group...
    while (    document != container[0] // not reached root
            && container.find('~.container, ~:has(.container)').length == 0)
        container = container.parent(); // search siblings of parent instead

    nextdiv = container.nextAll('.container, :has(.container)').first();

    // no next .container found, go back to first container
    if (nextdiv.length==0) nextdiv = $(document).find('.container:first');

    $(document).scrollTop(nextdiv.offset().top);
    // $(this).parent().next() // this is the next div container.
    return false;
});

​The code basically uses container.find('~.container, ~:has(.container)') to find any sibling that has or is a .container. If nothing, then go up the DOM tree 1 step.

After it finds something which is or has a .container, it grabs it with nextdiv = container.nextAll('.container, :has(.container)').first();.

Lastly, if nothing is found, checked by nextdiv.length==0, just grab the first .container in the whole page.

Then scroll to whatever .container was grabbed.

http://jsfiddle.net/Pm3cj/3/


To animate the scroll, place the scrollTop property in an animate function:

// $(document).scrollTop(nextdiv.offset().top); // snaps to new scroll position
$('body').animate({scrollTop:nextdiv.offset().top},300); // animates scrolling

http://jsfiddle.net/Pm3cj/4/

Upvotes: 6

automaticAllDramatic
automaticAllDramatic

Reputation: 2063

What you want can be easily achieved through parent() and child().

If the number of containers on each page is different, then you should start ID'ing (don't know if that's a term) containers serially. Something like, class="container-1"

The click event on the last button should do something like:

var num = $('div[class^="container-"]').filter(function() {
    return((" " + this.className + " ").match(/\scontainer-\d+\s/) != null);
});
num++;
var last_container = $(this).parent('.container' + num);
last_container .scrollTo();

Am sure you can figure out what the next button should do ;)

Upvotes: -2

Rusty Jeans
Rusty Jeans

Reputation: 1426

JavaScript is not required for this. You can use HTML anchors.

<div class="container" id="first">
    My Content
<a href="#second" class="button">scroll down</a>
</div>


<div class="container" id="second">
    My Content
<a href="#third" class="button">scroll down</a>
</div>


<div class="container" id="third">
    My Content
<a href="#fourth" class="button">scroll down</a>
</div>


<div class="container" id="fourth">
    My Content
<a href="#first" class="button">scroll down</a>
</div>

Upvotes: -2

Related Questions