¿Cuál es la mejor manera de detectar un dispositivo de 'pantalla táctil' usando JavaScript?

416

He escrito un complemento jQuery que se usa en dispositivos de escritorio y móviles. Me preguntaba si hay una manera con JavaScript para detectar si el dispositivo tiene capacidad de pantalla táctil. Estoy usando jquery-mobile.js para detectar los eventos de la pantalla táctil y funciona en iOS, Android, etc., pero también me gustaría escribir declaraciones condicionales en función de si el dispositivo del usuario tiene una pantalla táctil.

¿Es eso posible?

screenm0nkey
fuente
esta es la mejor manera var x = 'touchstart' en document.documentElement; console.log (x) // devuelve verdadero si es compatible // de lo contrario devuelve falso
Risa__B
¿Por qué está protegido este hilo si aún surgen nuevas técnicas?
Andy Hoffman el

Respuestas:

139

Actualización: lea la respuesta de blmstr a continuación antes de incluir una biblioteca de detección de características completa en su proyecto. Detectar el soporte táctil real es más complejo, y Modernizr solo cubre un caso de uso básico.

Modernizr es una forma excelente y liviana de realizar todo tipo de detección de funciones en cualquier sitio.

Simplemente agrega clases al elemento html para cada característica.

Luego puede orientar esas funciones fácilmente en CSS y JS. Por ejemplo:

html.touch div {
    width: 480px;
}

html.no-touch div {
    width: auto;
}

Y Javascript (ejemplo de jQuery):

$('html.touch #popup').hide();
Alan Christopher Thomas
fuente
88
Modernizr no prueba las pantallas táctiles. Prueba la existencia de eventos táctiles en el navegador. Consulte la sección "Pruebas varias" en los documentos: modernizr.com/docs/#features-misc
Harry Love
1
también puede hacer una prueba JS para detectar la existencia de eventos táctiles si (Modernizr.touch) {/ * do touch stuff /} else {/ fine, don't * /}
Anatoly G
77
Para el punto de @ harrylove, desde que salió Windows 8, Modernizr ha estado devolviendo incorrectamente todos los navegadores de mi PC como compatibles con el tacto.
Anton
3
Actualización: la respuesta de blmstr es mejor, y es una solución Javascript pura.
Alan Christopher Thomas
1
Si Modernizr.touchregresa inesperadamente undefined, es posible que tenga un Modernizador personalizado (puede elegir y elegir) sin soporte para la detección de eventos táctiles.
Henrik N
680

¿Has intentado usar esta función? (Esto es lo mismo que Modernizr solía usar).

function is_touch_device() {  
  try {  
    document.createEvent("TouchEvent");  
    return true;  
  } catch (e) {  
    return false;  
  }  
}

console.log(is_touch_device());

ACTUALIZACIÓN 1

document.createEvent("TouchEvent")han comenzado a regresar trueen el último Chrome (v. 17). Modernizr actualizó esto hace un tiempo. Mira la prueba Modernizr aquí .

Actualice su función de esta manera para que funcione:

function is_touch_device1() {
  return 'ontouchstart' in window;
}

console.log(is_touch_device1());

ACTUALIZACIÓN 2

Descubrí que lo anterior no funcionaba en IE10 (devolviendo falso en MS Surface). Aquí está la solución:

function is_touch_device2() {
  return 'ontouchstart' in window        // works on most browsers 
  || 'onmsgesturechange' in window;  // works on IE10 with some false positives
};

console.log(is_touch_device2());

ACTUALIZACIÓN 3

'onmsgesturechange' in windowvolverá cierto en algunas versiones de escritorio de IE, por lo que no es confiable. Esto funciona de manera un poco más confiable:

function is_touch_device3() {
  return !!('ontouchstart' in window        // works on most browsers 
  || navigator.maxTouchPoints);       // works on IE10/11 and Surface
};

console.log(is_touch_device3());

ACTUALIZACIÓN 2018

El tiempo pasa y hay nuevas y mejores formas de probar esto. Básicamente, he extraído y simplificado la forma en que Modernizr lo verifica:

function is_touch_device4() {
    
    var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
    
    var mq = function (query) {
        return window.matchMedia(query).matches;
    }

    if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
        return true;
    }

    // include the 'heartz' as a way to have a non matching MQ to help terminate the join
    // https://git.io/vznFH
    var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
    return mq(query);
}

console.log(is_touch_device4());

