1

I am trying to use the scrollTop function for my program, but I am finding that I am writing a lot of repetitive code.

This is an example:

<div id="table_contents >
    <ul>
        <li id="one"> title One </li>
        <li id="two"> title Two </li>
    </ul>
</div>


<div id="content">
    <p id="target_one"> I am content one </p>

    <p id="target_two"> I am content two </p>
</div>

If i was to click on 'title One' I want to scroll to 'I am content one' Likewise for title two and content two.

This is easy enough to do with jQuery/JS

$("#one").click(function() {
        $('html, body').animate({
            scrollTop: $("#target_one").offset().top -20
        }, 800);
    });

But say for example my table of contents has 15 elements in it, and I want to make each clickable to scroll to its content. For this I would have to repeat the above code 15 times for each element.

Is there a better way than that?

2
  • from all the answers below, everyone is using $(this).attr() What does this do? Commented Aug 22, 2014 at 16:51
  • 1
    $(this).attr() or $(this).prop() returns or sets the attribute of the element. Read here : api.jquery.com/prop and api.jquery.com/attr Commented Aug 22, 2014 at 16:54

7 Answers 7

5

Just change your script to :

Method 1

$("#table_contents").on("click","li",function() {
        $('html, body').animate({
            scrollTop: $("#target_"+$(this).prop('id')).offset().top -20
        }, 800);
    });

In this method, the id of the clicked element will be appended to "target_", to locate the "target id". This method will work even for the dynamically added li elements.


Method 2 : Without ids [but same order]:

$("#table_contents").on("click","li",function() {
        $('html, body').animate({
            scrollTop: $("#content p").eq($(this).index()).offset().top -20
        }, 800);
    });

in this method, the index of the element li is mapped to the index of the p elements to locate the scroll location.

And done!!

http://jsfiddle.net/bmL0o9ez/

http://jsfiddle.net/bmL0o9ez/2/

Sign up to request clarification or add additional context in comments.

2 Comments

Still requires managing unique IDs for the list elements and targets.
@JeanFerreira it appends the id of the clicked element to "target_"
1

LIVE FIDDLE DEMO

$("#table_contents ul li").click(function () {

    var theIdAttr = $(this).attr("id");

    $("html, body").animate({
        scrollTop: $("#target_" + theIdAttr).offset().top -20
    });

});

Comments

1

You can use a more generic selector for type sort of thing where each element requires identical behavior.

$("#table_contents li").click(function() {
        var liElement = $(this);
        $('html, body').animate({
            scrollTop: $("#target_" + liElement.attr('id')).offset().top -20
        }, 800);
    });

Comments

1

You can build the id of the paragraph dynamically based on the id of the li.

HTML

    title One title Two

<div id="content">
    <p id="target_one"> I am content one </p>

    <p id="target_two"> I am content two </p>
</div>

Javascript:

$("#table_contents li").click(function() {
    $('html, body').animate({
        scrollTop: $('#target_' + $(this).attr('id')).offset().top -20
    }, 800);
 });

Comments

1

Here's a solution that doesn't rely on using IDs at all, but instead uses jQuery's index() function:

$("#table_contents li").click(function () {
    $('html, body').animate({
        scrollTop: $("p").eq($(this).index()).offset().top - 20
    }, 800);
});

jsFiddle example

Comments

1

Make it generic, like:

$("#table_contents ul li").click(function() {
        $('html, body').animate({
            scrollTop: $('#target_'+ $(this).attr("id")).getId.offset().top -20
        }, 800);
    });

if you keep the content in order you could even go ultra generic, like:

$("#table_contents ul li").click(function() {
        var index = $(this).index();
        $('html, body').animate({
            scrollTop: $('#content:nth-child('+index+')').getId.offset().top -20
        }, 800);
    });

Not tested, but it should give you an idea

cheer mate

Comments

-1

I do

$("#content p").each(function() {
    var heights = [];
    heights.push($(this).offset().top);
});

Then do

heights[your_target_as_index];

Done?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.