简体   繁体   中英

Javascript IE8 wrapper for existing onclick event

I have to call another function before the original onclick event fires, I've tried a lot of different paths before I've come to following solution:

function bindEnableFieldToAllLinks() {
    var links = document.getElementsByTagName('a');
    for (var i = 0; i < links.length; i++) {
        var link = links[i];
        var onclick = link.getAttribute('onclick');
        link.onclick = new Function("if(linkClickHandler()){"+onclick+"}");
        console.log(link.getAttribute('onclick'));
    }
}

This does the trick in Firefox and Chrome but IE8 is acting strange, it seems that the function that's in the onclick variable isn't executed. I've already added console.log messages that get fired after the if statement is true and if I print out the onclick attribute I get following:

LOG: function anonymous() {
if(linkClickHandler()){function onclick()
{
if(typeof jsfcljs == 'function'){jsfcljs(document.getElementById('hoedanigheidForm'),      {'hoedanigheidForm:j_id_jsp_443872799_27':'hoedanigheidForm:j_id_jsp_443872799_27'},'');}return false
}}
}

So it seems that the function is on the onclick of the link and the old onclick function is on it as well.

Can anyone help me out with this please?

Say you have an onclick attribute on a HTMLElement ..

<span id="foo" onclick="bar"></span>

Now,

var node = document.getElementById('foo');
node.getAttribute('onclick'); // String "bar"
node.onclick; // function onclick(event) {bar}

The latter looks more useful to what you're trying to achieve as using it still has it's original scope and you don't have to re- eval uate code with Function .

function bindEnableFieldToAllLinks() {
    var links = document.getElementsByTagName('a'),
        i;
    for (i = 0; i < links.length; i++) function (link, click) { // scope these
        link.onclick = function () { // this function literal has access to
            if (linkClickHandler())  // variables in scope so you can re-
                return click.apply(this, arguments); // invoke in context
        };
    }(links[i], links[i].onclick); // pass link and function to scope
}

Further, setting a named function inside an onclick attribute (ie as a String ) doesn't achieve anything; the function doesn't invoke or even enter the global namespace because it gets wrapped.
Setting an anonymous one is worse and will throw a SyntaxError when onclick tries to execute.

This will do what you want, executing what is inside linkClickHandler first, and then executing the onclick event. I put in a basic cross browser event subscribing function for your reuse.

bindEnableFieldToAllLinks();    

function bindEnableFieldToAllLinks() {
    var links = document.getElementsByTagName('a');
    for (var i = 0; i < links.length; i++) {
        var link = links[i];
        var onclick = link.getAttribute('onclick');
        onEvent(link, 'click', function() { 
            linkClickHandler(onclick);
        });
        link.onclick = undefined;
    }
}

function onEvent(obj, name, func) {
    if (obj.attachEvent) obj.attachEvent('on' + name, func);
    else if (obj.addEventListener) obj.addEventListener(name, func);    
}
function linkClickHandler(funcText) {
    alert('before');
    var f = Function(funcText);

    f();
    return true;
}

jsFiddle

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