Aquí están utilizando la touch-enabledfunción de consulta de medios no estándar , que creo que es un poco raro y una mala práctica. Pero bueno, en el mundo real, supongo que funciona. En el futuro (cuando sean compatibles con todos) esas funciones de consulta de medios podrían brindarle los mismos resultados: pointery hover.

Echa un vistazo a la fuente de cómo lo está haciendo Modernizr .

Para ver un buen artículo que explica los problemas con la detección táctil, consulte: Stu Cox: no se puede detectar una pantalla táctil .

bolmaster2
fuente
20
La explosión doble arroja un valor a un valor booleano, lo que obliga a la función a devolver trueo false. Puede leer más sobre esto aquí: stackoverflow.com/questions/4686583/…
Rob Flaherty
2
Esto no funciona con Opera Mobile 10 o Internet Explorer Mobile 6 (Windows Mobile 6.5).
doubleJ
17
El doble NOT (!!) es superfluo ya que el inoperador ya se evalúa como booleano.
Steve
11
'onmsgesturechange'está evaluando verdadero incluso en dispositivos no táctiles (PC). window.navigator.msMaxTouchPointsParece ser más preciso. Lo encontré aquí .
Steve
66
Está evaluando a verdadero en IE10 en Windows 8 a pesar de que mi pantalla no tiene sensores táctiles. Actualicé mi vieja computadora portátil de Windows 7 a Windows 8.
Pwner
120

Como Modernizr no detecta IE10 en Windows Phone 8 / WinRT, una solución simple para varios navegadores es:

var supportsTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints;

Solo necesita verificarlo una vez, ya que el dispositivo no admitirá de repente o no admitirá el tacto, así que simplemente guárdelo en una variable para que pueda usarlo varias veces de manera más eficiente.

Matt Stow
fuente
3
'onmsgesturechange' en la ventana también detecta IE10 "de escritorio" en dispositivos no táctiles, por lo que este no es un método confiable para determinar el tacto.
Matt Stow
66
Esta respuesta debería haber sido aceptada, ya que es la mejor y más simple y actualizada. En una función, creo que esto sería más consistente: return !!('ontouchstart' in window) || !!('msmaxtouchpoints' in window.navigator);(para combinar ambas respuestas) ¡Funciona bien en IE10 también!
Yeti
Esta debería ser la respuesta aceptada. 'onmsgesturechange' in windowvuelve verdadero en el escritorio IE10 incluso cuando es posible tocar
Sam Thornton
66
Todo lo que necesitas:function isTouchDevice() { return 'ontouchstart' in window || !!(navigator.msMaxTouchPoints);}
GFoley83
1
Incluso la sugerencia de GFoleys de 'ontouchstart' en la ventana || !! (navigator.msMaxTouchPoints); devuelve fals positivo en Chrome 30 dev febrero de 2014.
Tom Andersen
37

Utilizando todos los comentarios anteriores, he reunido el siguiente código que funciona para mis necesidades:

var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0));

He probado esto en iPad, Android (navegador y Chrome), Blackberry Playbook, iPhone 4s, Windows Phone 8, IE 10, IE 8, IE 10 (Windows 8 con pantalla táctil), Opera, Chrome y Firefox.

Actualmente falla en Windows Phone 7 y todavía no he podido encontrar una solución para ese navegador.

Espero que alguien encuentre esto útil.

