Pregunta

Me encontré con este problema hoy y lo publiqué en caso de que alguien más tenga el mismo problema.

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

Resulta que para que IE ejecute un clic en un elemento generado dinámicamente, no podemos usar setAttribute.En su lugar, necesitamos establecer la propiedad onclick en el objeto con una función anónima que envuelva el código que queremos ejecutar.

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

MALAS IDEAS:

Tu puedes hacer

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

pero se interrumpirá en IE en modo no estándar según @scunliffe.

No puedes hacer esto en absoluto

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

porque se ejecuta inmediatamente y establece el resultado de runCommand() como el valor del atributo onClick, y usted tampoco puede hacerlo

execBtn.setAttribute("onclick", runCommand);
¿Fue útil?

Solución

Para que esto funcione tanto en FF como en IE, debes escribir en ambos sentidos:


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

gracias a esta publicación.

ACTUALIZAR:Esto es para demostrar que a veces es necesario utilizar setAttribute!Este método funciona si necesita tomar el atributo onclick original del HTML y agregarlo al evento onclick, para que no se anule:

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

Otros consejos

Hay un GRANDE colección de atributos que no se puede configurar en IE usando .setAtributo() que incluye todos los controladores de eventos en línea.

Consulte aquí para obtener más detalles:

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

¡Funciona genial!

Usar ambas formas parece ser innecesario ahora:

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

aparentemente funciona en todos los navegadores actuales.

probado en Firefox, IE, Safari, Opera, Chrome actuales en Windows;Firefox y Epifany en Ubuntu;no probado en Mac o sistemas móviles.

  • Craig:Probaría "document.getElementById(ID).type='password';
  • ¿Alguien ha comprobado el enfoque "AddEventListener" con diferentes motores?

Esta es una función sorprendente para el enlace de eventos compatible con varios navegadores.

Lo tengo de http://js.isite.net.au/snippets/addevent

Con él puedes simplemente hacer Events.addEvent(element, event, function); ¡Y no te preocupes!

Por ejemplo:(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);

Aquí está la función:

// 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};
})();

Si no desea utilizar una función tan grande, esto debería funcionar para casi todos los navegadores, incluido IE:

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

En respuesta a la pregunta de Craig.Tendrás que crear un elemento nuevo y copiar los atributos del elemento anterior.Esta función debería hacer el trabajo:(fuente)

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

O podrías usar jQuery y evitar todos esos problemas:

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

jQuery también se encargará de todos los problemas entre navegadores.

En realidad, hasta donde yo sé, los controladores de eventos en línea creados dinámicamente SÍ funcionan perfectamente en Internet Explorer 8 cuando se crean con el x.setAttribute() dominio;sólo tienes que colocarlos correctamente dentro de tu código JavaScript.Me topé con la solución a tu problema (y al mío) aquí.

Cuando moví todas mis declaraciones que contenían x.appendChild() en sus posiciones correctas (es decir, inmediatamente después del último comando setAttribute dentro de sus grupos), descubrí que CADA setAttribute funcionó en IE8 como se suponía, incluidos todos los atributos de entrada del formulario (incluidos los atributos "nombre" y "tipo", como así como mis controladores de eventos "onclick").

Esto me pareció bastante notable, ya que todo lo que obtuve en IE antes de hacer esto fue basura representada en la pantalla y un error tras otro.Además, descubrí que cada setAttribute también funcionaba en los otros navegadores, por lo que si recuerdas esta sencilla práctica de codificación, estarás listo en la mayoría de los casos.

Sin embargo, esta solución no funcionará si tiene que cambiar algún atributo sobre la marcha, ya que no se pueden cambiar en IE una vez que su elemento HTML se haya agregado al DOM;en este caso, me imagino que habría que eliminar el elemento del DOM y luego recrearlo junto con sus atributos (¡en el orden correcto, por supuesto!) para que funcionen correctamente y no arrojen ningún error.

Escriba la función en línea y el intérprete será lo suficientemente inteligente como para saber que está escribiendo una función.Hágalo así y asumirá que es solo una cadena (que técnicamente lo es).

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+');');
    }
}

Has probado:

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

En algunos casos, los ejemplos enumerados aquí no me funcionaron en Internet Explorer.

Ya que tienes que configurar la propiedad con un método como este (sin corchetes)

HtmlElement.onclick = myMethod;

no funcionará si tiene que pasar un nombre de objeto o incluso parámetros.Para Internet Explorer deberías crear un nuevo objeto en tiempo de ejecución:

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

Funciona también en otros navegadores.

No es relevante para el problema del clic, pero también está relacionado:

Para los atributos HTML cuyo nombre colisiona con palabras reservadas de JavaScript, se elige un nombre alternativo, por ejemplo. <div class=''>, pero div.className, o <label for='...'>, pero label.htmlFor.

En navegadores razonables, esto no afecta setAttribute.Entonces en gecko y webkit llamarías div.setAttribute('class', 'foo'), pero en IE tienes que usar el nombre de propiedad de JavaScript en su lugar, por lo que div.setAttribute('className', 'foo').

¿Ha considerado un detector de eventos en lugar de establecer el atributo?Entre otras cosas, te permite pasar parámetros, lo cual fue un problema que encontré al intentar hacer esto.Aún tienes que hacerlo dos veces para IE y 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");

Simplemente deje que el evento tenga un nombre como "clic" o "mouseover".

Hice esto para solucionarlo y seguir adelante, en mi caso no estoy usando un elemento de 'entrada', en su lugar uso una imagen, cuando intenté configurar el atributo "onclick" para esta imagen experimenté el mismo problema, así que Intenté envolver la imagen con un elemento "a" y hacer que el punto de referencia a la función sea este.

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

Pruebe esto ExecBtn.OnClick = function () {eval ('runCommand ()')};

Para mí funciona.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top