Detectando dispositivos de tela de toque com Javascript


129

Em Javascript / jQuery, como posso detectar se o dispositivo cliente possui um mouse?

Eu tenho um site que desliza um pequeno painel de informações quando o usuário passa o mouse sobre um item. Estou usando o jQuery.hoverIntent para detectar o foco, mas isso obviamente não funciona em dispositivos touchscreen como iPhone / iPad / Android. Então, nesses dispositivos, eu gostaria de reverter para tocar para mostrar o painel de informações.


6
Por que você não pode fazer as duas coisas? A funcionalidade de toque é indesejável em dispositivos sem tela sensível ao toque?
EMPraptor 20/10/10

1
Como alguns dispositivos mais novos não suportam :hover, provavelmente é melhor (ao codificar uma folha de estilo para vários dispositivos) usar :hoverpara fins puramente cosméticos.
quer

@ Empraptor: bom ponto - sim, eu poderia fazer isso. No entanto ... também estávamos pensando em sempre mostrar o painel em dispositivos com tela sensível ao toque - nesse caso, eu precisaria detectar o suporte.
Brad Robinson

Se você sempre pode mostrar o painel em dispositivos com tela sensível ao toque, também não pode mostrá-lo em outros dispositivos? Qual é o tamanho do painel e por que é desejável mostrá-lo apenas ao passar o mouse / tocar?
EMPraptor

Respostas:


12

+1 para fazer hovere clickambos. Uma outra maneira poderia ser usar consultas de mídia CSS e usar alguns estilos apenas para telas / dispositivos móveis menores, que são os que têm mais probabilidade de ter a funcionalidade de toque / toque. Portanto, se você tem alguns estilos específicos via CSS e, no jQuery, verifica esses elementos para as propriedades de estilo do dispositivo móvel, pode conectar-se a eles para escrever um código específico para o seu celular.

Veja aqui: http://www.forabeautifulweb.com/blog/about/hardboiled_css3_media_queries/


1
Boa solução, você provavelmente poderia fazer algo como uma verificação instantânea com uma ligação one (), para que seja acionada apenas na primeira vez.
Timothy Perez

O problema é que, se você segmentar pela largura da tela, quando girar o dispositivo (vamos usar o iphone 6+ 736x414), ele não terá o mesmo estilo. Portanto, não é a melhor solução: /
antoni 6/06

266
var isTouchDevice = 'ontouchstart' in document.documentElement;

Nota : O fato de um dispositivo suportar eventos de toque não significa necessariamente que ele é exclusivamente um dispositivo de tela de toque. Muitos dispositivos (como o meu Asus Zenbook) suportam eventos de clique e toque, mesmo quando não possuem nenhum mecanismo de entrada de toque real. Ao projetar para suporte por toque, sempre inclua suporte a eventos de clique e nunca assuma que um dispositivo seja exclusivamente um ou outro.


33
Conforme descrito nos documentos Modernizr, isso detecta apenas a capacidade do navegador , e não a capacidade do dispositivo ... você obterá um resultado falso positivo em dispositivos sem entrada por toque executando um navegador com capacidade de toque. Não conheço uma maneira de detectar a capacidade de toque do dispositivo de forma nativa, sem esperar apenas pela ocorrência de um evento de toque.
quer

12
Para detectar também o IE 10 touch, estou usando: (window.navigator.msMaxTouchPoints || ('ontouchstart' em document.documentElement));
precisa

2
'ontouchstart' in document.documentElement retorna incorretamente true no BlackBerry 9300
17/10/2013 mais simples

10
@typhon se o software (Win 8, navegadores modernos) suportar toque, isso sempre será verdade - mesmo se você estiver em hardware (desktop, monitor padrão, mouse e teclado) que não suporta toque. Portanto, esta solução está desatualizada.
Barney

1
funnyItsNotCamelCaseAsJsIsThroughout. Quero dizer, as pessoas agora precisarão copiar, colar E editar o código. :)
Ross

20

O teste encontrado para o window.Touch não funcionou no Android, mas faz isso:

function is_touch_device() {
  return !!('ontouchstart' in window);
}

Veja o artigo: Qual é a melhor maneira de detectar um dispositivo 'touch screen' usando JavaScript?


Isso detecta telas sensíveis ao toque, mas tenha cuidado, pois também retorna VERDADEIRO para laptops com telas sensíveis ao toque. Isso pode ser um problema se você estiver tentando distinguir se o usuário é de telefone / tablet OU computador / laptop porque, para laptops com tela sensível ao toque, ele retorna TRUE.
Combine

