简体   繁体   中英

Attach mouse event to anchor: Javascript

I'm trying to attach onmouseover/out events to all anchor tags on the page (idea is to underling it onmouseover and remove it onmouseout).

I did the following code. It attaches the event to all anchors but onmouseover of any anchor, it does the underline only for the last anchor in the page, always.

Any idea, what could be wrong?

window.onload = function () {

    var elArray = document.getElementsByTagName("a");
    if (elArray != null && elArray.length > 0) {
        for (var count = 0; count < elArray.length; count++) {
            var el = elArray[count];
            if (el.addEventListener) {
                el.addEventListener("mouseover", function () {
                    el.style.textDecoration = 'underline'
                }, false);
                el.addEventListener("mouseout", function () {
                    el.style.textDecoration = 'none'
                }, false);
            } else {
                el.attachEvent('onmouseover', function () {
                    el.style.textDecoration = 'underline'
                });
                el.attachEvent('onmouseout', function () {
                    el.style.textDecoration = 'none'
                });
            }

        } //for
    } //if
}; //end of window.onload

You can do it by using simple CSS:

a {
    text-decoration: none;
}

a:hover {
    text-decoration: underline;
}

Do not trouble browser by using javascript when it can be done by CSS.

It's due to a scoping issue; el isn't scoped to each iteration of the for loop, it's scoped to the entire function, so once the for loop has finished executing el refers to the last element. Since the el inside your event handler functions is that same variable, they'll only ever be affecting the last <a> element on your page.

However, there's no need to use JavaScript for this, the same thing has been possible using CSS for quite some time. The following should work:

a {
    text-decoration: none;
}

a:hover {
    text-decoration: underline;
}

If you absolutely wanted to use JavaScript, then you'll need to create a closure to modify the scope of el using an immediately invoked function expression:

window.onload = function () {

    var elArray = document.getElementsByTagName("a");
    if (elArray != null && elArray.length > 0) {
        for (var count = 0; count < elArray.length; count++) {
            var el = elArray[count];
            (function(el) {
            // el in here is different to el outside since the parameter shadows it
            // you could give them different names - or not declare an el variable outside - to make the difference clearer
            if (el.addEventListener) {
                el.addEventListener("mouseover", function () {
                    el.style.textDecoration = 'underline'
                }, false);
                el.addEventListener("mouseout", function () {
                    el.style.textDecoration = 'none'
                }, false);
            } else {
                el.attachEvent('onmouseover', function () {
                    el.style.textDecoration = 'underline'
                });
                el.attachEvent('onmouseout', function () {
                    el.style.textDecoration = 'none'
                });
            }
            })(el);

        } //for
    } //if
}; //end of window.onload

The scope of el changes inside that anonymous function so that it does refer to the value of el for each iteration of the for loop.

The variable el that you use is not local to the loop iteration, so it will have the last value at the time when the event handlers are triggered.

Use an immediately invoked function to create a scope where each iteration gets it's own variable containing the element for that iteration:

window.onload = function (){

  var elArray = document.getElementsByTagName("a");
  if(elArray != null && elArray.length > 0){
    for(var count=0; count < elArray.length; count++){

      (function(el){

        if (el.addEventListener) {
          el.addEventListener("mouseover", function (){el.style.textDecoration = 'underline'}, false);
          el.addEventListener("mouseout", function (){el.style.textDecoration = 'none'}, false);
        } else {
          el.attachEvent('onmouseover',function (){el.style.textDecoration = 'underline'});
          el.attachEvent('onmouseout',function (){el.style.textDecoration = 'none'});
        }

      })(elArray[count]);

    }//for
  }//if
};//end of window.onload

However, for this specific effect you can just use CSS instead:

a { text-decoration: none; }
a:hover { text-decoration: underline; }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM