52

I have a list of objects in DOM, which is longer than screen height area.

I need to detect on-screen visible objects only to make something like timeline tree-view. (something like on the picture below):

enter image description here

My DOM looks like this:

<!-- elements visibility on screen to be DETECTED -->
<div id="elements">
    <div id="elem-1">Lorem ipsum</div>
    <div id="elem-2">Lorem ipsum</div>
    <div id="elem-3">Lorem ipsum</div>
    <div id="elem-4">Lorem ipsum</div>
    <div id="elem-5">Lorem ipsum</div>
    <div id="elem-6">Lorem ipsum</div>
    <div id="elem-7">Lorem ipsum</div>
    <div id="elem-8">Lorem ipsum</div>
</div>


<!--elements visibility on screen to be AFFECTED  -->
<ul id="timeline">
    <li view-id="elem-1">Elem-1</li>
    <li view-id="elem-2">Elem-2</li>
    <li view-id="elem-3" class="active">Elem-3</li>
    <li view-id="elem-4" class="active">Elem-4</li>
    <li view-id="elem-5" class="active">Elem-5</li>
    <li view-id="elem-6" class="active">Elem-6</li>
    <li view-id="elem-7">Elem-7</li>
    <li view-id="elem-8">Elem-8</li>
</ul>

My goal is to detect IDs' of on-screen visible elements from #elements container and assign active class to corresponding elements in #timeline container.

I need to do this process on Scroll event.

Any ideas how to achieve this?

  • 1
    You need to iterate over each element and compare its `top` to the `scrollTop` of the document, and the `bottom` to the `scrollTop + height` of the document. – Rory McCrossan Oct 21 '13 at 15:07
  • 1
    you can use http://benpickles.github.io/onScreen/ – Tushar Gupta - curioustushar Oct 21 '13 at 15:09
  • This question is not duplicate, other linked question want to know if an element is in view-port, this one like to know which one of many elements are the first visible element in view-port – AaA Jan 27 '19 at 01:00

1 Answers1

46

First of all on-screen visible area is known as Viewport.

image is took from OP and cleaned up in Photoshop

(image is taken from OP. Cleared and edited in Photoshop)


So all you need is to detect all elements in your Viewport.

This can be achieved using many plugins for jQuery, but I'll explain you on one example, which is called as jQuery withinviewport

Link to source and documentation on: [ withInViewport - Github ]


Step 1:

Download plugins and include jQuery framework and withinviewport plugin in your script:

<script src="http://code.jquery.com/jquery-1.7.min.js"></script>
<script src="withinViewport.js"></script>
<script src="jquery.withinviewport.js"></script>

.

Step 2:

Initialise function on scroll event:

$(window).bind("scroll", function() {
    //your code placeholder
});

.

Step 3:

Use withinviewport selector to get all elements in you Viewport and by each element add class to corresponding list-item in your #timeline container:

$("#elements > div").withinviewport().each(function() {
   $('#timeline > li[view-id="'+$(this)[0].id+'"]').addClass('active');
});

Step 4:

Put all together:

$(window).bind("scroll", function() {

    //clear all active class
    $('#timeline > li').removeClass('active');

    //add active class to timeline
    $("#elements > div").withinviewport().each(function() {
         $('#timeline > li[view-id="'+$(this)[0].id+'"]').addClass('active');
    });
});

.


.

Also this plugin gives you opportunity to set top, bottom, left and right offset for view-port.

See demo here: http://patik.com/code/within-viewport/

zur4ik
  • 6,072
  • 9
  • 52
  • 78
  • 3
    Please explain the difference between 'doing it' and using a plugin? I'd love to know. Also please show me where the OP has said I don't want to use a plugin – Jamie Hutber Oct 21 '13 at 15:09
  • 1
    @Zap7 actually this is the way wow to do it. I don't see the reason why it was downvoted. – zur4ik Oct 21 '13 at 15:09
  • I've upvoted this answer... even though its the same as mine – Jamie Hutber Oct 21 '13 at 15:10
  • 1
    @Zap7 Overzealous pedantry. If you were to insist "doing it", we could have [linked to the exact line in the source](https://github.com/patik/within-viewport/blob/master/withinViewport.js#L41), but that isn't particularly helpful to anyone. – Brian Oct 21 '13 at 15:10
  • @Brian this is the exact reason i've voted for the question to be closed. – Jamie Hutber Oct 21 '13 at 15:11
  • 2
    @musefan I had same answer on different forum and just copied most part. Only I took picture of Punto and quickly cleaned up in photoshop. – zur4ik Oct 21 '13 at 15:16
  • 4
    @zur4ik, to be perfectly clear: Punto has only asked two questions so far and you answered both (and your answers were accepted). The only answer he provided was to one of your questions, and you accepted it. Coincidences happen, but this looks a little too much. – Frédéric Hamidi Oct 21 '13 at 15:16
  • 1
    I don't think there is anything wrong with using plugin. Even if you wrote the code by your own, it's better to extract this feature into a plugin later. So why re-invent wheel? However, I agree with @musefan's point that the answer is way too quick to type. – Billy Chan Oct 21 '13 at 15:17
  • @FrédéricHamidi looks like you are right. I just looked on it. – zur4ik Oct 21 '13 at 15:19
  • lol I must say I did think blimey! that was one hella quick reply with a whole lot of content. – Jamie Hutber Oct 21 '13 at 15:19
  • @zur4ik this is exactly what i was searching for. Thanks for the best answer. This is another time you are my help! Thank you! –  Oct 21 '13 at 15:21
  • 2
    @zur4ik: Look, just be honest, you and the OP (assuming you are not both accounts) decided to get together and make this post. I personally have no problem with answering your "own questions", and having this as a point of reference isn't a problem either because it could be helpful to other visitors. The thing I am debating though is that it is a duplicate and I don't think this question deserves to exist for that reason (it also doesn't show any effort to solve the problem prior to asking) – musefan Oct 21 '13 at 15:23
  • 3
    I don't understand whats wrong. I had same content and it was just matter of Copy/Paste. I just modified picture in Photoshop. I don't think that it's not possible to answer in 3 mins with big content. – zur4ik Oct 21 '13 at 15:23
  • 1
    This is old, but I thought I'd specify something, because I did the mistake of copy/pasting @zur4ik's code; the function is "withinviewport" (lowercase "V"), and **not** "withinViewport" with a capital V like he wrote it. That is all. – Justin01 Oct 20 '15 at 06:23
  • @Justin01 Thanks for note. Updated. – zur4ik Oct 20 '15 at 08:38