javascript - habilitar - ¿Cómo simulo un vuelo estacionario con un toque en los navegadores habilitados para tocar?
javascript no funciona en chrome (13)
Otra solución mejorada
Primero fui con el enfoque de Rich Bradshaw , pero luego comenzaron a aparecer problemas. Al hacer el evento e.preventDefault () en ''touchstart'' , la página ya no se desplaza y ni la pulsación larga puede abrir el menú de opciones ni hacer doble clic en el zoom para finalizar la ejecución.
Una solución podría ser averiguar qué evento se está llamando y solo e.preventDefault () en el último, ''touchend'' . Como ''touchmove'' de scroll viene antes que ''touchend'', se mantiene como por defecto, y ''click'' también se previene ya que viene afterwords en la cadena de evento aplicada al móvil, de esta manera:
// Binding to the ''.static_parent'' ensuring dynamic ajaxified content
$(''.static_parent'').on(''touchstart touchend'', ''.link'', function (e) {
// If event is ''touchend'' then...
if (e.type == ''touchend'') {
// Ensuring we event prevent default in all major browsers
e.preventDefault ? e.preventDefault() : e.returnValue = false;
}
// Add class responsible for :hover effect
$(this).toggleClass(''hover_effect'');
});
Pero luego, cuando aparece el menú de opciones, ya no se activa ''touchend'' responsable de alternar entre clases, y la próxima vez que el comportamiento de vuelo estacionario será al revés, totalmente mezclado.
Una solución sería, una vez más, descubrir condicionalmente en qué evento estamos, o simplemente hacer por separado, y usar addClass () y removeClass () respectivamente en ''touchstart'' y ''touchend'' , asegurándose de que siempre comienza y termina por respectivamente, agregar y eliminar en lugar de decidirlo condicionalmente. Para finalizar, también enlazaremos la devolución de llamada eliminada al tipo de evento ''focusout'' , y nos responsabilizaremos de borrar la clase de vuelo flotante de cualquier enlace que pueda permanecer encendida y nunca volver a visitarse nuevamente, así:
$(''.static_parent'').on(''touchstart'', ''.link'', function (e) {
$(this).addClass(''hover_effect'');
});
$(''.static_parent'').on(''touchend focusout'', ''.link'', function (e) {
// Think double click zoom still fails here
e.preventDefault ? e.preventDefault() : e.returnValue = false;
$(this).removeClass(''hover_effect'');
});
Atención: aún se producen algunos errores en las dos soluciones anteriores y, también creo (no probado), el doble clic en el zoom todavía falla.
Tidy y con suerte Bug Free (no :)) Solución de Javascript
Ahora , por un segundo enfoque más limpio, más ordenado y receptivo, simplemente use javascript (sin mezcla entre .hover class y pseudo: hover) y desde donde podría llamar directamente su comportamiento de ajax en el evento universal (móvil y de escritorio) ''click'' , Encontré una pregunta bastante bien respondida de la cual finalmente entendí cómo podía mezclar los eventos de toque y mouse sin varias repeticiones de eventos que inevitablemente cambiaban los unos de los otros en la cadena de eventos. Así es cómo:
$(''.static_parent'').on(''touchstart mouseenter'', ''.link'', function (e) {
$(this).addClass(''hover_effect'');
});
$(''.static_parent'').on(''mouseleave touchmove click'', ''.link'', function (e) {
$(this).removeClass(''hover_effect'');
// As it''s the chain''s last event we only prevent it from making HTTP request
if (e.type == ''click'') {
e.preventDefault ? e.preventDefault() : e.returnValue = false;
// Ajax behavior here!
}
});
Con algo de HTML como este:
<p>Some Text</p>
Entonces algo de CSS como este:
p {
color:black;
}
p:hover {
color:red;
}
¿Cómo puedo permitir un toque prolongado en un dispositivo con capacidad táctil para replicar el vuelo estacionario? Puedo cambiar el marcado / usar JS, etc., pero no puedo pensar en una manera fácil de hacerlo.
Agregue este código y luego configure la clase "tapHover" a los elementos que le gustaría trabajar de esta manera. La primera vez que toque un elemento obtendrá pseudoclass ": hover" y clase "tapped". Se evitará el evento Click. La segunda vez que toque el mismo elemento, se activará el evento de clic.
// Activate only in devices with touch screen
if(''ontouchstart'' in window)
{
// this will make touch event add hover pseudoclass
document.addEventListener(''touchstart'', function(e) {}, true);
// modify click event
document.addEventListener(''click'', function(e) {
// get .tapHover element under cursor
var el = jQuery(e.target).hasClass(''tapHover'')
? jQuery(e.target)
: jQuery(e.target).closest(''.tapHover'');
if(!el.length)
return;
// remove tapped class from old ones
jQuery(''.tapHover.tapped'').each(function() {
if(this != el.get(0))
jQuery(this).removeClass(''tapped'');
});
if(!el.hasClass(''tapped''))
{
// this is the first tap
el.addClass(''tapped'');
e.preventDefault();
return false;
}
else
{
// second tap
return true;
}
}, true);
}
.box {
float: left;
display: inline-block;
margin: 50px 0 0 50px;
width: 100px;
height: 100px;
overflow: hidden;
font-size: 20px;
border: solid 1px black;
}
.box.tapHover {
background: yellow;
}
.box.tapped {
border: solid 3px red;
}
.box:hover {
background: red;
}
<div class="box" onclick="this.innerHTML = Math.random().toFixed(5)"></div>
<div class="box tapHover" onclick="this.innerHTML = Math.random().toFixed(5)"></div>
<div class="box tapHover" onclick="this.innerHTML = Math.random().toFixed(5)"></div>
El efecto de hover
mouse no se puede implementar en el dispositivo táctil. Cuando aparecí con la misma situación en safari
ios
, usé :active
en css para hacer efecto.
es decir.
p:active {
color:red;
}
En mi caso, funciona. Puede ser que este sea también el caso que se puede usar sin usar javascript. Solo dale una oportunidad.
El uso también puede usar CSS, agregar foco y activo (para IE7 y menos) al enlace oculto. Ejemplo de un menú ul dentro de un div con menú de clase:
.menu ul ul {display:none; position:absolute; left:100%; top:0; padding:0;}
.menu ul ul ul {display:none; position:absolute; top:0; left:100%;}
.menu ul ul a, .menu ul ul a:focus, .menu ul ul a:active { width:170px; padding:4px 4%; background:#e77776; color:#fff; margin-left:-15px; }
.menu ul li:hover > ul { display:block; }
.menu ul li ul li {margin:0;}
Es tarde y no ha sido probado, debería funcionar ;-)
La solución más sencilla que encontré fue: tenía algunas etiquetas <span> con: reglas de desplazamiento de CSS en ellas. Cambié para <a href = "javascript: void (0)"> y voilà. Los estilos de desplazamiento en iOS comenzaron a funcionar.
Mi gusto personal es atribuir los estilos :hover
al estado de :focus
también, como:
p {
color: red;
}
p:hover, p:focus {
color: blue;
}
Luego con el siguiente HTML:
<p id="some-p-tag" tabindex="-1">WOOOO</p>
Y el siguiente JavaScript:
$("#some-p-tag").on("touchstart", function(e){
e.preventDefault();
var $elem = $(this);
if($elem.is(":focus")) {
//this can be registered as a "click" on a mobile device, as it''s a double tap
$elem.blur()
}
else {
$elem.focus();
}
});
OK, lo he resuelto! Implica cambiar el CSS ligeramente y agregar algunos JS.
Usando jQuery para hacerlo más fácil:
$(document).ready(function() {
$(''.hover'').bind(''touchstart touchend'', function(e) {
e.preventDefault();
$(this).toggleClass(''hover_effect'');
});
});
En inglés: cuando comienzas o finalizas un toque, hover_effect
o desactiva la clase hover_effect
.
Luego, en su HTML, agregue un elemento emergente de clase a cualquier elemento con el que desee que funcione. En su CSS, reemplace cualquier instancia de:
element:hover {
rule:properties;
}
con
element:hover, element.hover_effect {
rule:properties;
}
Y solo para una utilidad adicional, agregue esto a su CSS también:
.hover {
-webkit-user-select: none;
-webkit-touch-callout: none;
}
Para detener el navegador pidiéndole que copie / guarde / seleccione la imagen o lo que sea.
¡Fácil!
Para responder a su pregunta principal: "¿Cómo simulo un vuelo estacionario con un toque en navegadores habilitados con el toque?"
Simplemente permita ''hacer clic'' en el elemento (tocando la pantalla) y luego active el evento de hover
usando JavaScript.
var p = document.getElementsByTagName(''p'')[0];
p.onclick = function() {
// Trigger the `hover` event on the paragraph
p.onhover.call(p);
};
Esto debería funcionar, siempre que haya un evento de hover
en su dispositivo (aunque normalmente no se use).
Actualización: Acabo de probar esta técnica en mi iPhone y parece funcionar bien. Pruébelo aquí: http://jsfiddle.net/mathias/YS7ft/show/light/
Si desea utilizar un "toque largo" para activar el vuelo estacionario en su lugar, puede usar el fragmento de código anterior como punto de partida y divertirse con temporizadores y cosas;)
Prueba esto:
<script>
document.addEventListener("touchstart", function(){}, true);
</script>
Y en tu CSS:
element:hover, element:active {
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-user-select: none;
-webkit-touch-callout: none /*only to disable context menu on long press*/
}
¡Con este código no necesitas una clase adicional de .hover!
Sin dispositivo (o mejor navegador) JS específico, estoy bastante seguro de que no tienes suerte.
Editar: pensó que quería evitar eso hasta que vuelva a leer su pregunta. En el caso de Mobile Safari, puede registrarse para obtener todos los eventos táctiles de forma similar a lo que puede hacer con UIView-s nativo. No puedo encontrar la documentación en este momento, aunque intentaré hacerlo.
Todo lo que necesita hacer es vincular touchstart a un padre. Algo como esto funcionará:
$(''body'').bind(''touchstart'', function() {});
No necesita hacer nada en la función, déjelo vacío. Esto será suficiente para mantener el cursor al tacto, por lo que un toque se comporta más como: pasar el mouse y menos como: activo. iOS magia.
Una forma de hacerlo sería hacer el efecto de desplazamiento cuando se inicia el toque, luego eliminar el efecto de desplazamiento cuando el toque se mueve o termina.
Esto es lo que Apple tiene que decir sobre el manejo táctil en general, ya que mencionas iPhone.
Una mezcla de Javascript nativo y jQuery:
var gFireEvent = function (oElem,sEvent)
{
try {
if( typeof sEvent == ''string'' && o.isDOM( oElem ))
{
var b = !!(document.createEvent),
evt = b?document.createEvent("HTMLEvents"):document.createEventObject();
if( b )
{ evt.initEvent(sEvent, true, true );
return !oElem.dispatchEvent(evt);
}
return oElem.fireEvent(''on''+sEvent,evt);
}
} catch(e) {}
return false;
};
// Next you can do is (bIsMob etc you have to determine yourself):
if( <<< bIsMob || bIsTab || bisTouch >>> )
{
$(document).on(''mousedown'', function(e)
{
gFireEvent(e.target,''mouseover'' );
}).on(''mouseup'', function(e)
{
gFireEvent(e.target,''mouseout'' );
});
}