3

I need to select elements currently visible (and in view) in scrolling list. In my list I have a table. Example:

<div class='list'>
<table>
    <tr>
        <td>item</td>
    </tr>
    <tr>
        <td>item</td>
    </tr>
    <tr>
        <td>item</td>
    </tr>
    <tr>
        <td>item</td>
    </tr>        
</table>

I want to only choose those elements that are now in visible to the user (ie. on the screen, not off screen)

enter image description here

On JsFiddle: jsfiddle

Ionut Necula
  • 11,107
  • 4
  • 45
  • 69
pgrekovich
  • 137
  • 1
  • 9

5 Answers5

2

The accepted answer here provides a function to detect if an element is within scrollable view, iterate you elements and check against the function

Check if element is visible after scrolling

EDIT: with some adjustment this code works (it could be refactored, but shows the concept): https://jsfiddle.net/vas840kr/

var $window = $(".list");
var docViewTop = $window.scrollTop();
var docViewBottom = docViewTop + $window.height() + 5;
Community
  • 1
  • 1
BobbyTables
  • 4,481
  • 1
  • 31
  • 39
2

Tweaked my other answer

Demo

See comments inline in the code.

$(document).ready(function() {
  // Get viewport height, gridTop and gridBottom
  var gridTop = 0,
    gridBottom = $('.list').outerHeight();

  $('.list').on('scroll', function() {
    // On each scroll check if `td` is in interested viewport
    $('.list td').each(function() {
      var thisTop = $(this).offset().top;

      // Check if this element is in the interested viewport
      if (thisTop >= gridTop && (thisTop + $(this).height()) <= gridBottom) {
        $(this).css('background', 'red');
      } else {
        $(this).css('background', 'gray');
      }
    });
  });
});
.list {
  height: 112px;
  width: 300px;
  display: block;
  overflow-y: scroll;
}
table tr td {
  width: 300px;
  height: 50px;
  background-color: gray;
  border: 1px solid #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<div class='list'>
  <table>
    <tr>
      <td>item</td>
    </tr>
    <tr>
      <td>item</td>
    </tr>
    <tr>
      <td>item</td>
    </tr>
    <tr>
      <td>item</td>
    </tr>
    <tr>
      <td>item</td>
    </tr>
    <tr>
      <td>item</td>
    </tr>
    <tr>
      <td>item</td>
    </tr>
    <tr>
      <td>item</td>
    </tr>
    <tr>
      <td>item</td>
    </tr>
    <tr>
      <td>item</td>
    </tr>
    <tr>
      <td>item</td>
    </tr>
    <tr>
      <td>item</td>
    </tr>
    <tr>
      <td>item</td>
    </tr>
    <tr>
      <td>item</td>
    </tr>
    <tr>
      <td>item</td>
    </tr>
    <tr>
      <td>item</td>
    </tr>
  </table>
</div>
Community
  • 1
  • 1
Tushar
  • 85,780
  • 21
  • 159
  • 179
0

I think this will help you:

$('tr:first-child td, tr:nth-child(2) td').css('background', 'red');
Ionut Necula
  • 11,107
  • 4
  • 45
  • 69
0

I figure you're going to want to apply this to a dynamic number of td's. However, since there's no CSS selector to specifically target those elements 'hidden' from view due to overflow clipping, you'll have to use javascript to reach those elements or their inverse, in-view siblings.

0

I made a pure JavaScript solution ("Vanilla JS"), as a branch of your question's jsfiddle. Maybe of interest for some readers:

https://jsfiddle.net/rplantiko/u2gLr64c/

(function(){

    var result = document.getElementById("result");
    var container = document.getElementById("container");
    var cells  = toArray(
       document.getElementsByTagName("td")
       );
    var isCellVisible = isChildElementVisible( container );

    container.addEventListener("scroll",determineVisibleRows);
    determineVisibleRows();

    function determineVisibleRows() {
      result.value =  
        cells.filter( isCellVisible ).map( rowIndex ).join(',');
      }

    function isChildElementVisible(container) {
      var containerHeight = parseInt(getComputedStyle(container).height);
      return function(element) {
        var containerTop = parseInt( container.scrollTop );
        var containerBottom = containerTop + containerHeight;
        var elemTop = element.offsetTop;
        var elemHeight =  parseInt(getComputedStyle(element).height);
        var elemBottom = elemTop + elemHeight;
        return (elemTop >= containerTop && 
                elemBottom <= containerBottom);
        }
     }

    function toArray(arraylikeObject) {
      return Array.prototype.slice.call( arraylikeObject, 0 )
    }

    function rowIndex( cell ) {
      return cell.parentNode.rowIndex+1;  
    }

})()    
rplantiko
  • 2,698
  • 1
  • 22
  • 21