David
fuente
¿Hay alguna razón por la que no pueda usar: function is_touch_device () {return !! ('ontouchstart' en la ventana) || !! ('msmaxtouchpoints' en el navegador); };
sidonaldson
usar la función funcionará, pero generalmente me gusta usar el método variable anterior, por lo que solo se prueba una vez y es más rápido cuando verifico más adelante mi código. También descubrí que necesitaba probar para ver si msMaxTouchPoints era más de 0 como IE 10 en Windows 8 sin que una pantalla táctil devolviera 0 como msMaxTouchPoints.
David
vuelve truea mi Firefox 32 en Windows 7 :(
vsync
Firefox 33 y 33.1 en Windows 8 muestran falso correctamente en mi sistema. Si actualiza su Firefox a la última versión, ¿sigue siendo cierto? ¿Quizás tenga un dispositivo instalado en su máquina que podría hacer que Firefox piense incorrectamente que su máquina tiene toque?
David
>>> 'ontouchstart' en la ventana >>> true FF 51.0.1 en ubuntu
Ravi Gadhia
25

Desde la introducción de las funciones de medios de interacción , simplemente puede hacer:

if(window.matchMedia("(pointer: coarse)").matches) {
    // touchscreen
}

https://www.w3.org/TR/mediaqueries-4/#descdef-media-any-pointer

Actualización (debido a comentarios): la solución anterior es detectar si un "puntero grueso", generalmente una pantalla táctil, es el dispositivo de entrada principal. En caso de que desee detectar si un dispositivo con, por ejemplo, un mouse, también tiene una pantalla táctil, puede usarany-pointer: coarse en lugar.

Para más información mira aquí: detectar que el navegador no tiene mouse y es solo táctil

Blackbam
fuente
3
Esta es, de lejos, la mejor solución, ¡gracias! Aunque recomendaría usarlo (pointer: coarse)ya que lo más probable es que solo apunte a la entrada principal. Se puede usar en producción, ya que los pocos navegadores que no son compatibles son solo de escritorio. Hay un gran artículo sobre esto en css-tricks .
Fabian von Ellerts
2
Esta es la única solución que he probado que funciona en todas las situaciones. ¡Gracias!
kaiserkiwi
20

Me gusta este:

function isTouchDevice(){
    return typeof window.ontouchstart !== 'undefined';
}

alert(isTouchDevice());
Benny Neugebauer
fuente
12
No es necesario usar una expresión ternaria para devolver un valor booleano. Simplemente use la expresión para devolver el booleano. function isTouchDevice(){ return (window.ontouchstart !== undefined); }
Tim Vermaelen
1
También podría usar: var isTouch = 'ontouchstart' in window;sin embargo, esto no funciona con el último Chrome (v31), var isTouch = 'createTouch' in window.document;todavía funciona.
Olivier
2
Como ya se mencionó en los comentarios de la pregunta previamente aceptada. "Modernizr no prueba las pantallas táctiles. Prueba la existencia de eventos táctiles en el navegador". Su función es técnicamente hasTouchEvents () no isTouchDevice ()
hexalys
Tenga en cuenta que las pruebas de métodos similares solo touchstartno reconocerán Surface como un dispositivo táctil porque IE usa pointereventos en su lugar.
CookieMonster
1
Tal vez @Nis tenía razón, pero en Firefox 39, devuelve correctamente false.
Dan Dascalescu
17

Si usa Modernizr , es muy fácil de usarModernizr.touch como se mencionó anteriormente.

Sin embargo, prefiero usar una combinación de Modernizr.touchpruebas de agente de usuario, solo por seguridad.

var deviceAgent = navigator.userAgent.toLowerCase();

var isTouchDevice = Modernizr.touch || 
(deviceAgent.match(/(iphone|ipod|ipad)/) ||
deviceAgent.match(/(android)/)  || 
deviceAgent.match(/(iemobile)/) || 
deviceAgent.match(/iphone/i) || 
deviceAgent.match(/ipad/i) || 
deviceAgent.match(/ipod/i) || 
deviceAgent.match(/blackberry/i) || 
deviceAgent.match(/bada/i));

if (isTouchDevice) {
        //Do something touchy
    } else {
        //Can't touch this
    }

Si no usa Modernizr, simplemente puede reemplazar la Modernizr.touchfunción anterior con('ontouchstart' in document.documentElement)

También tenga en cuenta que probar el agente de usuario iemobilele dará una gama más amplia de dispositivos móviles de Microsoft detectados queWindows Phone .

También vea esta pregunta SO

Peter Pan
fuente
8
Muchos puntos de bonificación por "hacer algo delicado" y "no puedo tocar esto"
Lee Saxon
está comprobando varias veces los mismos dispositivos y haciendo múltiples expresiones regulares cuando podría usar solo uno. Además, está haciendo expresiones regulares entre mayúsculas y minúsculas, pero la cadena ya está en minúsculas.
caesarsol
1
esto debería ser suficiente:/(iphone|ipod|ipad|android|iemobile|blackberry|bada)/.test(window.navigator.userAgent.toLowerCase())
caesarsol
¿Alguna razón para minúsculas o hacer que la coincidencia no distinga entre mayúsculas y minúsculas? ¿Cuándo "iOS", "Android" o "IEMobile" usarían otra carcasa?
Henrik N
14

Intentamos la implementación del modernizador, pero la detección de los eventos táctiles ya no es consistente (IE 10 tiene eventos táctiles en el escritorio de Windows, IE 11 funciona, porque han eliminado los eventos táctiles y agregado la api de puntero).

Así que decidimos optimizar el sitio web como un sitio táctil siempre y cuando no sepamos qué tipo de entrada tiene el usuario. Esto es más confiable que cualquier otra solución.

Nuestras investigaciones dicen que la mayoría de los usuarios de escritorio se mueven con el mouse sobre la pantalla antes de hacer clic, para que podamos detectarlos y cambiar el comportamiento antes de que puedan hacer clic o desplazar el cursor sobre cualquier cosa.

Esta es una versión simplificada de nuestro código:

var isTouch = true;
window.addEventListener('mousemove', function mouseMoveDetector() {
    isTouch = false;
    window.removeEventListener('mousemove', mouseMoveDetector);
});
Martin Lantzsch
fuente
las computadoras de hoy tienen tanto el tacto como el mouse ... debes diferenciarte. Es imprescindible saber si solo se trata del tacto, el mouse o ambos. 3 estados diferentes.
vsync
1
Sí, tienes razón, pero esto es muy difícil. En el mejor de los casos, su aplicación está diseñada para ser utilizada por cualquier controlador de entrada y no le importa si el usuario tiene una pantalla táctil, mouse, teclado o todos juntos.
Martin Lantzsch
1
El comportamiento del usuario vale más que una información real de qué tipo de dispositivo tiene el usuario. Cuando sabes que el usuario tiene un mouse, pantalla táctil y teclado, ¿entonces qué? Manejar el comportamiento (mousemove, touchmove, keydown, etc.). Los usuarios pueden cambiar su tipo de entrada en "tiempo de ejecución", este es un verdadero problema, cuando estás desarrollando una aplicación real que se usa de 8 a 5 sin recargar.
Martin Lantzsch
2
+1 Pragmáticamente esta es la mejor respuesta para mí. Por ejemplo, tengo cuadrículas de datos. Estas cuadrículas de datos mostrarán un "icono de edición" para tocar para editar o un menú contextual para más opciones. Si se detecta el movimiento del mouse, elimino el icono (ahorra espacio en la cuadrícula) y los usuarios pueden hacer doble clic o clic derecho.
prograhammer
3
Chrome en dispositivos táctiles activa el movimiento del mouse ocasionalmente
pstanton
9

Violín de trabajo

Lo he logrado así;

function isTouchDevice(){
    return true == ("ontouchstart" in window || window.DocumentTouch && document instanceof DocumentTouch);
}

if(isTouchDevice()===true) {
    alert('Touch Device'); //your logic for touch device
}
else {
    alert('Not a Touch Device'); //your logic for non touch device
}
Aamir Shahzad
fuente
no detecta la tableta de superficie de Windows
Dan Beaulieu
@DanBeaulieu puede ser específico para el dispositivo, porque tengo Windows Phone para el que funciona bien, también lo he usado en mi aplicación que es QA: ED, lo volveré a verificar y actualizaré la respuesta. Disculpe las molestias
Aamir Shahzad
No estoy seguro de qué año, es un Windows Surface Pro que pertenece a un compañero de trabajo. Después de agregar modernizr lo pusimos a trabajar.
Dan Beaulieu
Esto informó correctamente No táctil en mi máquina con Windows 7 y táctil en una computadora portátil con pantalla táctil Windows 8 y un teléfono Android 4.4 MotoX.
Clay Nichols
Da un falso positivo en Chrome (46) en mi Mac
Patrick Fabrizius el
9

Hay algo mejor que verificar si tienen una pantalla táctil, es verificar si la están usando, y además es más fácil de verificar.

if (window.addEventListener) {
    var once = false;
    window.addEventListener('touchstart', function(){
        if (!once) {
            once = true;
            // Do what you need for touch-screens only
        }
    });
}
Ivan Castellanos
fuente
6

¡Este funciona bien incluso en tabletas con Windows Surface!

function detectTouchSupport {
msGesture = window.navigator && window.navigator.msPointerEnabled && window.MSGesture,
touchSupport = (( "ontouchstart" in window ) || msGesture || window.DocumentTouch &&     document instanceof DocumentTouch);
if(touchSupport) {
    $("html").addClass("ci_touch");
}
else {
    $("html").addClass("ci_no_touch");
}
}
Sathiyamoorthy
fuente
4

Utilicé partes del código anterior para detectar si se toca, por lo que mis iframes de fancybox aparecerían en las computadoras de escritorio y no en el tacto. Noté que Opera Mini para Android 4.0 todavía se estaba registrando como un dispositivo no táctil cuando solo usaba el código de blmstr. (¿Alguien sabe por qué?)

Terminé usando:

<script>
$(document).ready(function() {
    var ua = navigator.userAgent;
    function is_touch_device() { 
        try {  
            document.createEvent("TouchEvent");  
            return true;  
        } catch (e) {  
            return false;  
        }  
    }

    if ((is_touch_device()) || ua.match(/(iPhone|iPod|iPad)/) 
    || ua.match(/BlackBerry/) || ua.match(/Android/)) {
        // Touch browser
    } else {
        // Lightbox code
    }
});
</script>
Amado
fuente
¿podría explicar por qué no utilizar una sola llamada de coincidencia con una sola expresión regular /iPhone|iPod|iPad|Android|BlackBerry/?
user907860
Opera Mini realiza el renderizado en los servidores de Opera y no en el dispositivo en sí, por lo que es un poco extraño de esa manera.
bluesmoon
4

El mayor "problema" al tratar de detectar el tacto está en los dispositivos híbridos que admiten el tacto y el trackpad / mouse. Incluso si puede detectar correctamente si el dispositivo del usuario admite el tacto, lo que realmente necesita hacer es detectar qué dispositivo de entrada está utilizando actualmente el usuario . Hay una descripción detallada de este desafío y una posible solución aquí .

Básicamente, el enfoque para averiguar si un usuario acaba de tocar la pantalla o utilizar un ratón / trackpad lugar es registrar la vez una touchstarty mouseovereventos en la página:

document.addEventListener('touchstart', functionref, false) // on user tap, "touchstart" fires first
document.addEventListener('mouseover', functionref, false) // followed by mouse event, ie: "mouseover"

Una acción táctil activará ambos eventos, aunque el primero ( touchstart) siempre es el primero en la mayoría de los dispositivos. Entonces, contando con esta secuencia predecible de eventos, puede crear un mecanismo que agregue o elimine dinámicamente una can-touchclase a la raíz del documento para reflejar el tipo de entrada actual del usuario en este momento en el documento:

;(function(){
    var isTouch = false //var to indicate current input type (is touch versus no touch) 
    var isTouchTimer 
    var curRootClass = '' //var indicating current document root class ("can-touch" or "")
     
    function addtouchclass(e){
        clearTimeout(isTouchTimer)
        isTouch = true
        if (curRootClass != 'can-touch'){ //add "can-touch' class if it's not already present
            curRootClass = 'can-touch'
            document.documentElement.classList.add(curRootClass)
        }
        isTouchTimer = setTimeout(function(){isTouch = false}, 500) //maintain "istouch" state for 500ms so removetouchclass doesn't get fired immediately following a touch event
    }
     
    function removetouchclass(e){
        if (!isTouch && curRootClass == 'can-touch'){ //remove 'can-touch' class if not triggered by a touch event and class is present
            isTouch = false
            curRootClass = ''
            document.documentElement.classList.remove('can-touch')
        }
    }
     
    document.addEventListener('touchstart', addtouchclass, false) //this event only gets called when input type is touch
    document.addEventListener('mouseover', removetouchclass, false) //this event gets called when input type is everything from touch to mouse/ trackpad
})();

Más detalles aquí .

hojaldres de coco
fuente
3

Echa un vistazo a esta publicación , proporciona un fragmento de código realmente agradable para saber qué hacer cuando se detectan dispositivos táctiles o qué hacer si se llama al evento touchstart:

$(function(){
  if(window.Touch) {
    touch_detect.auto_detected();
  } else {
    document.ontouchstart = touch_detect.surface;
  }
}); // End loaded jQuery
var touch_detect = {
  auto_detected: function(event){
    /* add everything you want to do onLoad here (eg. activating hover controls) */
    alert('this was auto detected');
    activateTouchArea();
  },
  surface: function(event){
    /* add everything you want to do ontouchstart here (eg. drag & drop) - you can fire this in both places */
    alert('this was detected by touching');
    activateTouchArea();
  }
}; // touch_detect
function activateTouchArea(){
  /* make sure our screen doesn't scroll when we move the "touchable area" */
  var element = document.getElementById('element_id');
  element.addEventListener("touchstart", touchStart, false);
}
function touchStart(event) {
  /* modularize preventing the default behavior so we can use it again */
  event.preventDefault();
}
Safran Ali
fuente
3

Evitaría usar el ancho de pantalla para determinar si un dispositivo es táctil. Hay pantallas táctiles mucho más grandes que 699 px, piense en Windows 8. Navigatior.userAgent puede ser bueno para anular falsas notificaciones.

Recomendaría revisar este problema en Modernizr.

¿Desea probar si el dispositivo admite eventos táctiles o es un dispositivo táctil? Desafortunadamente, eso no es lo mismo.

híbrido
fuente
3

No, no es posible. Las excelentes respuestas dadas son solo parciales, porque cualquier método producirá falsos positivos y falsos negativos. Incluso el navegador no siempre sabe si hay una pantalla táctil, debido a las API del sistema operativo, y el hecho puede cambiar durante una sesión del navegador, particularmente con arreglos de tipo KVM.

Ver más detalles en este excelente artículo:

http://www.stucox.com/blog/you-cant-detect-a-touchscreen/

El artículo sugiere que reconsidere las suposiciones que lo hacen querer detectar pantallas táctiles, probablemente estén equivocadas. (Revisé la mía para mi aplicación, ¡y mis suposiciones estaban realmente equivocadas!)

El artículo concluye:

Para diseños, suponga que todos tienen una pantalla táctil. Los usuarios del mouse pueden usar controles de IU grandes mucho más fácilmente que los usuarios táctiles pueden usar los pequeños. Lo mismo ocurre con los estados flotantes.

Para eventos e interacciones, suponga que cualquiera puede tener una pantalla táctil. Implemente interacciones de teclado, mouse y toque una al lado de la otra, asegurando que ninguna se bloquee.

Dave Burt
fuente
3

Muchos de estos funcionan, pero requieren jQuery o los linters de JavaScript se quejan de la sintaxis. Teniendo en cuenta que su pregunta inicial requiere una forma de "JavaScript" (no jQuery, no Modernizr) para resolver esto, aquí hay una función simple que funciona siempre. También es lo más mínimo posible.

function isTouchDevice() {
    return !!window.ontouchstart;
}

console.log(isTouchDevice());

Una última ventaja que mencionaré es que este código es independiente del marco y del dispositivo. ¡Disfrutar!

seanforyou23
fuente
function isTouchScreen() { return window.matchMedia('(hover: none)').matches;}Esto funcionó para mí, así que estoy aquí agregando una contribución a esta respuesta, ya que también esperaba un hilo vainilla JS cuando Google me trajo aquí.
Daniel Lavedonio de Lima
2

Parece que Chrome 24 ahora admite eventos táctiles, probablemente para Windows 8. Por lo tanto, el código publicado aquí ya no funciona. En lugar de intentar detectar si el navegador admite el tacto, ahora estoy vinculando los eventos táctiles y de clic y me aseguro de que solo se llame uno:

myCustomBind = function(controlName, callback) {

  $(controlName).bind('touchend click', function(e) {
    e.stopPropagation();
    e.preventDefault();

    callback.call();
  });
};

Y luego llamándolo:

myCustomBind('#mnuRealtime', function () { ... });

Espero que esto ayude !

wizmagister
fuente
2

¡Todos los navegadores son compatibles, excepto Firefox para escritorio, siempre VERDADERO debido a que Firefox para escritorio admite un diseño receptivo para desarrolladores, incluso si hace clic en el botón táctil o no!

Espero que Mozilla arregle esto en la próxima versión.

Estoy usando el escritorio Firefox 28.

function isTouch()
{
    return !!("ontouchstart" in window) || !!(navigator.msMaxTouchPoints);
}
xicooc
fuente
¡Todavía es la versión 32.0 y aún no lo han arreglado! insano. ¿Por qué no puede ser esto toggable? Esto siempre regresa true:(
vsync
2

jQuery v1.11.3

Hay mucha buena información en las respuestas proporcionadas. Pero, recientemente, pasé mucho tiempo tratando de vincular todo en una solución de trabajo para lograr dos cosas:

  1. Detecta que el dispositivo en uso es un dispositivo de tipo pantalla táctil.
  2. Detecta que el dispositivo fue intervenido.

Además de esta publicación y Detección de dispositivos de pantalla táctil con Javascript , esta publicación de Patrick Lauke me resultó extremadamente útil: https://hacks.mozilla.org/2013/04/detecting-touch-its-the-why-not-the-how / /

Aquí está el código ...

$(document).ready(function() {
//The page is "ready" and the document can be manipulated.

    if (('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0))
    {
      //If the device is a touch capable device, then...
      $(document).on("touchstart", "a", function() {

        //Do something on tap.

      });
    }
    else
    {
      null;
    }
});

¡Importante! los*.on( events [, selector ] [, data ], handler ) método debe tener un selector, generalmente un elemento, que pueda manejar el evento "touchstart" o cualquier otro evento similar asociado con los toques. En este caso, es el elemento de hipervínculo "a".

Ahora, no necesita manejar el clic normal del mouse en JavaScript, porque puede usar CSS para manejar estos eventos usando selectores para el elemento de hipervínculo "a" de esta manera:

/* unvisited link */
a:link 
{

}

/* visited link */
a:visited 
{

}

/* mouse over link */
a:hover 
{

}

/* selected link */
a:active 
{

}

Nota: También hay otros selectores ...

serge-k
fuente
1
var isTouchScreen = 'createTouch' in document;

o

var isTouchScreen = 'createTouch' in document || screen.width <= 699 || 
    ua.match(/(iPhone|iPod|iPad)/) || ua.match(/BlackBerry/) || 
    ua.match(/Android/);

Sería una verificación más exhaustiva, supongo.

samuel segal
fuente
3
Sería bueno tener en cuenta que se uarefiere a navigator.userAgent. Además, la detección por ancho de pantalla puede dar resultados falsos si alguien abre un navegador en modo de pantalla no completa.
HoLyVieR
1

Yo suelo:

if(jQuery.support.touch){
    alert('Touch enabled');
}

en jQuery mobile 1.0.1

marca
fuente
1

También luché mucho con diferentes opciones sobre cómo detectar en Javascript si la página se muestra en un dispositivo de pantalla táctil o no. OMI, a partir de ahora, no existe una opción real para detectar la opción correctamente. Los navegadores informan eventos táctiles en máquinas de escritorio (porque el sistema operativo puede estar listo para tocar) o algunas soluciones no funcionan en todos los dispositivos móviles.

Al final, me di cuenta de que estaba siguiendo el enfoque equivocado desde el principio: si mi página tuviera un aspecto similar en dispositivos táctiles y no táctiles, tal vez no debería tener que preocuparme por detectar la propiedad en absoluto: mi escenario era para desactivar la información sobre herramientas sobre los botones en los dispositivos táctiles, ya que conducen a dos toques en los que quería un solo toque para activar el botón.

Mi solución fue refactorizar la vista para que no se necesita información sobre herramientas sobre un botón, y al final no tuve que detectar el dispositivo táctil de Javascript con métodos que tienen sus inconvenientes .

Miguel
fuente
1

Puede instalar el modernizador y usar un evento táctil simple. ¡Esto es muy efectivo y funciona en todos los dispositivos en los que lo he probado, incluida la superficie de Windows!

He creado un jsFiddle

function isTouchDevice(){
    if(Modernizr.hasEvent('touchstart') || navigator.userAgent.search(/Touch/i) != -1){
         alert("is touch");
            return true;
         }else{
            alert("is not touch");
            return false;
    }
}
Endjeechner
fuente
3
Bienvenido a SO! El código en sí mismo (como el código no comentado) rara vez constituye una respuesta. Puede mejorar esta respuesta agregando una explicación del fragmento.
ebarr
1

La respuesta práctica parece ser la que considera el contexto:

1) Sitio público (sin inicio de sesión)
Codifique la IU para que funcione con ambas opciones juntas.

2) Sitio de inicio de sesión
Capture si se produjo un movimiento del mouse en el formulario de inicio de sesión y guárdelo en una entrada oculta. El valor se pasa con las credenciales de inicio de sesión y se agrega a la sesión del usuario , por lo que puede usarse durante la sesión.

Jquery para agregar solo a la página de inicio de sesión:

$('#istouch').val(1); // <-- value will be submitted with login form

if (window.addEventListener) {
    window.addEventListener('mousemove', function mouseMoveListener(){
        // Update hidden input value to false, and stop listening
        $('#istouch').val(0); 
        window.removeEventListener('mousemove', mouseMoveListener);
    });
} 

(+1 a @Dave Burt y +1 a @Martin Lantzsch en sus respuestas)

martillo programador
fuente
1

El problema

Debido a los dispositivos híbridos que utilizan una combinación de entrada táctil y de mouse, debe poder cambiar dinámicamente el estado / variable que controla si un código debe ejecutarse si el usuario es un usuario táctil o no.

Los dispositivos táctiles también disparan mousemoveal toque.

Solución

  1. Suponga que el toque es falso en la carga.
  2. Espere hasta touchstartque se active un evento, luego configúrelo como verdadero.
  3. Si se activó el inicio táctil, agregue un controlador de movimiento del mouse.
  4. Si el tiempo entre disparos de dos eventos de mousemove fue inferior a 20 ms, suponga que están usando un mouse como entrada. Elimine el evento porque ya no es necesario y mousemove es un evento costoso para los dispositivos de mouse.
  5. Tan pronto como se activa nuevamente el inicio táctil (el usuario volvió a usar el tacto), la variable se restablece en verdadero. Y repita el proceso para que se determine de manera dinámica. Si, por algún milagro, el movimiento del mouse se dispara dos veces al tacto de manera absurdamente rápida (en mis pruebas es prácticamente imposible hacerlo dentro de los 20 ms), el siguiente inicio táctil lo volverá a poner en verdadero.

Probado en Safari iOS y Chrome para Android.

Nota: no estoy 100% seguro en los eventos de puntero para MS Surface, etc.

Codepen demo


const supportsTouch = 'ontouchstart' in window;
let isUsingTouch = false;

// `touchstart`, `pointerdown`
const touchHandler = () => {
  isUsingTouch = true;
  document.addEventListener('mousemove', mousemoveHandler);
};

// use a simple closure to store previous time as internal state
const mousemoveHandler = (() => {
  let time;

  return () => {
    const now = performance.now();

    if (now - time < 20) {
      isUsingTouch = false;
      document.removeEventListener('mousemove', mousemoveHandler);
    }

    time = now;
  }
})();

// add listeners
if (supportsTouch) {
  document.addEventListener('touchstart', touchHandler);
} else if (navigator.maxTouchPoints || navigator.msMaxTouchPoints) {
  document.addEventListener('pointerdown', touchHandler);
}
escarchado
fuente
1

En realidad, investigué esta pregunta y considero todas las situaciones. porque también es un gran problema en mi proyecto. Entonces llego a la siguiente función, funciona para todas las versiones de todos los navegadores en todos los dispositivos:

const isTouchDevice = () => {
  const prefixes = ['', '-webkit-', '-moz-', '-o-', '-ms-', ''];
  const mq = query => window.matchMedia(query).matches;

  if (
    'ontouchstart' in window ||
    (window.DocumentTouch && document instanceof DocumentTouch)
  ) {
    return true;
  }
  return mq(['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join(''));
};

Sugerencia : Definitivamente, elisTouchDevicejust devuelvebooleanvalores.

AmerllicA
fuente
0

Extensión supportobjeto jQuery :

jQuery.support.touch = 'ontouchend' in document;

Y ahora puedes consultarlo en cualquier lugar, así:

if( jQuery.support.touch )
   // do touch stuff
vsync
fuente
0

Esto parece estar funcionando bien para mí hasta ahora:

//Checks if a touch screen
is_touch_screen = 'ontouchstart' in document.documentElement;

if (is_touch_screen) {
  // Do something if a touch screen
}
else {
  // Not a touch screen (i.e. desktop)
}
Lewis James-Odwin
fuente
0

Cuando se conecta un mouse, se puede suponer con una tasa de aciertos bastante alta (diría que prácticamente al 100%) que el usuario mueve el mouse al menos una pequeña distancia una vez que la página está lista, sin hacer clic. El siguiente mecanismo detecta esto. Si se detecta, considero esto como un signo de falta de soporte táctil o, si es compatible, de menor importancia cuando se usa un mouse. Se supone un dispositivo táctil si no se detecta.

EDITAR Este enfoque puede no ajustarse a todos los propósitos. Se puede utilizar para controlar la funcionalidad que se activa en función de la interacción del usuario en la página cargada, por ejemplo, un visor de imágenes. El código a continuación también dejará el evento mousemove vinculado en dispositivos sin mouse como se destaca ahora. Otros enfoques pueden ser mejores.

Aproximadamente, es así (perdón por jQuery, pero similar en Javascript puro):

var mousedown, first, second = false;
var ticks = 10;
$(document).on('mousemove', (function(e) {
    if(UI.mousechecked) return;
    if(!first) {
        first = e.pageX;
        return;
        }
    if(!second && ticks-- === 0) {
        second = e.pageX;
        $(document).off('mousemove'); // or bind it to somewhat else
        }
    if(first  && second  && first !== second && !mousedown){
        // set whatever flags you want
        UI.hasmouse = true;
        UI.touch = false;
        UI.mousechecked = true;
    }

    return;
}));
$(document).one('mousedown', (function(e) {
    mousedown = true;
    return;
}));
$(document).one('mouseup', (function(e) {
    mousedown = false;
    return;
}));
resplandor
fuente