2009-09-24 12 views
13

Questo potrebbe essere il bug più oscuro che abbia mai incontrato in molti anni di lavoro con JavaScript e qualsiasi versione di Internet Explorer. Usiamo YUI 2.7 per alcuni dei (non) metodi di convenienza. Sigh, cosa farei per jQuery ....JavaScript: errore di visibilità in Internet Explorer quando si imposta lo stato attivo su un elemento di input

Ciò si ripercuote su Internet Explorer 6 e Internet Explorer7. Internet Explorer 8 si comporta correttamente. Anche tutti gli altri browser funzionano correttamente.

Problema: Quando ho creato focus su un particolare elemento, ottengo il seguente errore:

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

Così ho un div chiamato 'add-commento-login-overlay' che contiene l'elemento di input. Questo div è visualizzato: nessuno fino a quando l'utente non fa clic su uno dei numerosi collegamenti chiamati 'login'.

Quanto segue è il codice JavaScript che sto utilizzando che seleziona i collegamenti "login", che sposta la posizione di "add-comment-login-overlay" nel DOM, imposta display: block, quindi imposta focus su il primo campo di input nella sovrapposizione. È questo processo di messa a fuoco che sta causando l'errore che ho scritto sopra.

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

Posso assolutamente confermare che il div overlay è completamente visibile. Posso guardarlo. Ho aggiunto un timer setInterval per misurare cosa sta succedendo e non ha alcun effetto. A un certo punto ho avuto 10 secondi tra il momento in cui l'overlay era visibile e quando è stato chiamato focus() e l'errore si verifica ancora. Oltre all'errore, il modulo è completamente funzionale diverso da questo errore.

Questa è una versione semplificata del codice HTML di sovrapposizione come riferimento.

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

risposta

17

Questo è un vecchio bug heck in IE (felice di sapere che è stato risolto in 8). Non conosco la causa ufficiale, ma credo che abbia a che fare con IE non riverniciatura il DOM fino a dopo il contesto di esecuzione è completa, nel frattempo cercando di focus() l'elemento mentre pensa che sia ancora nascosto:

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) 

ho avuto accadere molti-a-time, anche con jQuery. Non è colpa di nessuna libreria. Il setTimeout ha sempre funzionato intorno a me per me.

+0

Stavo avendo questo problema in IE 8, ma credo che il mio problema avesse a che fare con il fatto che il modulo veniva aperto da una chiamata a window.showModalDialog (...).Questa soluzione ha funzionato perfettamente per me. Grazie! – Sanjamal

+0

Questo ha funzionato per me su un problema di DotNetNuke! Grazie Crescent Fresh! –

+0

Apparentemente esiste ancora in IE11, solo che questa volta è necessario un timer di 500ms per l'efficacia. – Jason

1

Impostare lo stato attivo in un blocco try/catch.

+0

Sfortunatamente non sto cercando di mettere un pezzo di gomma nella diga che perde per ricoprirlo. Mi piacerebbe scoprire cosa diavolo sta causando questo. – Geuis

+5

Bene, a mio parere, un pezzo di gomma in ie6 è la migliore pratica. Questo browser è pieno di strani bug che non provi a capirli, basta provare a far funzionare la tua app. Non ho testato l'approccio Iod3n, ma se funziona, se non danneggia le prestazioni, dovresti applicare una patch alla tua app per una birra. – GmonC

0

Ad una ipotesi, direi che la chiamata insertAfter confonde il DOM IE. Puoi testare il codice senza la chiamata insertAfter? Fallisce allo stesso modo? Se no, c'è un altro modo per ottenere lo stesso risultato? Forse copiare i nodi e cancellare gli originali, invece di spostare i nodi?

Problemi correlati