8
return (('ontouchstart' in window)
      || (navigator.maxTouchPoints > 0)
      || (navigator.msMaxTouchPoints > 0));

Motivo para usar maxTouchPoints junto com o msMaxTouchPoints:

A Microsoft declarou que, começando com o Internet Explorer 11, a versão prefixada por fornecedor desta propriedade da Microsoft (msMaxTouchPoints) pode ser removida e recomenda o uso de maxTouchPoints.

Fonte: http://ctrlq.org/code/19616-detect-touch-screen-javascript


este dispositivo trabalhou e trabalhou no google ferramentas para desenvolvedores Chrome simular obrigado
Behnam Mohammadi

7
if ("ontouchstart" in window || navigator.msMaxTouchPoints) {
    isTouch = true;
} else {
    isTouch = false;
}

Funciona em todos os lugares !!


E o que isso tem a ver com um mouse? (a causa real)
hexalys

Seria mais simples de fazerisTouch = "ontouchstart" in window || navigator.msMaxTouchPoints;
Andrew


4

O Google Chrome parece retornar falsos positivos neste:

var isTouch = 'ontouchstart' in document.documentElement;

Suponho que tenha algo a ver com a capacidade de "emular eventos de toque" (F12 -> configurações no canto inferior direito -> guia "substitui" - - última caixa de seleção). Sei que está desativado por padrão, mas é com isso que conecto a alteração nos resultados (o método "in" usado para trabalhar no Chrome). No entanto, isso parece estar funcionando, tanto quanto eu testei:

var isTouch = !!("undefined" != typeof document.documentElement.ontouchstart);

Em todos os navegadores em que corri esse código, o typeof é "objeto", mas tenho mais certeza de que é indefinido :-)

Testado no IE7, IE8, IE9, IE10, Chrome 23.0.1271.64, Chrome para iPad 21.0.1180.80 e iPad Safari. Seria legal se alguém fizesse mais alguns testes e compartilhasse os resultados.


Ambos os métodos retornam falsos positivos no Win 8 PC com FF 23 e Chrome 28. Esse é sempre o caso ou é porque eu já tive uma tela sensível ao toque conectada a este computador - provavelmente antes de instalar o FF e o Chrome - mas não mais? Não tenho o conjunto de opções "emular eventos de toque".
Typhon

É sempre uma luta com novo hardware. Os navegadores precisam trabalhar com as camadas de abstração do sistema operacional ... que nem sempre implementam tudo ... em suma, com o JS, você precisa confiar no navegador :) Nunca existe uma maneira universal.
Ash

Ambos retornam ao Ubuntu Firefox em um laptop sem toque.
NoBugs

4

Escrevi isso para um dos meus sites e provavelmente é a solução mais infalível. Especialmente porque até o Modernizr pode obter falsos positivos na detecção de toque.

Se você estiver usando jQuery

$(window).one({
  mouseover : function(){
    Modernizr.touch = false; // Add this line if you have Modernizr
    $('html').removeClass('touch').addClass('mouse');
  } 
});

ou apenas JS puro ...

window.onmouseover = function(){ 
    window.onmouseover = null;
    document.getElementsByTagName("html")[0].className += " mouse";
}

4
Seja embora cuidado: pelo menos iPads jogar onmouseovers também
Joril

14
Maldito seja, Apple!
Timothy Perez

E as pessoas que usam o IE em um tablet Windows podem querer usar o toque e o mouse.
Sebazzz

Esta postagem foi feita antes da existência do Windows Tablet.
Timothy Perez

@ s427 - Fecking IE ... basta verificar o IE8. Acho que não há dispositivos móveis com <= IE8.
Timothy Perez

4

Para meu primeiro post / comentário: todos sabemos que o 'touchstart' é acionado antes do clique. Também sabemos que, quando o usuário abrir sua página, ele (a) irá: 1) mover o mouse 2) clicar em 3) tocar na tela (para rolar ou ... :))

Vamos tentar algo:

// -> Iniciar: jQuery

var hasTouchCapabilities = 'ontouchstart' in window && (navigator.maxTouchPoints || navigator.msMaxTouchPoints);
var isTouchDevice = hasTouchCapabilities ? 'maybe':'nope';

//attach a once called event handler to window

$(window).one('touchstart mousemove click',function(e){

    if ( isTouchDevice === 'maybe' && e.type === 'touchstart' )
        isTouchDevice = 'yes';
});

// <- Fim: jQuery

Tenha um bom dia!


3

