0

I am trying to learn javascript, without using jQuery and others.

I'm having this error: Cannot call method 'getElementsByTagName' of undefined

I know what the problem of the error, but it does not know to solve it. how can I avoid this error in the future?

   var menu = document.getElementsByClassName("menu-item");
    var i;
    for (i = 0; i < menu.length; i = i + 1) {
      menu[i].addEventListener("mouseenter", function () {
        setInterval(function(){
          menu[i].getElementsByTagName("a").css("color","red")
        },5000)
      })
    }
Mateus Vahl
  • 979
  • 2
  • 12
  • 29
  • [`.css()`](http://api.jquery.com/css/) is jquery also see http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example – Musa Nov 02 '13 at 06:16
  • in pure javascript you should call style.color="red", no css() – Maxim Ershov Nov 02 '13 at 06:18
  • document.getElementsById(menu[i].id).setAttribute('style','color:red'); you can also find your own using console of your browser – Just code Nov 02 '13 at 06:18
  • 1
    This code looks like it has other problems. Why would you start a new interval in mouseenter and never, ever stop the interval? Every time you get a mouseenter, you will get yet another interval running. And, then further your interval just does the same thing over and over again. It doesn't seem like you even want to use `setInterval()` here at all. Perhaps you meant to use `setTimeout()` which will run once at some time in the future, not continuously. – jfriend00 Nov 02 '13 at 06:41
  • You might want to take a look at http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example – Qantas 94 Heavy Nov 02 '13 at 09:31
  • @jfriend00 Right! t.you – Mateus Vahl Nov 02 '13 at 20:02

1 Answers1

1

Actually there is a deeper problem with the code. setInterval's function will not be called while the loop is running. It will be called after the loop has finished. So when it is called, i will have a value of menu.length, thus being outside of the array. To fix it, try something like this: (fiddle:http://jsfiddle.net/bKY9y/5/)

var menu = document.getElementsByClassName("menu-item");
console.log(menu);

for (var i = 0; i<menu.length; i++)
{

    console.log(menu[i].addEventListener)
    menu[i].addEventListener("mouseover",function () {
        var obj = this;
        setTimeout(function(){
            console.log(obj);
            var a = obj.getElementsByTagName("a");
            for (var j = 0; j < a.length; j++){
                a[j].style.color = "red";
            }          
        },1000)
      })
}
pax162
  • 4,735
  • 2
  • 22
  • 28
  • The OP's code applies the color to all the "a" tags found with `getElementsByTagName()`. That's not what your code does. – jfriend00 Nov 02 '13 at 06:42
  • OP is using mouseenter, you are using mouseover and different time on the interval. I think you've fixed the main things wrong with the OP's code, but as I commented on the OP's question, I don't see how starting a new `setInterval()` in every mouse event could possibly be the right thing. Intervals will accumulate and then you will have multiple intervals running on the same object forever. – jfriend00 Nov 02 '13 at 06:51
  • You're right, it should be setTimeout, edited. mouseenter, as far as I know is supported only by IE. jquery simulates it, but if we don't have jquery, I think mouseover is a good replacement. – pax162 Nov 02 '13 at 06:59