javascript - tactiles - Manejo de eventos de desplazamiento en una pantalla táctil
touchend (1)
Un sitio web que he diseñado utiliza un menú de navegación que muestra los submenús en: hover. El sitio inicial no utilizó ningún diseño receptivo: se enfocó solo en el entorno de escritorio. Ahora estoy usando técnicas de diseño adaptativo para apuntar a dispositivos móviles y tabletas, muchos de los cuales son táctiles en lugar de mouse.
El gran problema al que me enfrentaba (y que muchas otras personas parecen haber enfrentado) era el menú de navegación basado en el vuelo: funciona muy bien en un entorno de mouse, pero en los dispositivos táctiles, no hay manera confiable de activar el vuelo estacionario, haciendo la página es difícil de usar
El objetivo es este:
- Cuando un menú está rodeado por un mouse, muestre el submenú.
- Cuando se hace clic en un menú con un mouse, abre el enlace de la etiqueta de anclaje.
- La primera vez que se hace clic en un menú táctil, se muestra el submenú.
- La segunda vez que se hace clic en un menú táctil, abra el vínculo de la etiqueta de anclaje.
- Cambie la funcionalidad sin problemas para tabletas que también tienen dispositivos de mouse conectados.
Mi equipo no está dispuesto a sacrificar el efecto de desplazamiento sobre las máquinas basadas en el mouse. Les gusta y no desean que los menús hagan clic en función de todos los dispositivos. Estoy de acuerdo con ésto.
Después de mirar alrededor de la red, no pude encontrar ninguna solución para mi problema. Puse algunos de ellos juntos y desarrollé algo que ha probado bien en Android, obteniendo exactamente la funcionalidad que quería. ¿Hay algo que pueda mejorarse y / o vea algún problema con este enfoque?
jQuery(document).ready(function() {
var touched=false;
jQuery(".nav").on(''touchstart'', ''li .has_children'', function (e) { touched=true; });
jQuery("html").on(''mousemove'', function (e) { touched=false; });
jQuery("html").on(''click'', updatePreviousTouched );
jQuery(".nav").on(''click'', ''li .has_children'', function (e) {
updatePreviousTouched(e);
if( touched ) {
if (jQuery(this).data(''clicked_once'')) {
jQuery(this).data(''clicked_once'', false);
return true;
} else {
e.preventDefault();
jQuery(this).trigger("mouseenter");
jQuery(this).data(''clicked_once'', true);
}
}
touched=false;
});
var previous_touched;
function updatePreviousTouched(e) {
if( typeof previous_touched != ''undefined'' && previous_touched != null && !previous_touched.is( jQuery(e.target) ) ) {
previous_touched.data(''clicked_once'', false);
}
previous_touched=jQuery(e.target);
}
}
Aquí hay un jfiddle: http://jsfiddle.net/5FfCF/1/
Si se puede mejorar esta solución, por favor brinde cualquier sugerencia. Si encuentra que no funciona para usted, hágamelo saber también. Lo publico aquí para tratar de obtener sugerencias para mejorar y publicar la idea para que otros puedan beneficiarse de ella.
Aquí están los resultados de mis pruebas hasta el momento:
- Windows 7 en los principales 5 navegadores : funciona.
- Tableta Android en el navegador predeterminado : funciona.
- Computadora portátil con Windows 7 con pantalla táctil en IE y Chrome : Tipo de trabajo. La máquina ejecuta la versión de escritorio de ambos navegadores, por lo que no activa el evento "touchstart". En algún lugar entre la pantalla táctil y el navegador, algo está convirtiendo el toque en eventos del mouse. Sin embargo, como el mouse es una parte no extraíble de este dispositivo, no lo considero una falla. Me gustaría que funcionara como una tableta, pero parece que todavía no hay tecnología disponible.
- iOS iPad : funcionó como se esperaba antes de escribir el javascript anterior. Parece que ios hace algo de esta magia de desplazamiento / clic para nosotros detrás de las escenas. Tengo un miembro del equipo revisando para ver si mi javascript rompió la funcionalidad de iOS, editaré esta publicación una vez que obtenga una respuesta.
Otras notas:
- Este es solo el menú para el sitio de escritorio y tableta. Hay un menú diferente basado en clics para el sitio móvil. No recomendaría usar esta solución para un dispositivo del tamaño de un teléfono.
Piddle Diddle Fiddle :)
Demo embebida Fiddle (uso con teléfono para un acceso más fácil)
Antes de leer este muro de texto, revisa el violín y asegúrate de que sea lo que estás buscando. Prueba también en un teléfono (lo probé en mi Android y no tuve problemas).
Si tienes un conjunto de códigos completamente separados para teléfonos móviles, entonces no tienes nada de qué preocuparte realmente. La adaptación al evento touch vs. hover es particularmente complicada en los dispositivos con iOS. Pero pude superar esto capturando una gama de eventos de mouse que se tradujeron en un evento táctil.
Para su caso particular, ya que desea que esto sea tan diferente entre los tres, le sugiero que ejecute un script inicial para obtener el tamaño de pantalla y si es menor que ### px x ### px
, agregue una clase llamada handheld
o mobile
o lo que sea para el body
. Ahora todo lo que tiene que hacer es asignar el código de captura touch
a $(''.mobile .nav'')
y tener un fragmento de código separado que asigne el evento hover
a las PC.
Para las tabletas, tendrá que decidir qué es más importante para usted: la capacidad de hacer clic y navegar utilizando el elemento del menú raíz para cada menú, o solo permitiendo hacer clic en los elementos del submenú (lo que eliminaría la necesidad de agregar el .mobile
class to body
).
Aquí hay algunos códigos que debería poder usar tanto en dispositivos móviles como en computadoras de escritorio.
jQuery:
jQuery(document).ready(function () {
$(''.nav'').on(''click mousedown mouseup touchstart touchmove'', ''a.has_children'', function () {
if ( $(this).next(''ul'').hasClass(''open'') && !$(this).parents(''ul'').hasClass(''open'')) {
$(''.open'').removeClass(''open'');
return false;
}
$(''.open'').not($(this).parents(''ul'')).removeClass(''open'');
$(this).next(''ul'').addClass(''open'');
return false;
});
$(document).on(''click'', '':not(.has_children, .has_children *)'', function() {
if( $(''.open'').length > 0 ) {
$(''.open'').removeClass(''open'');
return false;
}
});
});
Normalmente no copio todo el HTML como lo voy a hacer, pero en esta instancia en particular necesitarás tomarlo exactamente como lo tengo aquí para evitar el problema de espacio en blanco de inline-block
. Compare mi violín con su original y vea cuánto más fácil es colocar / hacer clic en cada enlace.
HTML:
<div class="header-nav-menu">
<ul class="nav">
<li><a href="http://www.google.com">One</a></li><li>
<a class="has_children" href="http://www.google.com">Two</a>
<ul>
<li><a href="http://www.google.com">2A</a></li><li>
<a href="http://www.google.com">2B</a>
</li>
<li><a href="http://www.google.com">2C</a>
</li>
</ul>
</li><li>
<a class="has_children" href="http://www.google.com">Three</a>
<ul>
<li><a href="http://www.google.com">3A</a>
</li>
<li> <a class="has_children" href="http://www.google.com">3B</a>
<ul>
<li><a href="http://www.google.com">3BI</a>
</li>
<li><a href="http://www.google.com">3BII</a>
</li>
<li><a href="http://www.google.com">3BIII</a>
</li>
</ul>
</li>
<li><a href="http://www.google.com">3C</a>
</li>
</ul>
</li><li>
<a href="http://www.google.com">Four</a></li><li>
<a href="http://www.google.com">Five</a></li>
</ul>
</div>
Estoy bastante seguro de que ni siquiera toqué el CSS, así que lo dejo en el Fiddle por ahora. Espero que esto te ayude en tu camino.