chris.carruthers chris.carruthers - 7 months ago 9
Javascript Question

Trouble converting a simple one off jQuery function to each

This should be a reasonably simple one - I have written a very basic script that detects when an image with specific class name appears on the screen via scroll. When the image appears, a class is added to it which triggers opacity and movement CSS animation.

This is all working fine, but I want this to work for several images on the same page. I have tried using each() both inside and outside of the scroll function and it breaks the script. I believe I am on the right track, but the variables used to detect when the image appears on screen are throwing me off I think, as I can't use $(this) as I normally would with an each() function.

jQuery Script is here:

// Setup
$(".appear").addClass("off");

objectOffset = $(".appear").offset().top;
winHeight = $(window).height();
trigger = objectOffset - winHeight;

$(window).scroll(function() {
if ($(window).scrollTop() > trigger) {

$(".appear").removeClass("off");
$(".appear").addClass("on");

}

});


JS Fiddle of the original, functioning script ( works only on the first image ):

https://jsfiddle.net/gv6qzxph/

Many thanks guys.

Edited to included broken attempt:

// Setup
$(".appear").addClass("off");

$(".appear").each(function() {

objectOffset = $(this).offset().top;
winHeight = $(window).height();
trigger = objectOffset - winHeight;

$(window).scroll(function() {
if ($(window).scrollTop() > trigger) {

$(this).removeClass("off");
$(this).addClass("on");

}

});

});

Answer

On your first attempt you have only defined trigger for your first <div>. In the second attemt you are trying to bind scroll within loop it would be rather killing the performance. What you need is to check if your element is visibile when scrolled. Please find working version below

  // Setup
  $(".appear").addClass("off");

  $(window).scroll(function() {

        $('.appear').each(function() {
            if(isVisible(this)){
                $(this).removeClass('off').addClass('on');
          }
      });

  });

  function isVisible(elem) {
    var $elem = $(elem);
    var $window = $(window);

    var elemTop = $elem.offset().top;
    var docViewTop = elemTop - $window.height();

    return $window.scrollTop() > docViewTop;
  };

And working jsfiddle here: https://jsfiddle.net/swnuro9z/1/

Cheers

Comments