Pourquoi mon bouton doit-il être cliqué deux fois pour que le gestionnaire d'événement fonctionne la première fois, mais par la suite, juste une fois?

Je souhaite que le visiteur puisse étendre / réduire certaines sections et utilise:

<input onclick="return toggleDiv('xx')" type="button" class="button" value="click here to expand/collapse"/> 

Et dans le j'ai la fonction:

 function toggleDiv(a){ var e=document.getElementById(a); if(!e)return true; if(e.style.display=="none"){ e.style.display="block" } else { e.style.display="none" } return true; } 

La première fois qu'un bouton est cliqué, il ne fonctionne pas, les clics suivants (sur l'un des boutons) fonctionnent correctement.

Il y a une conversation connexe ici: Le bouton doit être cliqué deux fois pour déclencher la fonction

Mais je ne comprends pas la réponse (trop technique ;-), quelqu'un pourrait-il l'expliquer s'il vous plait?

Le style initial sur votre div 'xx' peut causer des problèmes …

Explication

Dites que vous avez une règle de feuille de style configurée pour que vos div s soient initialement cachées. Quelque chose comme:

 div { display: none } 

(… où bien sûr le sélecteur ( div ) sera probablement un peu moins large)

Cela semble fonctionner correctement, en ce que la page sera chargée avec tous vos éléments div cachés ("effondrés"). Cependant, il n'y a pas de valeur réelle pour la propriété style.display sur les éléments euxmêmes – ils ne font que hériter de la valeur de la feuille de style. Donc dans votre code, le test que vous utilisez pour vérifier si l'élément est masqué:

 if(e.style.display=="none"){ 

… échouera, identifiant incorrectement la cible comme étant visible et provoquant la style.display propriété style.display sur "none" (qui n'a aucun effet visible, puisque l'élément a déjà été caché par la feuille de style). Ensuite, la prochaine fois que le bouton est cliqué, la valeur que vous avez définie la dernière fois entraînera le succès du texte, et votre routine définira style.display pour "bloquer".

Le moyen simple de corriger ceci est simplement inverser votre test et vérifier "bloc":

  if(e.style.display=="block"){ e.style.display="none" } else { e.style.display="block" } 

… cependant, cela s'effondrera si vous avez certains éléments configurés pour être initialement visibles: vous rencontrerez le même problème en sens inverse, avec le premier bouton sur le fait de ne pas avoir d'effet visible. Pour un comportement plus robuste, vous devrez tester le style qui est réellement actif sur l'élément:

 function getStyle(el, name) { // the way of the DOM if ( document.defaultView && document.defaultView.getComputedStyle ) { var style = document.defaultView.getComputedStyle(el, null); if ( style ) return style[name]; } // IE-specific else if ( el.currentStyle ) return el.currentStyle[name]; return null; } function toggleDiv(a){ var e=document.getElementById(a); if(!e)return true; if(getStyle(e, "display") == "none"){ e.style.display="block" } else { e.style.display="none" } return true; } 

Ici, nous utilisons une fonction helper, getStyle() , pour récupérer la valeur active d'une manière croisée. Voir aussi: getComputedStyle() , currentStyle

Quelque chose comme ça pourrait fonctionner pour vous. Mais mettez-le dans la tête du document. La fonction de chargement de la fenêtre est importante parce que le DOM doit être chargé avant de pouvoir faire le tour du champ de saisie

 <input id="divOpener" rel="xx" type="button" class="button" value="click here to expand/collapse"/> 

et ça

 window.onload = function(){ // get input field from html var myInput = document.getElementById('divOpener'); // add onclick handler myInput.onclick = function(){ // if you really need to say which div in the document body, you can // add it to the rel or ref etc. attributes then get the value with // get attribute var myDiv = document.getElementById(this.getAttribute('rel')); if(!myDiv) return; if(myDiv.style.display=="none"){ myDiv.style.display="block"; } else { myDiv.style.display="none"; } } } 

Implémentation plus facile

 var a=1; function toggleDiv(xx){ var e=document.getElementById(xx); if(a==1){ e.style.display="block";a=0; } else { e.style.display="none"; a=1; } } 

Pour enregistrer tout le code Javascript supplémentaire pour obtenir le style, etc., une solution simple serait d'ajouter le CSS caché à l'élément lui-même.

 <div class="yourclass" style="display:none;">content</div> 

modifier

J'ai décidé d'expliquer un peu mieux ma réponse. Je suppose que vous n'avez pas caché la div vous vouliez changer par défaut, donc c'était visible, cependant, lorsque vous appelez e.style.display le résultat ne serait pas none plus, ce serait block car le style n'a pas été réglé encore.

Au lieu de cela, vous récupérez une chaîne vide, c'est-à-dire la première fois que vous l'avez cliqué, votre autre déclaration a été déclenchée; L'affichage div a été mis à aucun sur le premier clic, de sorte que le clic suivant récupérerait la valeur car none bien sûr, la changerait alors en block .