Eu testei o seguinte código mencionado acima na discussão

 function is_touch_device() {
    return !!('ontouchstart' in window);
 }

funciona no Android Mozilla, chrome, Opera, navegador padrão do Android e safari no iphone ... tudo positivo ...

parece sólido para mim :)


Super simples e funciona bem para mim. Testado no Android (antigo Galaxy Note) e com emuladores (Chrome) e no iPad.
22815 Ralf

Retorna um falso positivo para mim no Chrome.
James


2

Isso funciona para mim:

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

1
Em quantas plataformas, navegadores, sistemas operacionais 'você testou?
precisa saber é o seguinte

1
FF, Chrome, Safari no Android e iOS (iPad)
Turtletrail

1
Bom o suficiente. Acabei de testar no desktop e recebi um monte de "indefinido", o que torna a estrutura do IF um pouco invasiva. Se você ajustar um pouco o valor de retorno, assim: return true == ("inicie o touch" na janela || window.DocumentTouch && document instanceof do DocumentTouch); Então você tem verdadeiro ou falso :-)
BerggreenDK

2
No Chrome, "ontouchstart" na janela é verdadeiro no meu PC sem uma tela de toque; portanto, isso não funciona. Como observado anteriormente, isso testa se o navegador é compatível com toque. Além disso, true == não faz nada e deve ser omitido.
Rakensi

1
Quando eu tento isso no Chrome com o emulador embutido, ele detecta o toque quando é ligado no emulador e não detecta o toque quando é desligado. Então funciona bem para mim. Mas: eu uso a versão curta de Prasad (abaixo) que não usa o || no código de Turtletrail. E: não me importo se funciona para 100% dos dispositivos. 99% fará por mim.
Ralf

1

Se você usa o Modernizr , é muito fácil usar Modernizr.touchcomo mencionado anteriormente.

No entanto, eu prefiro usar uma combinação de Modernizr.touche teste de agente de usuário, apenas por segurança.

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
    }

Se você não usa o Modernizr, pode simplesmente substituir a Modernizr.touchfunção acima por('ontouchstart' in document.documentElement)

Observe também que ao testar o agente do usuário, iemobilevocê terá uma gama mais ampla de dispositivos móveis Microsoft detectados do que Windows Phone.

Veja também esta pergunta do SO


2
É a mesma resposta para 4 perguntas agora ... e esta não é uma solução para a pergunta que ele está fazendo.
jycr753

1
Eu acredito que não responder à pergunta aqui
Peter-Pan

não é a resposta mas é uma dica eu acho que para quem que querem detectar se o dispositivo é palpável antes do toque do usuário que
Shahadat Hossain Khan

1

No jQuery Mobile, você pode simplesmente fazer:

$.support.touch

Não sei por que isso é tão indocumentado .. mas é seguro para navegadores cruzados (duas versões mais recentes dos navegadores atuais).


0

Como já mencionado, um dispositivo pode suportar entradas de mouse e toque. Muitas vezes, a questão não é "o que é suportado", mas "o que é usado atualmente".

Nesse caso, você pode simplesmente registrar eventos do mouse (incluindo o ouvinte ao passar o mouse) e tocar em eventos da mesma forma.

element.addEventListener('touchstart',onTouchStartCallback,false);

element.addEventListener('onmousedown',onMouseDownCallback,false);

...

O JavaScript deve chamar automaticamente o ouvinte correto com base na entrada do usuário. Então, no caso de um evento de toque,onTouchStartCallback será acionado, emulando seu código de foco.

Observe que um toque pode disparar os dois tipos de ouvintes, toque e mouse. No entanto, o ouvinte de toque é o primeiro e pode impedir que ouvintes de mouse subseqüentes sejam acionados chamando event.preventDefault().

function onTouchStartCallback(ev) {
    // Call preventDefault() to prevent any further handling
    ev.preventDefault();
    your code...
}

Leia mais aqui .


-3

Para o desenvolvimento do iPad, estou usando:

  if (window.Touch)
  {
    alert("touchy touchy");
  }
  else
  {
    alert("no touchy touchy");
  }

Posso então ligar-me seletivamente aos eventos baseados em toque (por exemplo, ontouchstart) ou em eventos baseados em mouse (por exemplo, onmousedown). Ainda não testei no Android.


1
Isso não funciona com o Opera Mobile 10 ou o Internet Explorer Mobile 6 (Windows Mobile 6.5).
doubleJ

4
aconselhamento incorreto entre navegadores / SOs cruzados / plataformas cruzadas.
precisa saber é o seguinte
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.