【问题标题】:how to get javaScript event source element?如何获取javascript事件源元素?
【发布时间】:2012-05-03 09:25:35
【问题描述】:

有没有办法检索内联 JavaScript 调用的元素源?

我有一个这样的按钮:

<button onclick="doSomething('param')" id="id_button">action</button>

注意:

  • 按钮是从服务器生成的
  • 我无法修改生成过程
  • 页面上生成了几个按钮,我只能在客户端进行控制。

我尝试过的:

function doSomething(param){
    var source = event.target || event.srcElement;
    console.log(source);
}

在萤火虫上我得到事件未定义

编辑: 在一些答案之后,使用 jQuery 覆盖事件处理是非常可以接受的。我的问题是如何在不知道函数名称的情况下使用原始参数调用原始 onClick 函数。

代码:

<button onclick="doSomething('param')" id="id_button1">action1</button>
<button onclick="doAnotherSomething('param1', 'param2')" id="id_button1">action2</button>.
<button onclick="doDifferentThing()" id="id_button3">action3</button>
.
.
and so on..

所以覆盖将是:

$(document).on('click', 'button', function(e) {
  e.preventDefault();
  var action = $(this).attr('onclick');
  /**
   * What to do here to call
   * - doSomething(this, 'param'); if button1 is clicked
   * - doAnotherSomething(this, 'param1', 'param2'); if button2 is clicked
   * - doDifferentThing(this); if button3 is clicked
   * there are many buttons with many functions..
   */
});

【问题讨论】:

  • 我在那儿!此解决方案假定我必须将事件参数传递给我的函数,或者 按钮是从服务器生成的
  • 传递事件参数是 Firefox 的要求。跨浏览器解决方案需要事件参数。
  • @skafandri:如果您运行 JavaScript,您可以修改按钮,无论其源代码是如何生成的。

标签: javascript jquery html


【解决方案1】:

你的 html 应该是这样的:

<button onclick="doSomething" id="id_button">action</button>

并将您的输入参数重命名为这样的事件

function doSomething(event){
    var source = event.target || event.srcElement;
    console.log(source);
}

会解决你的问题。

作为旁注,我建议看看 jQuery 和不显眼的 javascript

【讨论】:

  • 按钮是从服务器生成的,我无法修改生成过程
  • @skafandri:如果您可以修改脚本,为什么不呢?除此之外,当他建议查看 unobtrusive JavaScript 时,他是对的 - 阅读会告诉您 HTML 是不好的做法。
  • 我知道!在我自己的脚本中,我总是使用不显眼的 javascript,但在这种情况下,我正在构建现有框架的前端应用程序..
  • 不要忘记使用 .value 属性来获取项目的实际值。如console.log(source.value);
  • 只会添加我的回答中提到的跨浏览器功能。
【解决方案2】:

您应该将生成的 HTML 更改为不使用内联 javascript,并改用 addEventListener。

如果您不能以任何方式更改 HTML,您可以获取 onclick 属性、使用的函数和参数,然后通过删除 @987654323 将其“转换”为不显眼的 javascript @ 处理程序,并使用事件侦听器。

我们首先从属性中获取值

$('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') );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button onclick="doSomething('param')" id="id_button1">action1</button>
<button onclick="doAnotherSomething('param1', 'param2')" id="id_button1">action2</button>.
<button onclick="doDifferentThing()" id="id_button3">action3</button>

这为我们提供了一个由 onclick 属性调用的所有和任何全局方法的数组,以及传递的参数,因此我们可以复制它。

然后我们就删除所有的内联 javascript 处理程序

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

并附加我们自己的处理程序

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

在这些处理程序中,我们将获取存储的原始函数调用及其参数,然后调用它们。
我们知道内联javascript调用的任何函数都是全局的,我们可以用window[functionName].apply(this-value, argumentsArray)调用它们,所以

$('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]);
    });
});

在该点击处理程序中,我们可以在调用原始函数之前或之后添加任何我们想要的内容。

一个工作示例

$('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 --------');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<button onclick="doSomething('param');" id="id_button1">action1</button>
<button onclick="doAnotherSomething('param1', 'param2')" id="id_button2">action2</button>.
<button onclick="doDifferentThing()" id="id_button3">action3</button>

