2009-09-24 22 views
13

Este puede ser el error más oscuro que he encontrado en muchos años de trabajo con JavaScript y cualquier versión de Internet Explorer. Estamos usando YUI 2.7 para algunos de los métodos (no) de conveniencia. Suspiro, lo que haría por jQuery ....JavaScript: Error de visibilidad en Internet Explorer al establecer el foco en un elemento de entrada

Esto afecta a Internet Explorer 6 e Internet Explorer7. Internet Explorer 8 se comporta correctamente. Todos los demás navegadores también se comportan correctamente.

Problema: Cuando me puse el foco en un elemento particular, me sale el siguiente error:

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

así que tengo un div llamado 'complemento comentario-login-overlay' que contiene el elemento de entrada. Este div es display: none hasta que el usuario haga clic en uno de los varios enlaces llamados 'login'.

El siguiente es el código JavaScript que estoy usando que selecciona los enlaces de "inicio de sesión", que mueve la posición de 'add-comment-login-overlay' en el DOM, establece display: block, luego establece el foco en el primer campo de entrada en la superposición. Es este proceso de establecer el foco el que está causando el error que escribí arriba.

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

Puedo absolutamente confirmar que la superposición div es completamente visible. Puedo mirarlo. He agregado un setInterval timer para medir lo que está sucediendo y no tiene ningún efecto. En un momento tuve 10 segundos entre el momento en que la superposición fue visible y cuando se llamó a focus() y aún se produce el error. Aparte del error, el formulario es completamente funcional además de este error.

Esta es una versión simplificada del código HTML de superposición como referencia.

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

Respuesta

17

Este es un viejo error en IE (me alegra saber que está corregido en 8). No sé la causa oficial, pero yo creo que tiene que ver con IE no volver a pintar el DOM hasta después de que el contexto de ejecución se ha completado, por su parte tratando de focus() el elemento mientras se piensa que todavía está oculta:

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) 

que he tenido que suceda-a-tiempo muchos, incluyendo con jQuery. No es culpa de ninguna biblioteca. El setTimeout siempre ha funcionado para mí.

+0

Estaba teniendo este problema en IE 8, pero creo que mi problema tenía que ver con el hecho de que el formulario se abría con una llamada a window.showModalDialog (...).Esta solución alternativa funcionó perfectamente para mí. ¡Gracias! – Sanjamal

+0

¡Esto funcionó para mí en un problema de DotNetNuke! ¡Gracias Crescent Fresh! –

+0

Aparentemente todavía existe en IE11, solo que esta vez se requiere un temporizador de 500 ms para su efectividad. – Jason

1

Establezca el foco en un bloque try/catch.

+0

Desafortunadamente, no estoy tratando de poner un pedazo de chicle en la presa con fugas para ponerle un parche. Me gustaría descubrir qué demonios está causando esto. – Geuis

+5

Bueno, en mi opinión, una pieza de chicle en ie6 es la mejor práctica. Este navegador está lleno de errores extraños que no intentas comprender, solo intenta hacer que tu aplicación funcione. No he probado el enfoque de Iod3n, pero si funciona, si no perjudica el rendimiento en absoluto, debe parchar su aplicación y salir a tomar una cerveza. – GmonC

0

Supongo que la llamada insertAfter confunde el DOM de IE. ¿Puedes probar el código sin la llamada insertAfter? ¿Falla de la misma manera? Si no, ¿hay alguna otra manera en la que puedas lograr el mismo resultado? Tal vez copiar los nodos y eliminar los originales, en lugar de mover los nodos?

Cuestiones relacionadas