0

I have an array of elements, to which I want to apply a certain onclick event. What is the correct way of doing so (if possible at all)?

The function I want to apply to every element is this:

        function fade(element){
            var o = 1.0;
            var x = setInterval(function(){
                element.style.opacity = o;
                o -= 0.01;
                if(o <= 0) {
                    element.style.display = "none";
                    clearInterval(x);
                }
            }, 10);
        }

This is what I'm trying to do:

    <script type="text/javascript">
        var el = document.getElementsByClassName("circle");
        console.log(el[0]);
        for(var i = 0; i < el.length; i++){
            el[i].onclick = function(){ fade(el[i]); }
        }
    </script>

That is, I want to apply function fade() as the onclick event of every element of class circle, in such a way that whenever a circle is clicked, it fades out.

However, the code above does not work at all. JavaScript console gives me the following error:

Uncaught TypeError: Cannot read property 'style' of undefined

I'm not sure what I am doing wrong, I'm just learning Javascript. I have searched for this specific error, but found nothing very helpful.

--Edit--

My actual code is not long, so here it is:

function fade(element) {
  var o = 1.0;
  var x = setInterval(function() {
    element.style.opacity = o;
    o -= 0.01;
    if (o <= 0) {
      element.style.display = "none";
      clearInterval(x);
    }
  }, 10);
}
.circle {
  height: 200px;
  width: 200px;
  border-radius: 50%;
  content: '';
  float: left;
}
.red {
  background-color: red;
}
.green {
  background-color: green;
}
.blue {
  background-color: blue;
}
<div id="red" class="circle red"></div>
<div id="blue" class="circle blue"></div>
<div id="green" class="circle green"></div>
<script type="text/javascript">
  var el = document.getElementsByClassName("circle");
  console.log(el[0]);
  for (var i = 0; i < el.length; i++) {
    el[i].onclick = function() {
      fade(el[i]);
    }
  }
</script>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • 1
    Please click the `<>` button in the editor and create a [mcve] - we are missing HTML and you likely need a closure - or use transitions or jQuery – mplungjan Jan 24 '17 at 15:18
  • You know that you could fade with CSS3, then all you have to do is add/remove (toggle) a class with javascript .. [see here for css3 animation](http://stackoverflow.com/questions/21145621/css-transition-opacity-fade-background) – caramba Jan 24 '17 at 15:20
  • @caramba thanks for the tip, I did not know that. I'd still like to know how to do it with js though. I feel like I'm missing something about how variables are passed or how attributes are handled, and that I would really like to know. – Gabriel Taets Jan 24 '17 at 15:24

1 Answers1

1
  1. pass the element instead of an array element
  2. take a copy of the passed element to use in the setInterval
  3. assign the handler in the load event handler

function fade(el) {
  var o = 1.0,
    element = el, // copy the element passed
    x = setInterval(function() {
      element.style.opacity = o;
      o -= 0.01;
      if (o <= 0) {
        element.style.display = "none";
        clearInterval(x);
      }
    }, 10);
}
window.onload = function() {
  var el = document.querySelectorAll(".circle"); // more compatible
  for (var i = 0; i < el.length; i++) {
    el[i].onclick = function() {
      fade(this); // "this" is the element clicked
    }
  }

}
.circle {
  height: 200px;
  width: 200px;
  border-radius: 50%;
  content: '';
  float: left;
}
.red {
  background-color: red;
}
.green {
  background-color: green;
}
.blue {
  background-color: blue;
}
<div id="red" class="circle red"></div>
<div id="blue" class="circle blue"></div>
<div id="green" class="circle green"></div>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • That is exactly what I needed. I had a feeling that `this` would refer to the function instead of the element. Worked like a charm. Thanks! – Gabriel Taets Jan 24 '17 at 15:30