关于javascript:为什么使用setAttribute设置的onclick属性在IE中无法正常工作?

关于javascript:为什么使用setAttribute设置的onclick属性在IE中无法正常工作?

Why does an onclick property set with setAttribute fail to work in IE?

今天遇到了这个问题,以防其他人遇到同样的问题而发布。

1
2
3
4
5
var execBtn = document.createElement('input');
execBtn.setAttribute("type","button");
execBtn.setAttribute("id","execBtn");
execBtn.setAttribute("value","Execute");
execBtn.setAttribute("onclick","runCommand();");

结果是让IE在动态生成的元素上运行onclick,我们不能使用setAttribute。相反,我们需要使用匿名函数package对象上的onclick属性,该函数package要运行的代码。

1
execBtn.onclick = function() { runCommand() };

错误提示:

您可以

1
execBtn.setAttribute("onclick", function() { runCommand() });

但是根据@scunliffe,它将以非标准模式在IE中中断。

您根本无法做到这一点

1
execBtn.setAttribute("onclick", runCommand() );

因为它立即执行,并将runCommand()的结果设置为onClick属性值,所以也不能执行

1
execBtn.setAttribute("onclick", runCommand);

要使此功能在FF和IE中均能正常工作,您必须同时编写以下两种方式:

1
2
    button_element.setAttribute('onclick','doSomething();'); // for FF
    button_element.onclick = function() {doSomething();}; // for IE

感谢这篇文章。

更新:
这是为了证明有时需要使用setAttribute!如果您需要从HTML中获取原始的onclick属性并将其添加到onclick事件中,以使其不会被覆盖,则可以使用此方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// get old onclick attribute
var onclick = button_element.getAttribute("onclick");  

// if onclick is not a function, it's not IE7, so use setAttribute
if(typeof(onclick) !="function") {
    button_element.setAttribute('onclick','doSomething();' + onclick); // for FF,IE8,Chrome

// if onclick is a function, use the IE7 method and call onclick() in the anonymous function
} else {
    button_element.onclick = function() {
        doSomething();
        onclick();
    }; // for IE7
}

效果很好!

现在似乎不需要使用两种方式:

1
execBtn.onclick = function() { runCommand() };

显然可以在每个当前浏览器中使用。

在Windows上的当前Firefox,IE,Safari,Opera,Chrome中进行了测试;火狐浏览器
和Ubuntu上的Epiphany;未在Mac或移动系统上进行测试。

  • Craig:我会尝试" document.getElementById(ID).type = \\'password \\';
  • 有没有人使用不同的引擎检查过" AddEventListener"方法?

有一个无法使用.setAttribute()在IE中设置的大型属性集合,其中包括每个内联事件处理程序。

有关详细信息,请参见此处:

http://webbugtrack.blogspot.com/2007/08/bug-242-setattribute-doesnt-always-work.html


对于跨浏览器兼容的事件绑定,这是一个了不起的功能。

从http://js.isite.net.au/snippets/addevent

获得它

有了它,您只需执行Events.addEvent(element, event, function);并放心!

