2009-09-24 4 views
13

Il s'agit probablement du bug le plus obscur que j'ai rencontré pendant de nombreuses années de travail avec JavaScript et toute version d'Internet Explorer. Nous utilisons YUI 2.7 pour certaines des méthodes (non) de commodité. Soupir, ce que je ferais pour jQuery ....JavaScript: erreur de visibilité dans Internet Explorer lors de la mise au point sur un élément d'entrée

Cela affecte Internet Explorer 6 et Internet Explorer7. Internet Explorer 8 se comporte correctement. Tous les autres navigateurs se comportent également correctement.

Problème: Quand je mets l'accent sur un élément particulier, je reçois l'erreur suivante:

Can't move focus to the control because it is invisible, not enabled, or of a type that does not accept focus. 

J'ai donc div appelé « add-comment-login-overlay » qui contient l'élément d'entrée. Cette div est display: none jusqu'à ce que l'utilisateur clique sur l'un des liens appelés 'login'. Voici le code JavaScript que j'utilise qui sélectionne les liens 'login', qui déplace la position de 'add-comment-login-overlay' dans le DOM, définit display: block, puis active le focus le 1er champ d'entrée dans la superposition. C'est ce processus de mise au point qui provoque l'erreur que j'ai écrit ci-dessus.

//Get Login links in comment forms. 
links = YAHOO.util.Dom.getElementsByClassName('addCommentLoginLink'); 

//Set click event for login links. 
YAHOO.util.Event.addListener(links, "click", function(el){ 

    //Stop link. 
    YAHOO.util.Event.preventDefault(el); 

    //Move login overlay in DOM. 
    if(el.srcElement){ 
     var target = el.srcElement; 
    }else{ 
     var target = el.currentTarget; 
    } 

    YAHOO.util.Dom.insertAfter(overlay, target.parentNode.parentNode.parentNode.parentNode); 

    //Set to visible. 
    YAHOO.util.Dom.setStyle(overlay,'display', 'block'); 

    //Set focus to username field. 
    document.getElementById('add-comment-login-overlay-username-input').focus(); 
}); 

Je peux absolument confirmer que le div overlay est complètement visible. Je peux le regarder. J'ai ajouté un timer setInterval pour mesurer ce qui se passe et cela n'a aucun effet. À un moment donné, j'avais 10 secondes entre le moment où la superposition était visible et quand focus() a été appelé et l'erreur se produit toujours. Autre que l'erreur, le formulaire est complètement fonctionnel autre que cette erreur.

Il s'agit d'une version simplifiée du code HTML de superposition comme référence.

<div id="add-comment-login-overlay" class="add-comment-login-overlay" style="display: block;"> 
    <div class="add-comment-login-overlay-content clearfix"> 
     <div class="add-comment-login-overlay-signin clearfix"> 
      <input type="text" tabindex="2001" id="add-comment-login-overlay-username-input"/> 
      <input type="password" tabindex="2002" id="add-comment-login-overlay-password-input"/> 
     </div> 
    </div> 
</div> 

Répondre

17

Ceci est un vieux bug dans IE IE (heureux de savoir qu'il est corrigé en 8). Je ne connais pas la cause officielle, mais je crois qu'il doit faire avec IE ne repeindre les DOM jusqu'à ce que le contexte d'exécution est terminée, quant à lui essayer de focus() l'élément alors qu'il pense qu'il est toujours caché:

function calledAtSomePoint() { // begin execution 

    // ... 

    element.style.display = ''; // show container 
    input.focus(); // IE thinks element is hidden 

    // end of execution, IE repaints the DOM but it's too late 
} 

The solution is to use setTimeout:

setTimeout(function() { 
    document.getElementById('add-comment-login-overlay-username-input').focus() 
}, 0) 

Je l'ai eu beaucoup, arrive à temps, y compris avec jQuery. Ce n'est pas la faute de n'importe quelle bibliothèque. Le setTimeout a toujours travaillé autour de moi pour moi.

+0

J'avais ce problème dans IE 8, mais je crois que mon problème avait à voir avec le fait que le formulaire était ouvert par un appel à window.showModalDialog (...).Cette solution de contournement a parfaitement fonctionné pour moi. Merci! – Sanjamal

+0

Cela a fonctionné pour moi sur un problème de DotNetNuke! Merci Crescent Fresh! –

+0

Apparemment, il existe toujours dans IE11, mais cette fois une minuterie de 500ms requis pour l'efficacité. – Jason

1

Définissez le focus dans un bloc try/catch.

+0

Malheureusement, je n'essaie pas de mettre un morceau de chewing-gum dans le barrage qui fuit pour le réparer. Je voudrais savoir ce que le diable provoque. – Geuis

+5

Eh bien, à mon avis, un morceau de gomme dans IE6 est la meilleure pratique. Ce navigateur est plein de bugs étranges que vous n'essayez pas de comprendre, vous essayez simplement de faire fonctionner votre application. Je n'ai pas testé l'approche d'Iod3n, mais si cela fonctionne, si cela ne nuit en rien à la performance, vous devriez patcher votre application et sortir pour une bière. – GmonC

0

En supposant, je dirais que l'appel insertAfter confond le DOM IE. Pouvez-vous tester le code sans l'appel insertAfter? Est-ce qu'il échoue de la même manière? Sinon, y a-t-il une autre façon d'obtenir le même résultat? Peut-être copier les nœuds et supprimer les originaux, au lieu de déplacer les nœuds?

Questions connexes