50

今天遇到这个问题,发帖以防其他人有同样的问题。

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

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

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

坏主意:

你可以做

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

但根据@scunliffe,它会在非标准模式下中断 IE。

你根本不能这样做

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

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

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

13 回答 13

51

要使其在 FF 和 IE 中都能正常工作,您必须以两种方式编写:


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

感谢这篇文章

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

// 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
}
于 2009-02-18T13:48:31.093 回答
11

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

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

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

于 2008-09-19T02:23:37.000 回答
11

效果很好!

现在似乎没有必要同时使用这两种方式:

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

显然适用于每个当前的浏览器。

在 Windows 上的当前 Firefox、IE、Safari、Opera、Chrome 中测试;Ubuntu 上的 Firefox 和 Epiphany;未在 Mac 或移动系统上测试。

  • 克雷格:我会尝试“document.getElementById(ID).type='password';
  • 有没有人用不同的引擎检查过“AddEventListener”方法?
于 2012-03-13T13:05:53.767 回答
5

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

var execBtn = $("<input>", {
       type: "button",
       id: "execBtn",
       value: "Execute"
    })
    .click(runCommand);        

jQuery 也会处理所有跨浏览器的问题。

于 2009-07-01T17:14:34.377 回答
5

这是跨浏览器兼容事件绑定的惊人功能。

从http://js.isite.net.au/snippets/addevent得到它

有了它,您就Events.addEvent(element, event, function);可以无忧无虑!

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

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);

这是功能:

// 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:

if (el.addEventListener) { 
    el.addEventListener('click', function, false); 
} else if (el.attachEvent) { 
    el.attachEvent('onclick', function); 
} 

回答克雷格的问题。您将不得不创建一个新元素并复制旧元素的属性。这个功能应该做的工作:(来源

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;
}
于 2010-06-09T20:17:14.720 回答
4

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

当我将所有包含的语句x.appendChild()移到正确位置时(即紧随其组中的最后一个 setAttribute 命令之后),我发现每一个 setAttribute 都按预期在 IE8 中工作,包括所有表单输入属性(包括“名称" 和 "type" 属性,以及我的 "onclick" 事件处理程序)。

我发现这非常了不起,因为在我这样做之前我在 IE 中得到的只是在屏幕上呈现垃圾,并且一个接一个的错误。此外,我发现每个 setAttribute 在其他浏览器中仍然有效,所以如果你只记得这个简单的编码练习,在大多数情况下你会很好。

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

于 2013-09-24T19:34:31.887 回答
3

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

于 2008-09-18T19:12:08.237 回答
3
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+');');
    }
}
于 2013-02-17T15:31:39.263 回答
2

在某些情况下,此处列出的示例不适用于 Internet Explorer。

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

HtmlElement.onclick = myMethod;

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

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

也适用于其他浏览器。

于 2009-08-14T06:55:13.147 回答
1

你试过了吗:

    execBtn.setAttribute("onclick", function() { runCommand() });
于 2008-09-18T19:07:13.693 回答
1

与 onclick 问题无关,但也相关:

对于名称与 javascript 保留字冲突的 html 属性,将选择替代名称,例如。<div class=''>, 但是div.className, 或者<label for='...'>, 但是label.htmlFor

在合理的浏览器中,这不会影响setAttribute. 所以在 gecko 和 webkit 中你会调用div.setAttribute('class', 'foo'),但在 IE 中你必须使用 javascript 属性名,所以div.setAttribute('className', 'foo').

于 2008-09-18T19:26:05.007 回答
1

您是否考虑过事件侦听器而不是设置属性?除其他外,它允许您传递参数,这是我在尝试执行此操作时遇到的问题。对于 IE 和 Mozilla,您仍然需要执行两次:

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");

只需让事件成为“单击”或“鼠标悬停”之类的名称。

于 2009-03-13T14:19:29.693 回答
1

我这样做是为了绕过它并继续前进,在我的情况下,我没有使用“输入”元素,而是使用图像,当我尝试为该图像设置“onclick”属性时,我遇到了同样的问题,所以我尝试用“a”元素包装图像,并像这样将引用指向函数。

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.png");
imgDeleter.setAttribute('border', "0");

linkDeleter.appendChild(imgDeleter);
于 2009-07-01T17:04:37.417 回答