how to get javaScript event source element?

后端 未结 6 635
夕颜
夕颜 2020-12-23 16:20

Is there a way to retrieve the element source of an inline javaScript call?

I have a button like this:

6条回答
  •  离开以前
    2020-12-23 17:14

    You should change the generated HTML to not use inline javascript, and use addEventListener instead.

    If you can not in any way change the HTML, you could get the onclick attributes, the functions and arguments used, and "convert" it to unobtrusive javascript instead by removing the onclick handlers, and using event listeners.

    We'd start by getting the values from the attributes

    $('button').each(function(i, el) {
        var funcs = [];
    
    	$(el).attr('onclick').split(';').map(function(item) {
        	var fn     = item.split('(').shift(),
            	params = item.match(/\(([^)]+)\)/), 
                args;
                
            if (params && params.length) {
            	args = params[1].split(',');
                if (args && args.length) {
                    args = args.map(function(par) {
                		return par.trim().replace(/('")/g,"");
                	});
                }
            }
            funcs.push([fn, args||[]]);
        });
      
        $(el).data('args', funcs); // store in jQuery's $.data
      
        console.log( $(el).data('args') );
    });
    
    
    .
    

    That gives us an array of all and any global methods called by the onclick attribute, and the arguments passed, so we can replicate it.

    Then we'd just remove all the inline javascript handlers

    $('button').removeAttr('onclick')
    

    and attach our own handlers

    $('button').on('click', function() {...}
    

    Inside those handlers we'd get the stored original function calls and their arguments, and call them.
    As we know any function called by inline javascript are global, we can call them with window[functionName].apply(this-value, argumentsArray), so

    $('button').on('click', function() {
        var element = this;
        $.each(($(this).data('args') || []), function(_,fn) {
            if (fn[0] in window) window[fn[0]].apply(element, fn[1]);
        });
    });
    

    And inside that click handler we can add anything we want before or after the original functions are called.

    A working example

    $('button').each(function(i, el) {
        var funcs = [];
    
    	$(el).attr('onclick').split(';').map(function(item) {
        	var fn     = item.split('(').shift(),
            	params = item.match(/\(([^)]+)\)/), 
                args;
                
            if (params && params.length) {
            	args = params[1].split(',');
                if (args && args.length) {
                    args = args.map(function(par) {
                		return par.trim().replace(/('")/g,"");
                	});
                }
            }
            funcs.push([fn, args||[]]);
        });
        $(el).data('args', funcs);
    }).removeAttr('onclick').on('click', function() {
    	console.log('click handler for : ' + this.id);
      
    	var element = this;
    	$.each(($(this).data('args') || []), function(_,fn) {
        	if (fn[0] in window) window[fn[0]].apply(element, fn[1]);
        });
      
        console.log('after function call --------');
    });
    
    
    
    .
    
    
    

提交回复
热议问题