2011-01-03 13 views
6

Tengo este problema (estoy usando jQuery, pero no estoy reducen a ella):onhashchange con botones del navegador solamente

estoy usando una combinación de ancla de navegación (#id) y las peticiones Ajax . Para que las páginas se coloquen en su lugar (usando la navegación de ancla) o para buscar información (usando Ajax), utilizo el evento onhashchange.

EDIT: Tuve un pequeño error tipográfico. Me olvidé de comprobar si la bandera mouseDown era verdadera y se desencadenó el evento hashchange, así que agregué esa declaración if.

con jQuery que se parece a esto: (por supuesto, este código se envuelve en una función de la carga y se inicializa DOM, pero no importa para la pregunta)


$(window).bind('hashchange', function(e) { } 

para asegurar que sólo los navegadores apoyo a la onhashchange lee el código que encapsulan así:


if ('onhashchange' in window) { 
    $(window).bind('hashchange', function(e) { } 
} 

Mi aplicación web se hace de tal manera que sólo quiero el evento onhashchange para disparar cuando pulso los botones de atrás/adelante en el navegador. Para hacer esto, me gusta:


if ('onhashchange' in window) { 
    $(window).bind('mousedown hashchange', function(e) { } 
} 

Ahora, si hago clic dentro de la ventana de visualización activaré el evento mousedown. Si se activa el evento MouseDown Sé que no hizo clic en el navegador hacia atrás/adelante botones y puedo detener el evento onhashchange usando una bandera de esta manera:


var mouseDown = false; 

if ('onhashchange' in window) { 
    $(window).bind('mousedown hashchange', function(e) { 
    if (e.type === 'mousedown') { 
     mouseDown = true; 
    } 

    if (mouseDown && e.type === 'hashchange') { 
     // if the mousedown event was triggered and when the haschange event triggers, 
     // we need to stop the hashchange event and restore the mouseDown flag 
     mouseDown = false; 
     e.stopPropagation();   
    } 

    if (!mouseDown && e.type === 'hashchange') { 
     // Do the onhashchange stuff here 
    } 
    } 
} 

Esto causa un problema para IE, ya que Las costuras no pueden unir eventos del mouse al objeto ventana (?). IE nunca "verá" el evento mousedown.

Para resolver este problema de IE puedo tomar la propiedad "clientY". Esta propiedad se pasa en todas las llamadas a eventos en IE y le indica las coordenadas del mouse. Si e.clientY es menor que 0, el mouse se encuentra fuera de la ventana gráfica y sabré que activé el onhashchange haciendo clic en los botones de navegación hacia atrás/adelante. Ahora parece que esto:


var mouseDown = false; 

if ('onhashchange' in window) { 
    $(window).bind('mousedown hashchange', function(e) { 
    // IE: Use e.clientY to check if the mouse position was within the viewport (i.e. not a nagative value for Y) 
    // !IE: Use e.type 
    if (e.type === 'mousedown' || e.clientY > 0) { 
     mouseDown = true; 
    } 

    if (mouseDown && e.type === 'hashchange') { 
     // if the mousedown event was triggered and when the haschange event triggers, 
     // we need to stop the hashchange event and restore the mouseDown flag 
     mouseDown = false; 
     e.stopPropagation();   
    } 
    if (!mouseDown && e.type === 'hashchange') { 
     // Do the onhashchange stuff here 
    } 
    } 
} 

Esta solución estaba funcionando a las mil maravillas hasta que he tenido que añadir soporte para la navegación con las flechas del teclado. Ahora no importa en qué parte de la pantalla está el mouse. Siempre que la ventana de IE esté "activa", el evento de pulsación para escuchar la entrada del teclado se activa al presionar el teclado. Esto significa que el control de clienteY ya no funciona como se esperaba.

El problema:

Por lo que yo sé, el onhashchange debe estar enlazado al objeto de ventana. Todos los eventos deben procesarse dentro de la misma función de devolución de llamada si deseo poder controlar un evento escuchando otro.

¿Cómo puedo hacer que funcione?

+0

('onhashchange' en la ventana) siempre devolverá falso si aún no está definido y verdadero ya está definido. No significa que el navegador realmente ejecutará el código en un hashchange Esto es similar a window.onload que no está definido a menos que se le haya asignado una función, aunque prácticamente todas las browswers lo admiten. – qwertymk

+0

Sí, dejé intencionalmente la declaración de función porque no la consideré relevante para la pregunta. La función que vincula el evento hashchange se invoca cuando se carga el DOM. – Patrik

Respuesta

3

Por lo tanto, sólo tiene Put

"¿cómo puedo distinguir entre un/pulse el botón hacia delante hacia atrás contra la navegación procedente de interactuar con el DOM".

Es posible que desee tener una marca tal que cuando cambie la parte hash de la URL del código, establezca esta marca, ignore el evento hashchange y luego desactive la marca. En ese caso, se ignorará el evento (una especie de solución inversa en cuanto a lo que intenta hacer). Obviamente quieres envolver esto en una función.

En general, sin embargo, las aplicaciones que utilizan el evento hashchange para la navegación a menudo utilizar el evento hashchange como un medio para cambiar el estado de la aplicación. Por lo tanto, solo hay un punto de entrada y no es necesario distinguir si el evento se genera mediante la navegación del navegador frente a la interacción dom. Probablemente recomendaría cambiar tu enfoque.

yo también le apuntan al hecho de que la historia se puede apoyar en todos los navegadores (incluso IE6 y IE7 utilizando un corte del marco flotante). Echar un vistazo a la jQuery history plugin

+0

Maldición, sabía que podía ser descrito de una manera más corto;) Ese es el problema, la parte de hash no se establece a partir del código. Se configura desde el comportamiento del enlace predeterminado y utiliza el historial del navegador para navegar hacia atrás y hacia adelante con los botones del navegador. Cambiar el enfoque no es una opción. Mi solución funcionó bien hasta que tuve que implementar los eventos KeyDown. Además, no mencioné que esta es una solución dirigida GT IE 7 ya que podemos controlar esa parte con los usuarios. Entonces IE6 y 7 no serán ningún problema. – Patrik

+0

Acerca de "cambiar el estado de la aplicación". Esta solución es un poco diferente ya que usa una combinación de navegación de anclaje animado y llamadas ajax. Si solo fueran llamadas ajax, esto no sería un problema. :) De todos modos, voy a dar la idea de una solución inversa para ver si puedo encontrar un nuevo ángulo para abordar el problema. Gracias. – Patrik

+0

Tuve que hacer algunos cambios con el acercamiento a otras partes de mi código dejándome solo con el evento hashchange para esta función. No es muy bonito, pero funciona por ahora. – Patrik

1

La biblioteca de referencia para lograrlo: http://benalman.com/projects/jquery-bbq-plugin/

lo usé y funciona muy bien

pensar en poner "!" después de "#" en la url, para que google pueda descubrir las páginas ajax http://code.google.com/web/ajaxcrawling/docs/getting-started.html

+0

Sí, lo he visto. No encuentro especialmente el uso de complementos (o código que no escribí para el caso). Especialmente complementos que hacen mucho más de lo que necesito. En este caso estoy construyendo un sistema cerrado para que google nunca vea las páginas. Pero gracias de todos modos por el enlace. ¡Es una gran referencia! – Patrik

Cuestiones relacionadas