52 votes

Pourquoi une propriété onclick définie avec setAttribute ne fonctionne-t-elle pas dans IE?

Rencontré ce problème aujourd'hui, l'affichage dans le cas où quelqu'un d'autre a le même problème.

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

S'avère pour obtenir IE pour exécuter un onclick sur un générées dynamiquement élément, nous ne pouvons pas utiliser setAttribute. Au lieu de cela, nous avons besoin de définir la propriété onclick sur l'objet avec une fonction anonyme emballage le code à exécuter.

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

LES MAUVAISES IDÉES:

Vous pouvez le faire

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

mais il va se casser dans IE hors-normes de la mode selon @scunliffe.

Vous ne pouvez pas faire cela à tous les

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

parce qu'il s'exécute immédiatement, et définit le résultat de runCommand() à la valeur de l'attribut onClick, ni pouvez-vous faire

execBtn.setAttribute("onclick", runCommand);

53voto

Calvin_il Points 407

pour faire ce travail dans les deux FF et IE, vous devez écrire de deux façons:


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

merci pour ce post.

Mise à JOUR: C'est pour démontrer que, parfois, il est nécessaire d'utiliser setAttribute! Cette méthode fonctionne si vous avez besoin de prendre l'original de l'attribut onclick de l'HTML et l'ajouter à l'événement onclick, de sorte qu'elle ne soit pas remplacée:

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

12voto

Titus Points 51

fonctionne très bien!

utiliser les deux méthodes semble être inutile maintenant:

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

fonctionne apparemment dans tous les navigateurs actuels.

testé sous Firefox, IE, Safari, Opera, Chrome sous Windows; Firefox et Epiphany sur Ubuntu; non testé sur Mac ou systèmes mobiles.

  • Craig: J'essaierais "document.getElementById (ID) .type = 'password";
  • Quelqu'un a-t-il vérifié l'approche "AddEventListener" avec différents moteurs?

11voto

scunliffe Points 30964

Il existe une collection d'attributs LARGE que vous ne pouvez pas définir dans IE à l' aide de .setAttribute (), qui inclut tous les gestionnaires d'événements en ligne.

Voir ici pour plus de détails:

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

6voto

Acorn Points 16562

C'est une incroyable fonction de croix-navigateur compatible liaison d'événements.

Obtenu à partir de http://js.isite.net.au/snippets/addevent

Avec elle, vous pouvez le faire Events.addEvent(element, event, function); et être sans souci!

Par exemple: (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);

Voici la fonction:

// 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 vous ne voulez pas utiliser de telles une grande fonction, ce doit travailler pour presque tous les navigateurs, y compris IE:

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

En réponse à Craig de la question. Vous allez devoir faire un nouvel élément et de copier les attributs de l'ancien élément. Cette fonction devrait faire l'affaire: (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;
}

5voto

cdmckay Points 11234

Ou vous pouvez utiliser jQuery et éviter tous ces problèmes:

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

jQuery s’occupe également de tous les problèmes de navigateur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X