例如:(http://jsfiddle.net/Zxeka/)

1
2
3
4
5
6
7
8
9
10
11
function hello() {
    alert('Hello');
}

var button = document.createElement('input');
button.value ="Hello";
button.type ="button";

Events.addEvent(input_0,"click", hello);

document.body.appendChild(button);

这是函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// We create a function which is called immediately,
// returning the actual function object.  This allows us to
// work in a separate scope and only return the functions
// we require.
var Events = (function() {

  // For DOM2-compliant browsers.
  function addEventW3C(el, ev, f) {
    // Since IE only supports bubbling, for
    // compatibility we can't use capturing here.
    return el.addEventListener(ev, f, false);
  }

  function removeEventW3C(el, ev, f) {
    el.removeEventListener(ev, f, false);
  }

  // The function as required by IE.
  function addEventIE(el, ev, f) {
    // This is to work around a bug in IE whereby the
    // current element doesn't get passed as context.
    // We pass it via closure instead and set it as the
    // context using call().
    // This needs to be stored for removeEvent().
    // We also store the original wrapped function as a
    // property, _w.
    ((el._evts = el._evts || [])[el._evts.length]
        = function(e) { return f.call(el, e); })._w = f;

    // We prepend"on" to the event name.
    return el.attachEvent("on" + ev,
        el._evts[el._evts.length - 1]);
  }

  function removeEventIE(el, ev, f) {
    for (var evts = el._evts || [], i = evts.length; i--; )
      if (evts[i]._w === f)
        el.detachEvent("on" + ev, evts.splice(i, 1)[0]);
  }

  // A handler to call all events we've registered
  // on an element for legacy browsers.
  function addEventLegacyHandler(e) {
    var evts = this._evts[e.type];
    for (var i = 0; i < evts.length; ++i)
      if (!evts[i].call(this, e || event))
        return false;
  }

  // For older browsers.  We basically reimplement
  // attachEvent().
  function addEventLegacy(el, ev, f) {
    if (!el._evts)
      el._evts = {};

    if (!el._evts[ev])
      el._evts[ev] = [];

    el._evts[ev].push(f);

    return true;
  }

  function removeEventLegacy(el, ev, f) {
    // Loop through the handlers for this event type
    // and remove them if they match f.
    for (var evts = el._evts[ev] || [], i = evts.length; i--; )
      if (evts[i] === f)
        evts.splice(i, 1);
  }

  // Select the appropriate functions based on what's
  // available on the window object and return them.
  return window.addEventListener
      ? {addEvent: addEventW3C, removeEvent: removeEventW3C}
      : window.attachEvent
          ? {addEvent: addEventIE, removeEvent: removeEventIE}
          : {addEvent: addEventLegacy, removeEvent: removeEventLegacy};
})();

如果您不想使用这么大的功能,则该功能应该适用于几乎所有浏览器,包括IE:

1
2
3
4
5
if (el.addEventListener) {
    el.addEventListener('click', function, false);
} else if (el.attachEvent) {
    el.attachEvent('onclick', function);
}

回答Craig的问题。您将必须制作一个新元素并复制旧元素的属性。此功能应该可以完成:(source)

1
2
3
4
5
6
7
8
9
10
11
function changeInputType(oldObject, oType) {
  var newObject = document.createElement('input');
  newObject.type = oType;
  if(oldObject.size) newObject.size = oldObject.size;
  if(oldObject.value) newObject.value = oldObject.value;
  if(oldObject.name) newObject.name = oldObject.name;
  if(oldObject.id) newObject.id = oldObject.id;
  if(oldObject.className) newObject.className = oldObject.className;
  oldObject.parentNode.replaceChild(newObject,oldObject);
  return newObject;
}

或者您可以使用jQuery并避免所有这些问题:

1
2
3
4
5
6
var execBtn = $("<input>", {
       type:"button",
       id:"execBtn",
       value:"Execute"
    })
    .click(runCommand);

jQuery也将解决所有跨浏览器的问题。


实际上,据我所知,动态创建的内联事件处理程序在使用x.setAttribute()命令创建时确实可以在Internet Explorer 8中完美运行;您只需要在JavaScript代码中正确放置它们即可。我在这里偶然发现了您的问题(和我的问题)的解决方案。

当我将所有包含x.appendChild()的语句移动到正确的位置时(即,紧跟其组中的最后一个setAttribute命令),我发现每个单独的setAttribute都可以在IE8中正常工作,包括所有形式输入属性(包括" name "和" type "属性,以及我的" onclick "事件处理程序)。

我发现这非常出色,因为在执行此操作之前,我在IE中获得的所有内容都是在整个屏幕上呈现垃圾内容,一个又一个错误。另外,我发现每个setAttribute仍然可以在其他浏览器中使用,因此,如果您只记得这种简单的编码实践,则在大多数情况下都可以使用。

但是,如果您必须即时更改任何属性,则此解决方案将不起作用,因为一旦将HTML元素附加到DOM后就无法在IE中对其进行更改;在这种情况下,我可以想象必须从DOM中删除该元素,然后重新创建它及其属性(当然,以正确的顺序!),它们才能正常工作,并且不会引发任何错误。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function CheckBrowser(){
    if(navigator.userAgent.match(/Android/i)!=null||
        navigator.userAgent.match(/BlackBerry/i)!=null||
        navigator.userAgent.match(/iPhone|iPad|iPod/i)!=null||
        navigator.userAgent.match(/Nokia/i)!=null||
        navigator.userAgent.match(/Opera M/i)!=null||
        navigator.userAgent.match(/Chrome/i)!=null)
        {
            return 'OTHER';
    }else{
            return 'IE';
    }
}


function AddButt(i){
    var new_butt = document.createElement('input');
    new_butt.setAttribute('type','button');
    new_butt.setAttribute('value','Delete Item');
    new_butt.setAttribute('id', 'answer_del_'+i);
    if(CheckBrowser()=='IE'){
        new_butt.setAttribute("onclick", function() { DelElemAnswer(i) });
    }else{
        new_butt.setAttribute('onclick','javascript:DelElemAnswer('+i+');');
    }
}

内联编写函数,解释器足够聪明,可以知道您正在编写函数。这样做,并假设它只是一个字符串(从技术上讲就是这样)。


在某些情况下,此处列出的示例在Internet Explorer中对我来说不起作用。

因为您必须使用这样的方法设置属性(不带括号)

1
HtmlElement.onclick = myMethod;

如果您必须传递对象名称或什至参数,它将不起作用。对于Internet Explorer,您应该在运行时中创建一个新对象:

1
HtmlElement.onclick = new Function('myMethod(' + someParameter + ')');

在其他浏览器上也可以使用。


您尝试过:

1
    execBtn.setAttribute("onclick", function() { runCommand() });

我这样做是为了解决它并继续前进,在我的情况下,当我尝试为此设置" onclick "属性时,我没有使用\\'input \\'元素,而是使用了图像image我也遇到了同样的问题,所以我尝试用" a "元素package图像,并将引用指向这样的函数。

1
2
3
4
5
6
7
8
9
10
var rowIndex = 1;
var linkDeleter = document.createElement('a');
linkDeleter.setAttribute('href',"javascript:function(" + rowIndex +");");

var imgDeleter = document.createElement('img');
imgDeleter.setAttribute('alt',"Delete");
imgDeleter.setAttribute('src',"Imagenes/DeleteHS.webp");
imgDeleter.setAttribute('border',"0");

linkDeleter.appendChild(imgDeleter);

您是否考虑过事件监听器而不是设置属性?除其他外,它使您可以传递参数,这是我在尝试执行此操作时遇到的一个问题。对于IE和Mozilla,您仍然必须做两次:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function makeEvent(element, callback, param, event) {
    function local() {
        return callback(param);
    }

    if (element.addEventListener) {
        //Mozilla
        element.addEventListener(event,local,false);
    } else if (element.attachEvent) {
        //IE
        element.attachEvent("on"+event,local);
    }
}

makeEvent(execBtn, alert,"hey buddy, what's up?","click");

仅让event为" click "或" mouseover "之类的名称。


与onclick问题无关,但也与以下内容有关:

对于名称与javascript保留字冲突的html属性,请选择一个备用名称,例如。 ,但div.className,或<label for='...'>,但label.htmlFor

在合理的浏览器中,这不会影响setAttribute。因此,在gecko和webkit中,您将调用div.setAttribute('class', 'foo'),但是在IE中,您必须改用javascript属性名称,因此,是div.setAttribute('className', 'foo')


推荐阅读

    linux设置命令行长度?

    linux设置命令行长度?,系统,工作,信息,地址,命令,工具,异常,管理,目录,文件,l

    linux设置代替命令?

    linux设置代替命令?,系统,地址,网络,工作,软件,工具,服务,信息,命令,别名,lin

    linux命令设置时区?

    linux命令设置时区?,时间,系统,国家,大陆,命令,时区,时钟,日期,指令,时分,lin

    linux设置命令限制?

    linux设置命令限制?,数字,情况,信息,管理,系统,最新,在线,设备,第一,发行,Lin

    linux设置日志命令行?

    linux设置日志命令行?,异常,系统,实时,日志,管理,信息,对比,项目,名称,情况,L

    linux命令行设置网卡?

    linux命令行设置网卡?,系统,地址,信息,网络,工具,电脑,工作,名称,设备,网卡,l

    linux命令优先级设置?

    linux命令优先级设置?,系统,时间,实时,策略,优先级,分时,管理,周期性,进程,

    linux设置ip命令?

    linux设置ip命令?,地址,系统,密码,设备,命令,服务,工具,网络,网卡,计算机,在L

    linux设置命令是什么?

    linux设置命令是什么?,系统,工作,信息,名称,地址,命令,在线,基础,标准,工具,l

    linux命令设置密码?

    linux命令设置密码?,密码,系统,服务,软件,地址,电脑,流程,管理,用户,命令,问

    linux设置编码命令?

    linux设置编码命令?,系统,数据,发展,文件,字符集,命令,数据库,以下,终端,大

    linux命令行设置语言?

    linux命令行设置语言?,系统,管理,环境,国家,工具,电脑,软件,文化,底部,语言,l

    linux设置壁纸的命令?

    linux设置壁纸的命令?,图片,系统,电脑,照片,位置,终端,颜色,字体,单击,壁纸,

    linux恢复命令行设置?

    linux恢复命令行设置?,系统,工作,密码,信息,工具,地址,电脑,命令,情况,地方,

    linux命令提示设置?

    linux命令提示设置?,系统,工作,地址,信息,命令,软件,目录,管理,变量,文件,Lin

    linux设置命令ip?

    linux设置命令ip?,地址,系统,代码,命令,密码,网卡,终端,计算机,测试,网关,lin

    linux设置man命令?

    linux设置man命令?,信息,系统,工具,工作,地址,命令,基础,地方,基本知识,技术

    linux鼠标设置命令?

    linux鼠标设置命令?,系统,软件,环境,产品,设备,数据,网络,网址,工具,情况,lin

    linux参数设置命令?

    linux参数设置命令?,网络,系统,地址,工作,信息,管理,服务,名称,状态,命令,在l

    linux设置电源的命令?

    linux设置电源的命令?,系统,信息,管理,设备,扩大,时间,设计,电脑,代码,位置,l