0


I'm trying to make a very light script for multiple classes class"demo" that can work on my onScrollDown responsive animation.

I don't really understand about writing arrays. but, I believe that if I use document.getElementsByClassName("demo")[i] , i < 0 and some function(i) I can implement it for individual classes. Because I use getBoundingClientRect() instead of fixed value.

So, how can I write it correctly using i as arrays?

Thank you..


Here is my working script :

<script>
var e = document.getElementById("demo");
var rect = e.getBoundingClientRect();
var x = rect.top;
$(window).bind('scroll', function () {
    if ($(window).scrollTop() > x-300) {
        $('#demo').addClass('animate');
    } else {
        $('#demo').removeClass('animate');
    }
});
</script>

*work only for a single element.


Here is what I'm trying to do, that not working yet

<script>
var e = document.getElementsClassName("test")[i];
var rect = e.getBoundingClientRect();
var x = rect.top;
var i;
for (i = 0; i < e.length; i++) {
  $(window).bind('scroll', function (i) {
      if ($(window).scrollTop() > x-300) {
          $e.addClass('animate');
      } else {
          $e.removeClass('animate');
      }
  });
}
</script>

CSS :

<style>
.test {
    background:#345;
    color:#FFF;
    height:2em;
    padding:.5em;
    top:50px;
    margin-top: 100px;
    width:100%;
}
.animate {
    width: 60px;
}
</style>

HTML

<div style="color: red; margin-bottom: 400px;">(Top!)</div>
<div class="test" id="demo">Menu</div>
<div class="test" id="demo">Menu</div>
<div class="test" id="demo">Menu</div>
<div style="color: red; margin-top: 400px;">(Bottom!)</div>
RedFrog
  • 76
  • 5

2 Answers2

0

Okay so I've achieved what you're trying to do. Here are the changes I made:

  1. Used the JQuery each function. This will loop all of the demo elements every time a scroll is detected. There are other ways of looping the elements but because you've already imported JQuery we may as well use it's functions.
  2. Changed #demo to .demo. In other words, I've changed id to class. id should only be used when working with elements that are completely unique. In this case, there are multiple demos so we use class instead.

Final code (as you scroll each element will turn red showing that the animate class has been added:

$(window).on('scroll', function() {

  $('.demo').each(function(i, obj) {
    var rect = obj.getBoundingClientRect();
    var x = rect.top;
    if ($(window).scrollTop() > x - 300) {
      $(obj).addClass('animate');
    } else {
      $(obj).removeClass('animate');
    }
  });
  
});
.body {
  height: 200vh;
  background-color: #f1f1f1;
}

.demo {
  height: 200px;
  width: 100%;
  background-color: #f9f9f9;
}

.demo.animate {
  background-color: #ff0000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="body">
  <div class="demo"></div>
  <div class="demo"></div>
  <div class="demo"></div>
  <div class="demo"></div>
</div>
A Friend
  • 1,420
  • 17
  • 22
  • can you explain me what does the `i` and `obj` inside `function(i, obj)` stood for – RedFrog Nov 30 '19 at 06:11
  • @RedFrog Yeah of course :) So the `i` and `obj` are the variables used to get the current loop element when inside the `each`. The `obj` is the current loop object (The value can also be accessed through the `this` keyword) and the `i` is the current loop objects index. You can find more information about it here: https://api.jquery.com/jquery.each/#entry-longdesc – A Friend Dec 01 '19 at 03:12
0

There are few notes in regards to your code:

  • In jQuery you can get elements offset by using .offset() function.
  • you should not use the same id more than once per page.
  • .bind() has been deprecated since jQuery 3.0. Use .on() instead.
  • To toggle class you can use .toggleClass(className, state). State is used to determine if you want to remove or add the class.

See this example:

$(window).on('scroll', function() {
  jQuery(".test").each(function() {
    let isTop = $(window).scrollTop() > jQuery(this).offset().top - 300;
    jQuery(this).toggleClass('animate', isTop);
  });
});
.test {
  background: #345;
  color: #FFF;
  height: 2em;
  padding: .5em;
  top: 50px;
  margin-top: 100px;
  width: 100%;
}

.animate {
  width: 60px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style="color: red; margin-bottom: 400px;">(Top!)</div>
<div class="test">Menu</div>
<div class="test">Menu</div>
<div class="test">Menu</div>
<div style="color: red; margin-top: 400px;">(Bottom!)</div>
Kalimah
  • 11,217
  • 11
  • 43
  • 80
  • The script is perfectly working as I expected. Thank you man.. Maybe my last question is, is there any reason why you prefer to use `let` instead of `var`? thank you.. – RedFrog Dec 01 '19 at 11:56
  • `let` and `const` are the new variable definition keywords. They replace `var`. I use them mainly for scope but there are number of reasons to use them. See here: https://stackoverflow.com/questions/762011/whats-the-difference-between-using-let-and-var – Kalimah Dec 01 '19 at 12:01