0

Here's what I'm trying to achieve in jQuery: I've multiple hero sections displayed one after the other in my HTML. Each time a hero section reaches the top of the window I want to add class 'link', if not remove that class.

Each hero section has class 'parallax' and as ID 'parallax-1', 'parallax-2', 'parallax-3', etc.

<section class="parallax" id="parallax-1"></section>
<section class="parallax" id="parallax-2"></section>
<section class="parallax" id="parallax-3"></section>
...

JS code:

var target = $('.parallax').attr('id'),
    $window = $(window);

$window.on('load resize scroll',function(){
  var $div = $('#parallax'+target);
  if ( $window.scrollTop() >= $div.offset().top ) {
    $div.addClass('link');
  } else {
    $div.removeClass('link');
  }
});

So the code above doesn't work and this is the error in browser console:

undefined is not an object (evaluating '$div.offset().top')

I don't understand what is wrong exactly because each ID exists. Thank you for your help!

Mathieu Préaud
  • 357
  • 3
  • 16
  • `$('#parallax'+target)` > `$('#parallax-'+target)` – Adam Azad Jan 16 '18 at 10:49
  • Try logging $div – Nicolas Leucci Jan 16 '18 at 10:50
  • `$('.parallax')` returns an array of parallax elements so which id are you expecting it to get? If you are wanting to see which div is currently on screen then you need to do something like this: https://stackoverflow.com/questions/487073/check-if-element-is-visible-after-scrolling – Pete Jan 16 '18 at 11:03

1 Answers1

0

var target = $('.parallax').attr('id') will select the first element with class parallax and store it's id into target ie: parallax-1

When you create the div selector, you are using '#parallax'+target which results in #parallaxparallax-1 and hence the error. Just change it to '#'+target and it will work fine but only for the first section because you have only done this for the first section's code.

If you want to do this for all sections, you can use JQuery.each in the following way.

$('.parallax').each(function(){
    var target = $(this).attr('id'),
    $window = $(window);

    $window.on('load resize scroll',function(){
      var $div = $('#'+target);
      if ( $window.scrollTop() >= $div.offset().top ) {
        $div.addClass('link');
      } else if($div.hasClass('link')) {
          $div.removeClass('link');
      }
  });

})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="parallax" id="parallax-1">1</section><br>
<section class="parallax" id="parallax-2">2</section><br>
<section class="parallax" id="parallax-3">3</section><br>
<section class="parallax" id="parallax-4">4</section><br>
<section class="parallax" id="parallax-5">5</section><br>
<section class="parallax" id="parallax-6">6</section><br>
<section class="parallax" id="parallax-7">7</section><br>
<section class="parallax" id="parallax-8">8</section><br>
<section class="parallax" id="parallax-9">9</section><br>
<section class="parallax" id="parallax-10">10</section><br>
<section class="parallax" id="parallax-11">11</section><br>
<section class="parallax" id="parallax-12">12</section><br>
<section class="parallax" id="parallax-13">13</section><br>
<section class="parallax" id="parallax-14">14</section><br>
<section class="parallax" id="parallax-15">15</section><br>
<section class="parallax" id="parallax-16">16</section><br>
<section class="parallax" id="parallax-17">17</section><br>
<section class="parallax" id="parallax-18">18</section><br>

Hope it helps!!

Varun Sharma
  • 1,602
  • 1
  • 13
  • 37
  • This is very inefficient - you are binding a new on load, resize and scroll event to the window for every section you iterate through - add a console.log inside that event and then resize your window, you will see it is logged 18 times – Pete Jan 16 '18 at 11:33
  • Hi Varun, I just tried your solution and it works perfectly! I can't believe I didn't see my mistake as you suggest with the ID. Thank you very much for your help. – Mathieu Préaud Jan 16 '18 at 16:23
  • Happy to help @MathieuPréaud – Varun Sharma Jan 16 '18 at 16:26