1

I have multiple sections with the class blockList li throughout each of these sections. How am I able to trigger only the current blockList li items for the ones that are in view? Currently, once any of the list items are in view they all fire throughout the page, even though they are not in view.

The snippet below illustrates the issue I am having.

$('.blockList').waypoint(function() {
  $('.blockList li').each(function(index) {
   setTimeout(()=>{
    $(this).addClass('active');
   }, 200*index);    
  });
 }, {
  offset: '60%'
 });
#blue, #red {
  width: 100%;
  height: 100vh;
}
#blue {
  background: blue;
}
#red {
  background: red;
}
.blockList {
 margin: 15px 0;
 text-align: left;
}
.blockList li {
 font-size: 1rem;
 color: #FFF;
 margin: 20px 0;
 opacity: 0;
 -webkit-transition: ease 0.4s;transition: ease 0.4s;
 -webkit-transform: translateY(-15px);transform: translateY(-15px);
}
.blockList li.active {
 opacity: 1;
 -webkit-transform: translateY(0px);transform: translateY(0px);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/waypoints/4.0.1/jquery.waypoints.min.js"></script>
<section id="blue">
  <ul class="blockList">
    <li>A</li>
    <li>B</li>
    <li>C</li>
    <li>D</li>
  </ul>
</section>
<section id="red">
  <ul class="blockList">
    <li>E</li>
    <li>F</li>
    <li>G</li>
    <li>H</li>
  </ul>
</section>
Paul
  • 3,180
  • 2
  • 20
  • 50

1 Answers1

1

You are adding active class to li items for all of them.

$('.blockList li').each(function(index) {
    setTimeout(()=>{
        $(this).addClass('active');
    }, 200*index);           
});

TL:TR

In shorter terms. you are basicaly adding active class two times to each list element. Since you are adding it at the begging and then adding it at the 60% offset.


It loops trough all li and puts active class. So therefore it doesnt have to be in view, since its adding on load.

One solution might be getting position in browser of second object, or make a compact system that it checks all of them, places in array. So it would check its position -> on scroll check if reached any of the elements -> if reached, add active class to the coresponding ID.

var p = $( "#red" ).position;
var Positions = {top: p.top};

Then get the your center window position Something like:

jQuery.fn.center = function () {
    this.css("position","absolute");
    this.css("top", Math.max(0, (($(window).height() - $(this).outerHeight()) / 2) + 
                                                $(window).scrollTop()) + "px");
    this.css("left", Math.max(0, (($(window).width() - $(this).outerWidth()) / 2) + 
                                                $(window).scrollLeft()) + "px");
    return this;
}

Then compare them, if it reached the element.

Then get its id and add .active class to the #red li, not genaraly li.

What I would do in this situation:

var global_list = {}; var elemCount = 0;
$(document).ready(function() {
 //call initFunc, after its complete, call elimination (so it would check on load) and then set on scroll.
 initFunc(function() {
    elimination();
    $(document).on('scroll', function() { elimination() });
  });

 //This function is basicaly your startup.
  function initFunc(int) { 
      $('.blockList').each(function() {
          var p = $(this).position(); //Lets get its position.
          var id = $(this).attr('id'); //Lets get its ID
          global_list[id] = p.top; //Lets asign ID -> topPosition, so { first: 8 }...
          elemCount++;
      });
      
      int();
  }
  
  //This assigns needed stuff for allready reached objects.
  function elimination() { 

    
    if(elemCount != 0) { //Did we allready show all elements?
      var cb = $(this).scrollTop() + ($(this).height()), ct = $(this).scrollTop(); //Gets top position, and bottom.
      var cP = ct + ((cb - ct)/2); //Gets your center point of viewport - ad half screen size to top;
      for(var k in global_list) { //Loop trough all element that are left and see if we did scroll.
        if(global_list[k] <= cP) { //Lets check if user scolled to it.
         var ic=0;
          $('#'+k+' li').each(function() {
             setTimeout(()=>{
                $(this).addClass('active');
              }, 200*ic); 
              ic++
            });
            delete global_list[k]; //Lets delete allready assigned classes
            elemCount--; //Decreses elements count, so eventualy once all reached, it becomes 0;
        }
      }
    }
  }
});
#first {
  height: 1000px;
}

#second {
  height: 1000px;
}

.beatiful {
  background: yellow;
}

.div_div li {
   font-size: 1rem;
 color: #000;
 margin: 20px 0;
 opacity: 0;
 -webkit-transition: ease 0.4s;transition: ease 0.4s;
 -webkit-transform: translateY(-15px);transform: translateY(-15px);
}

.div_div li.active {
   opacity: 1;
 -webkit-transform: translateY(0px);transform: translateY(0px);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class='div_div' id='first'>
  <ul class="blockList" id='first'>
    <li>A</li>
    <li>B</li>
    <li>C</li>
    <li>D</li>
  </ul>
</div>
<div class='div_div' id='second'>
  <ul class="blockList" id='second'>
    <li>A</li>
    <li>B</li>
    <li>C</li>
    <li>D</li>
  </ul>
</div>
Thomas J.
  • 543
  • 4
  • 17
  • 1
    Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/180979/discussion-on-answer-by-communityisridiculous-how-to-trigger-a-class-that-is-onl). – Samuel Liew Sep 29 '18 at 04:50
  • @Paul most likely it has to do something with css, js doesnt drop errors, and if you assigned correct class and unique ID, there is no reason for it not to work. – Thomas J. Oct 01 '18 at 14:11
  • The css is the same as before, which it displayed with the waypoints. Unique ID's have been applied. – Paul Oct 01 '18 at 14:22
  • I figured it out. I had to make a new each function for the img's. The existing each function was just for list items. Thanks! – Paul Oct 01 '18 at 15:34