2009-03-04 6 views
9

J'ai écrit du Javascript pour permettre la modification d'une liste d'éléments dans un formulaire HTML, y compris l'ajout et la suppression d'éléments. Je l'ai eu dans Firefox. En l'essayant dans Internet Explorer, j'ai constaté que les éléments ajoutés n'étaient pas soumis avec le formulaire. Longue histoire courte ... beaucoup de simplification, débogage, compris quelle ligne déclenche IE pour ignorer la nouvelle entrée de formulaire. Donc, le problème de comportement est résolu.IE ne soumet pas; éléments de formulaire ajoutés dynamiquement; est-ce un bug IE?

Mais maintenant je dois demander: Pourquoi? Est-ce un bug IE?

Voici le code simplifié:

<html> 
<head> 
    <title>Test</title> 
    <script type="text/javascript"> 
     function add() { 
      div = document.getElementById("mylist"); 

      // *** Adding text here works perfectly fine. *** 
      div.innerHTML += " "; 

      e = document.createElement("input"); 
      e.setAttribute("type", "text"); 
      e.setAttribute("name", "field3"); 
      e.setAttribute("value", "--NEWVALUE--"); 
      div.appendChild(e); 

      // *** Adding text here works perfectly fine in Firefox, but for 
      //  Internet Explorer it causes field3 to not be submitted. *** 
      //div.innerHTML += " "; 
     } 
    </script> 
</head> 
<body> 
    <form action="" method="get"> 
     <div id="mylist"> 
      <input type="text" name="field1" value="value1" /> 
      <input type="text" name="field2" value="value2" /> 
     </div> 
     <a href="javascript:" onclick="add()" />Add</a> 
     <input type="submit" value="Submit" /> 
    </form> 
</body> 
</html> 

Pour l'essayer, faire l'évidence: la charge dans IE, cliquez sur Ajouter, cliquez sur Envoyer, regardez ce qui est dans la barre d'adresse. Si vous décommentez la dernière ligne dans add(), IE cessera soudainement de signaler field3. Cela fonctionne très bien dans Firefox.

Des idées? Un esprit curieux veut savoir. (Et comment est-ce que j'ajouterais le texte là si nécessaire, de manière portative, donc IE est heureux?)

Répondre

7

Est-ce un bug IE?

Semble so. Lorsque vous créez un élément < input via des méthodes DOM, IE ne prend pas tout à fait l'attribut 'name'. C'est un peu comme si l'élément se soumettait, mais si vous essayez d'obtenir une représentation 'innerHTML' de l'élément, il disparaît mystérieusement. Cela ne se produit pas si vous créez l'élément en écrivant directement dans innerHTML.

De même, si vous utilisez des méthodes de navigation DOM niveau 0, comme 'myform.elements.x.value', l'accès via le tableau 'elements' peut ne pas fonctionner (de même que l'accès direct 'myform.x'). Dans tous les cas, vous préférerez peut-être getElementById().

Ainsi soit utilisation innerHTML ou utilisent des méthodes DOM; mieux ne pas les mélanger lors de la création de champs de formulaire.

Ceci est documented (see ‘Remarks’) et finalement fixé dans IE8.

Dans tous les cas, ne jamais faire:

div.innerHTML + = '...';

Ceci est seulement le sucre pour syntactique:

div.innerHTML = div.innerHTML + '...';

En d'autres termes, il doit serialise la totalité du contenu HTML enfant de l'élément, puis faire la concaténation de chaîne, puis ré-analyser la nouvelle chaîne de retour dans l'élément, jeter tout le contenu original. Cela signifie que vous perdez tout ce qui ne peut pas être sérialisé: ainsi que les pseudos attributs 'name' d'IE, qui sont aussi des gestionnaires d'événements JavaScript, des écouteurs DOM ou d'autres propriétés personnalisées que vous avez attachées à chaque élément enfant. En outre, le cycle de sérialisation/analyse inutile est lent.

3

IE est très pointilleux sur la modification de certaines propriétés intégrées à l'exécution. Par exemple, le nom d'un élément d'entrée ne peut pas être modifié lorsqu'il est défini.

Deux choses que je voudrais essayer si je vous étais:

  1. Au lieu d'utiliser setAttribute(), essayez de régler les name, type et value propriétés explicitement:

    e.name = "text";

  2. Si ce doesn ne fonctionne pas, vous devrez peut-être inclure tous ces attributs dans l'appel document.createElement():

    var e = document.createElement("<input type='text' name='field'>");

    Ceci peut en fait provoquer une exception dans certains navigateurs. Donc, la meilleure façon de navigateur croix pour aller serait:

.

var e; 
    try { 
    e = document.createElement("<input type='text' name='field'>"); 
    } catch (ex) { 
    e = document.createElement("input"); 
    e.type = 'text'; 
    e.name = 'field'; 
    } 
    e.value = 'value'; 
+0

1 à éviter setAttribute. -1 sur l'appel createElement-with-markup, qui est un bidouillage IE-only extrêmement flippant. – bobince

+0

Je suis d'accord sur le fait qu'il s'agit d'un hack - c'est pourquoi je suggère que l'affiche essaie de définir les propriétés en premier. Si ça ne marche pas, je ne vois pas d'autre moyen de faire ce qu'il veut. – levik

3

Merci bobince et levik pour vos réponses. En utilisant ceux-ci, et un peu plus d'expérimentation, voici mes conclusions:

  1. Oui c'est un bug IE.

  2. IE 8 corrige le bug selon Microsoft: « Internet Explorer 8 et plus tard peut définir l'attribut NAME lors de l'exécution sur les éléments créés dynamiquement avec la méthode createElement. » Le bug est le suivant: Appeler e.setAttribute("name", "field3") seulement kind-of définit le nom. Cela fonctionnera si rien d'autre n'arrive à l'élément, mais s'il est demandé de sérialiser, le nom n'est pas sérialisé. Donc, quand j'ai dit innerHTML += " " qui a forcé une sérialisation, qui a perdu le nom, donc il n'a pas été récupéré lors de la désérialisation. Pas de nom, pas d'inclusion dans la soumission du formulaire.

  3. Solution de contournement n ° 1: e = document.createElement("<input name='field3' />") fonctionnerait, même face à la sérialisation. Solution n ° 2: Plutôt que d'ajouter du texte en utilisant innerHTML + =, je peux ajouter un élément de texte comme ceci: div.appendChild(document.createTextNode(" "));. J'avais pensé qu'il devait y avoir une meilleure façon d'ajouter du texte, et maintenant je le sais :-).

vôtre,
--jsf

+0

J'ajoute plusieurs éléments via document.createElement et chaque élément a plusieurs attributs ... Un attribut étant l'identifiant. J'ai aussi une fonction javascipt sur la même page qui saisit l'ID via document.getElementById (ID) et innerHTML. Comment est-ce que je référencerais ou saisirais l'élément correct basé sur l'identification d'un élément qui a été créé dynamiquement?J'utilise IE 8..works dans Firefox :) – Jim