Почему свойство onclick, установленное с setAttribute, не работает в IE?
Начните эту проблему сегодня, разместив ее в том случае, если у кого-то другая проблема.
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() });
но он будет ломаться в IE в нестандартном режиме в соответствии с @scunliffe.
Вы не можете сделать это вообще
execBtn.setAttribute("onclick", runCommand() );
потому что он выполняется немедленно и устанавливает результат runCommand() как значение атрибута onClick, и вы не можете сделать
execBtn.setAttribute("onclick", runCommand);
Ответы
Ответ 1
чтобы сделать эту работу как в FF, так и в IE, вы должны написать оба пути:
button_element.setAttribute('onclick','doSomething();'); // for FF
button_element.onclick = function() {doSomething();}; // for IE
благодаря этот пост.
UPDATE:
Это должно продемонстрировать, что иногда необходимо использовать setAttribute! Этот метод работает, если вам нужно взять исходный атрибут onclick из HTML и добавить его в событие onclick, чтобы он не переопределялся:
// get old onclick attribute
var onclick = button_element.getAttribute("onclick");
// if onclick is not a function, it 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
}
Ответ 2
Существует набор LARGE атрибутов, которые вы не можете установить в IE, используя .setAttribute(), который включает в себя каждый встроенный обработчик событий.
Подробнее см. здесь:
http://webbugtrack.blogspot.com/2007/08/bug-242-setattribute-doesnt-always-work.html
Ответ 3
отлично работает!
использование обоих способов кажется ненужным сейчас:
execBtn.onclick = function() { runCommand() };
очевидно, работает в каждом текущем браузере.
протестирован в текущих Firefox, IE, Safari, Opera, Chrome на Windows; Fire Fox
и Крещение на Убунту; не протестированы на Mac или мобильных системах.
- Крейг: Я бы попробовал "document.getElementById(ID).type = 'password';
- Кто-нибудь проверил подход AddEventListener с разными двигателями?
Ответ 4
Или вы можете использовать jQuery и избегать всех этих проблем:
var execBtn = $("<input>", {
type: "button",
id: "execBtn",
value: "Execute"
})
.click(runCommand);
jQuery позаботится обо всех проблемах с перекрестным браузером.
Ответ 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);
}
В ответ на вопрос Крейга. Вам нужно будет создать новый элемент и скопировать атрибуты старого элемента. Эта функция должна выполнять работу: (source)
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;
}
Ответ 6
Фактически, насколько я знаю, динамически созданные встроенные обработчики событий DO отлично работают в Internet Explorer 8 при создании с помощью команды x.setAttribute()
; вам просто нужно правильно разместить их в своем JavaScript-коде. Я наткнулся на решение вашей проблемы (и мое) здесь.
Когда я переместил все свои утверждения, содержащие x.appendChild()
, в их правильные позиции (т.е. сразу после последней команды setAttribute в своих группах), я обнаружил, что КАЖДЫЙ одиночный setAttribute работал в IE8, как и предполагалось, включая всю форму (включая атрибуты "имя" и "тип", а также мои обработчики событий "onclick" ).
Я нашел это весьма примечательным, так как все, что я получил в IE, прежде чем я это сделал, это мусор, оказанный по экрану, и одна ошибка за другой. Кроме того, я обнаружил, что каждый setAttribute все еще работал в других браузерах, поэтому, если вы просто помните эту простую практику кодирования, в большинстве случаев вам будет хорошо.
Однако это решение не будет работать, если вам нужно изменить любые атрибуты "на лету", поскольку они не могут быть изменены в IE, когда их HTML-элемент добавлен в DOM; в этом случае я бы предположил, что нужно было бы удалить элемент из DOM, а затем воссоздать его и его атрибуты (в правильном порядке, конечно!), чтобы они работали правильно, а не бросали какие-либо ошибки.
Ответ 7
Напишите функцию inline, и интерпретатор достаточно умен, чтобы знать, что вы пишете функцию. Сделайте это так, и он предполагает, что это просто строка (которая технически есть).
Ответ 8
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+');');
}
}
Ответ 9
Вы пытались:
execBtn.setAttribute("onclick", function() { runCommand() });
Ответ 10
В некоторых случаях приведенные здесь примеры не сработали для меня в Internet Explorer.
Поскольку вам нужно установить свойство таким способом (без скобок)
HtmlElement.onclick = myMethod;
он не будет работать, если вам нужно передать имя объекта или даже параметры. Для Internet Explorer вы должны создать новый объект во время выполнения:
HtmlElement.onclick = new Function('myMethod(' + someParameter + ')');
Работает также и с другими браузерами.
Ответ 11
Не относится к проблеме onclick, но также относится:
Для атрибутов html, имя которых совпадает с зарезервированными словами javascript, выбирается альтернативное имя, например. <div class=''>
, но div.className
или <label for='...'>
, но label.htmlFor
.
В разумных браузерах это не влияет на setAttribute
. Так что в gecko и webkit вы бы назвали div.setAttribute('class', 'foo')
, но в IE вместо этого вы должны использовать имя свойства javascript, поэтому div.setAttribute('className', 'foo')
.
Ответ 12
Рассматривали ли вы прослушиватель событий, а не устанавливали атрибут? Помимо прочего, он позволяет вам передавать параметры, которые были проблемой, с которой я столкнулся при попытке сделать это. Вы все равно должны сделать это дважды для 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 up?", "click");
Просто дайте событию имя типа "click" или "mouseover".
Ответ 13
Я сделал это, чтобы обойти это и двигаться дальше, в моем случае я не использую элемент "input", вместо этого я использую изображение, когда я пытался установить атрибут "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);
Ответ 14
Попробуйте это
execBtn.onclick = function() {eval ('runCommand()')};
Для меня это работает.