riogrande riogrande - 1 month ago 12
jQuery Question

apply function on all elements with same class

I have a simple function which detects if an element is in the viewport or that it is visible. If that element is visible, on every scroll I move that element down with

.css()
and change the top property to achieve some parallax effect. This element on which I check is in the viewport and when it moves it is repeated X times on the page. Everything works but only on the first element has this problem, all other elements inherit top position from the first.

Demo: http://codepen.io/riogrande/pen/RRVVwq (scroll down for effect).

EDIT: Some who answered had the wrong idea what I want, so I want the title (element) to move on scroll but only when its in viewport(visible). So when the first element with same class is visible its moving with scroll, then when you scroll below it its not visible anymore it should not move but the other one which is visible should be moving etc etc.

Jquery:

(function($) {

'use strict';

$.prototype.isVisible = function() {
var rect = this[0].getBoundingClientRect();
return (
(rect.height > 0 || rect.width > 0) &&
rect.bottom >= 0 &&
rect.right >= 0 &&
rect.top <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.left <= (window.innerWidth || document.documentElement.clientWidth)
);
};

function doCheck() {
var elementToDetect = $('.text');
var scrolled = $(window).scrollTop();
if (elementToDetect.isVisible()) {
elementToDetect.css('top', (-100 + (scrolled * 0.2)) + 'px');
}
}

$(document).ready(function() {
doCheck();
});

$(window).scroll(function() {
doCheck();
});

})(jQuery);

Answer

jQuery applies operations like css() on each element matching the selector.

So if you iterate the jQuery object, you get this:

  function doCheck() {
    var elementToDetect = $('.text');
    var scrolled = $(window).scrollTop();
    for (var index = 0; index < elementToDetect.length; index++) {
      var element = $(elementToDetect[index]);
      if (element.isVisible()) {
        element.css('top', (-100 + (scrolled * 0.2)) + 'px');
      }
    }
  }

Which still has a problem, in that all the text maintain the same top relative to their image.

Edit: Actually, the way I understand what you're doing, you want to let them all move in the same way as you scroll, so each starts above the image when it comes into view. This is closer to what you need:

  function doCheck() {
    var elementToDetect = $('.text');
    for (var index = 0; index < elementToDetect.length; index++) {
      var text = elementToDetect[index];
      var parent = text.parentElement;
      var parentTop = parent.getBoundingClientRect().top;
      var scrolled = (window.innerHeight - parentTop);
      if (scrolled < 0) {
        scrolled = 0;
      }
      if (parentTop < window.innerHeight) {
        $(text).css('top', (-100 + (scrolled * 0.2)) + 'px');
      }
    }
  }

Basically, looking at scrollTop() is wrong, because you really want the position of the parent div to determine the placement of your text.