如何安全地将所有内联事件传输到jQuery元素绑定事件?

时间:2013-05-07 06:02:36

标签: jquery

现在首先关闭每个人都给出答案“不要使用内联事件”,让我首先说我没有使用内联事件,我只是想清理其他人编码而不能进入并修复所有代码。

所以,我编写了一个函数来将内联事件转移到jQuery事件,但它部分使用了新的Function()。它有效,但我知道它可以通常清理得更好。

var transferInlineEvents = function(element){

    var attributes = $(element).get(0).attributes;
    $(attributes).each(function(i){
        if (/^on/.test(this.name)) {
            var handler = this.name.replace(/^on/, '');
            var evt = this.value;
            evt = evt.replace('$(this)', "$('#"+$(element).attr('id')+"')");
            $(element).on(handler, function(){
                var newEvent = (jQuery.support.boxModel) ? new Function([evt]) : evt;
                newEvent();
            });
            $(element).removeAttr(this.name);
        }
    });

};

这样做,并且基本上可以做到这一点:

<input type="text" name="myinput" id="myinput" onclick="$(this).val('');" value="Enter your name..." />

进入这个:

<input type="text" name="myinput" id="myinput" value="Enter your name..." />

$('#myinput').on('focus', function(){
    $('#myinput').val('');
});

我不知道如何不使用新功能,因此它适用于所有浏览器,我不知道如何制作,所以我不需要替换它。

感谢任何帮助。

3 个答案:

答案 0 :(得分:3)

这将花费你一些努力,但不会给你买任何东西。

不应用内联事件处理程序的一点是将语义(标记)与页面功能(脚本)分开。另一种是将脚本执行推迟到所有其他页面加载活动发生之后。

在页面加载后开始操作事件处理程序后,这些目标都无法实现。如果你继续使用这种方法,你的源代码中仍然存在混乱(如果你查看源代码我保证你仍会看到内联处理程序),浏览器仍会将这些处理程序附加到DOM中的元素在删除并重新附加它们之前

真正清理事物的唯一方法是在源代码中,在后端执行此操作。

答案 1 :(得分:0)

根据你的报价:Any help is appreciated.

选项一

请注意以下代码,使用eval,这不是JavaScript编程的一部分,并且已知不安全。

我认为这足够跨浏览器:

var transferInlineEvents = function(element){

    var attributes = $(element).get(0).attributes;
    $(attributes).each(function(i){
        if (/^on/.test(this.name)) {
            var handler = this.name.replace(/^on/, '');
            var evt = this.value;
            evt = evt.replace('$(this)', "$('#"+$(element).attr('id')+"')");
          $(element).on(handler, function() {
                console.log('event activated', evt);
                var newEvent = eval('(function(){'+evt+'});');
                newEvent();
            });
            $(element).removeAttr(this.name);
        }
    });

};

$("input").each(function(i, element) {
    transferInlineEvents(element);
});

您可以找到演示here

选项二

另一种方法,如果你知道你的内联代码很简单而且不那么复杂,那就是regexp检查内联函数的每个参数,并为每个参数创建一个单独的函数。

这通常是安全的,但它不适用于复杂的代码。

var transferInlineEvents = function(element){

    var attributes = $(element).get(0).attributes;
    $(attributes).each(function(i){
       if (/^on/.test(this.name)) {
          var handler = this.name.replace(/^on/, '');
          var evt = this.value;
          var actions = evt.split(';');
          var functions = [];
          for ( var action = 0; action < actions.length; action++ ) {
             var methods = actions[action].split('.');
             for ( var method = 1; method < methods.length; method++ ) {
               /* If it is val attribute */
               if ( /^val\(/.test(methods[method]) ) {                 
                 var value = methods[method].substr(4).replace(/^('|")/, '').replace(/\)$/, '').replace(/('|")$/, '');
                 functions.push( function() { $('#'+element.id).val(value) } );
               }
             }
          }
          if ( functions.length > 0 ) { 
            $(element).on(handler, function() {
              for ( fn = 0; fn < functions.length; fn++ ) {
                console.log('fireing up function');
                functions[fn]();
              }
            });
            $(element).removeAttr(this.name);
          }
        }
    });

};

演示:http://jsbin.com/osevop/1/edit

答案 2 :(得分:0)

经过大量阅读和搜索后,如果不使用eval()或新的Function(),似乎无法做到这一点。而且由于后者稍微好一些,我会继续这样做。另外,请记住,eval()和new Function()只有当它们是可由用户操作的输入的一部分时才是不安全的。在我的情况下情况并非如此,所以我认为这是安全的。

这会将带有'on'前缀的所有内联事件转换为jQuery绑定事件并删除内联事件。

;(function ($) {
    $.fn.transferInlineEvents = function () {
        var el = this;
        var attributes = el.get(0).attributes;
        $(attributes).each(function(i){
            var oEvent = this.name;
            var oFunc = $.trim(this.value);
            if (/^on/.test(oEvent)) {
                var nEvent = oEvent.replace(/^on/, '');
                var nFunc = new Function(oFunc);
                el.removeAttr(oEvent);
                el.bind(nEvent, nFunc);
            }
        });
    };
})(jQuery);

在此测试:http://jsfiddle.net/9vXtm/2/