<script>
	function doSomething(arg) { console.log('doSomething', arg) }
    function doAnotherSomething(arg1, arg2) { console.log('doAnotherSomething', arg1, arg2) }
    function doDifferentThing() { console.log('doDifferentThing','no arguments') }
</script>

【讨论】:

  • 有很多按钮,有些按钮是在ajax调用之后生成的......我对ID一无所知(为了解释更多,我正在写一个Magento模块......)
  • 现在您的函数没有范围,您需要以某种方式添加范围,如果您无法修改按钮元素,则必须以某种方式覆盖它,请参阅我修改后的答案。
  • 我可以使用 jQuery 覆盖,只要我知道如何调用原始 onClick 函数(doSomething 就是一个例子,有几个函数有几个参数)
  • 这取决于,您可以使用 $(this).attr('onclick'); 获取 onclick 函数,并且只需构造一个包含 this 的新函数调用来获取范围,您可能必须使用 eval() 来运行该函数,然后是函数在 DOM 中的位置的问题,假设它们是内联的等等。总的来说,IMO 并不是一个很好的解决方案。
  • 请检查我的编辑 :-),它从 onclick 函数构造函数名称,并添加 this,如果可能的话,我可能会重新定义函数,以避免 eval() 调用,但应该可以工作。
【解决方案3】:

跨浏览器解决方案

我相信@slipset 的解决方案是正确的,它不需要 jQuery,但是它还没有跨浏览器准备好。

根据Javascript.info,事件(当在标记事件之外引用时)一旦您确保使用以下简单行定义它就可以跨浏览器:event = event || window.event。

所以完整的跨浏览器就绪函数如下所示:

function logMySource(param){
  event = event || window.event;
  var source = event.target || event.srcElement;
  console.log("sourceID= "+source.id,"\nsourceTagName= "+source.tagName,"\nparam= "+param);
}
&lt;button onclick="logMySource('myVariable')" id="myID"&gt;action&lt;/button&gt;

试试吧! 我已经包含了来源有用信息的返回。

【讨论】:

    【解决方案4】:

    调用函数时可以传递this

    <button onclick="doSomething('param',this)" id="id_button">action</button>
    
    <script>
        function doSomething(param,me){
    
        var source = me
        console.log(source);
    }
    </script>
    

    【讨论】:

    • 按钮是从服务器生成的,我无法修改生成过程
    【解决方案5】:

    试试这样的:

    <html>
      <body>
    
        <script type="text/javascript">
            function doSomething(event) {
              var source = event.target || event.srcElement;
              console.log(source);
              alert('test');
              if(window.event) {
                // IE8 and earlier
                // doSomething
               } else if(e.which) {
                // IE9/Firefox/Chrome/Opera/Safari
                // doSomething
               }
            }
         </script>
    
        <button onclick="doSomething('param')" id="id_button">
          action
        </button>
    
      </body>      
    </html>
    

    【讨论】:

      【解决方案6】:

      使用.live()

       $(selector).live(events, data, handler); 
      

      从 jQuery 1.7 开始,不推荐使用 .live() 方法。使用 .on() 附加事件处理程序。

      $(document).on(events, selector, data, handler);  
      

      【讨论】:

      • 他为什么要使用live()而不是普通的bind()?
      • 我在页面上有几个按钮,按钮有不同的onClick函数,我可以使用$('body').on(event,'button', function(){});没问题,你能告诉我如何执行 onClick 并将 $(this) 传递给它吗?
      • @Bergi 是的,他是对的,一些按钮在 Ajax 调用后被检索。
      • @Pranav:我知道区别,所以我想知道当问题只是传递事件对象时,为什么你会推荐更复杂的方法。好的,因为我们知道有很多按钮,有些甚至是动态附加的,所以显然是可取的。
      • @Bergi:是的,你是对的,因为按钮是动态生成的,所以我建议使用 live() 而不是 bind()。
      猜你喜欢
      • 1970-01-01
      • 2014-01-19
      • 1970-01-01
      • 1970-01-01
      • 2023-01-05
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多