2009-03-31 10 views
21

Me gustaría que el navegador actúe como si el usuario hubiera presionado la tecla Tab cuando hacían clic en algo. En el controlador de clic que he probado los siguientes enfoques:Simulando una pestaña presionando una tecla usando JavaScript

var event = document.createEvent('KeyboardEvent'); 
event.initKeyEvent("keypress", true, true, null, false, false, false, false, 9, 0); 
this.input.focus()[0].dispatchEvent(event); 

y jQuery:

this.input.focus().trigger({ type : 'keypress', which : 9 }); 

... que tomé de here.

El primer enfoque parece ser la mejor opción, pero no funciona del todo. Si cambio los dos últimos parámetros a 98, 98, de hecho, se escribe una 'b' en el cuadro de entrada. Sin embargo, 9, 0 y 9, 9 (el primero de los cuales Tomé derecha desde el sitio web MDC) tanto dame estos errores en Firebug bajo FF3:

Permission denied to get property XULElement.popupOpen 
[Break on this error] this.input.focus()[0].dispatchEvent(event); 

Permission denied to get property XULElement.overrideValue 
[Break on this error] this.input.focus()[0].dispatchEvent(event); 

Permission denied to get property XULElement.selectedIndex 
[Break on this error] this.input.focus()[0].dispatchEvent(event); 

Permission denied to set property XULElement.selectedIndex 
[Break on this error] this.input.focus()[0].dispatchEvent(event); 

he oído tales (sin una definición clara de 'tales') eventos son 'no confiables', lo que podría explicar estos errores.

El segundo enfoque causa cualquier valor que puse como evento.que se pase como evento.que, pero sin ningún efecto (incluso si uso 98 en lugar de 9, no se escribe 'b' en el cuadro). Intento establecer event.data en el objeto que estoy pasando, termina indefinido cuando se desencadena el evento. Lo que sigue es el código que estoy usando para ver eso:

$('#hi').keypress(function(e) { 
    console.log(e); 
}); 

¿Alguna otra idea?

+0

¿Qué desea invocar? ¿Estás tratando de moverlos a la siguiente entrada? – hunter

+0

Sí. Pero la siguiente 'entrada' no es necesariamente un elemento de entrada u otro elemento con tabulación natural. Tampoco es necesariamente antinatural-tabstopped (es decir, $ ("[tabindex]")). Físicamente presionando la pestaña (o Mayús + pestaña) hace exactamente lo que quiero ... – Kev

+0

Gracias por esto. Solo me interesó el primer ejemplo de código de tu pregunta, que realmente me ayudó :) –

Respuesta

4

La solución con la que terminé fue crear un divisor de "foco ladrador" (con tabindex = -1 - puede tener el foco pero no se puede tabular al principio) en cualquier lado del área en la que quiere administrar manualmente el enfoque. Luego puse un oyente de evento de burbujeo verdadero para enfoque y desenfoque en toda el área. Cuando se produce un foco en el área, los valores de tabindex se cambian a -1, y cuando se produce cualquier desenfoque, se cambian a 0. Esto significa que mientras se enfoca en el área, puede desplazarla o desplazarla fuera de ella y terminan correctamente en otros elementos de la página o en los elementos de la IU del navegador, pero tan pronto como se enfoca, los ladrones de foco se vuelven tabbles, y al enfocar configuran el área manual correctamente y derivan el foco hacia el elemento que está al final, como si hubiera hecho clic en un extremo u otro del área manual.

1

En realidad, creo que hay una manera, incluso si es una PITA importante. Puedo asegurarme de que cada elemento, aunque sea de forma natural un tab-stop, tenga un Xtabindex, de alguna manera en el orden correcto, incluso cuando vaya a aparecer en los widgets de otras personas y use jQuery para agregarlos después del hecho, en lugar de ser capaz de especificarlo directamente en el HTML u otro código de construcción inicial. Entonces, toda mi forma tendrá un tabindex real. Si bien tiene el foco, absorberá las pulsaciones de tecla, y si son tabulador o shift + tabulador, mueva el foco falso basado en Xtabindex. Si se presiona la pestaña en el último elemento (o cambio + pestaña en el primero) en el formulario, no se engullirá la pulsación de tecla, lo que permite que el navegador se enfoque adecuadamente en otros elementos de la UI del navegador o la página fuera del formulario con el teclado.

Solo puedo adivinar qué tipo de efectos colaterales involuntarios presentará este enfoque.

En realidad, ni siquiera es una solución, porque todavía no puedo falsificar una pestaña en el último elemento que la usa.

+0

http: // lists .whatwg.org/htdig.cgi/whatwg-whatwg.org/2008-December/017980.html planteó un punto interesante: "Pero entonces, ¿qué sucede si el agente de usuario no hace cosas utilizando un ciclo, sino que utiliza la administración de foco direccional? como muchos teléfonos? " – Kev

3

Esta es la solución que utilicé en nuestra aplicación web para dos controles personalizados, un calendario emergente y un selector de unidad de peso emergente/valor (clic en el cuadro de texto hace aparecer una div con dos casillas)

function tab_focus(elem) 
    var fields = elem.form.getElements() 
    for(var i=0;i<fields.length;i++) { 
    if(fields[i].id == elem.id){ 
     for(i=i+1;i<fields.length;i++){ 
     if(fields[i].type != 'hidden'){ 
      fields[i].focus() 
      return  
     } 
     } 
     break; 
    } 
    } 
    elem.form.focusFirstElement(); 
} 

Esto está utilizando el marco Prototype y espera un elemento extendido (es decir, $ ('thing_id')) como su parámetro.

Obtiene la forma a la que pertenece el elemento y recorre los elementos de la forma hasta que se encuentra.

Luego busca el primer elemento que no está oculto y lo enfoca.

Si no hay elementos después en el formulario, mueve el foco hacia atrás al primer elemento del formulario. En su lugar, podría encontrar el siguiente formulario en la página a través de document.forms, pero la mayoría de nuestras páginas usan un solo formulario.

+0

La cuestión es que algunos de los elementos de IU que se pueden enfocar no son elementos de formulario, ya que son widgets personalizados. – Kev

+1

Para usuarios de jquery, reemplace la primera línea de esta función con: var fields = $ ('form') [0]; Para recorrer los elementos del formulario. – eniac

0

Creo que esos errores son de autocompletar. Usted puede ser capaz de apagarlos mediante el establecimiento, antes de distribuir el evento, el atributo de autocompletar en 'off'

setAttribute('autocomplete','off') 
1

he creado un simple jQuery plugin cual no resuelve este problema. Utiliza el selector ': tabbable' de jQuery UI para encontrar el siguiente elemento 'tabbable' y lo selecciona.

Ejemplo de uso:

// Simulate tab key when element is clicked 
$('.myElement').bind('click', function(event){ 
    $.tabNext(); 
    return false; 
}); 
Cuestiones relacionadas