O problema de passar o mouse do iPad / iPhone faz com que o usuário clique duas vezes em um link

125

Eu tenho alguns sites que eu criei há tempos, que usam eventos jquery mouse ... Acabei de receber um ipad e notei que todo o mouse sobre eventos é traduzido em cliques ... então, por exemplo, eu tenho que fazer dois cliques em vez de um .. (a primeira focalização, que o clique real)

existe uma solução pronta para resolver isso? talvez um comando jquery que eu deveria ter usado em vez de mouseover / out etc. obrigado!

Francesco
fonte
1
a que seus eventos estão vinculados? por exemplo, os eventos onclick devem funcionar bem ... onmouseover, onmouseout e CSS: hover são os que são um pouco difíceis de manusear, pois não há "hover" disponível em uma tela de toque. Você tem um exemplo de código?
scunliffe
Uma coisa que eu sugiro que você faça é repensar sua interface, se possível. a interação no ipad / iphone não reflete exatamente a de um PC, e provavelmente é uma coisa sensata fazer com que o site pareça ter sido escrito para o ipad / iphone / outros dispositivos de toque com mecanismos multitoque semelhantes. Apenas um pensamento.
Jer
Eu concordo com "jer". Essa é uma pergunta estranha, não acho que a solução aqui seja uma "solução alternativa" pessoalmente. Eu acho que traduzir um "passar o mouse" em um navegador de desktop para um "toque de dedo" em um navegador de tela sensível ao toque faz sentido. Se você concorda com essa tradução, mas deseja um toque em vez de dois, provavelmente faria a detecção de recursos para os eventos do iPad (por exemplo, "touchstart") e alteraria os manipuladores de eventos. Talvez extraia seu código em um tipo de funcionalidade "toque ou clique" no plug-in jquery, que é acionado de maneira diferente com base nos recursos, mas parece específico para seu site / aplicativo para mim.
Andy Atkinson
1
Na verdade, considero esta tradução um recurso. Se você configurou eventos de foco, deve ter havido algum utilitário para vê-los. Um único toque revela um elemento pairado; um segundo toque segue o link "por trás" do cursor.
Aaron

Respostas:

205

Ainda não testei isso completamente, mas como o iOS aciona eventos de toque, isso pode funcionar, desde que você esteja em uma configuração de jQuery.

$('a').on('click touchend', function(e) {
    var el = $(this);
    var link = el.attr('href');
    window.location = link;
});

A idéia é que o Mobile WebKit dispara um touchendevento no final de um toque, para que possamos ouvi-lo e redirecionar o navegador assim que um touchendevento for disparado em um link.

cduruk
fonte
17
Onde está minha recompensa? : P
cduruk 6/08/10
2
Paciência, Padwan. SO disse que leva 24 horas para entrar em vigor.
Andrew Hedges
2
A partir do jQuery 1.7, .oné preferível .live. Depois de ler esta resposta, descobri que alterar meu código para $('a').on('click touchend', function(e) {...})funciona de maneira excelente.
Blazemonger
23
Bem, isso resolve o problema inicial, mas cria um novo: ao passar o mouse sobre o clicado. Esta não é uma solução.
luksak
9
Isso tem suas falhas. Se você clicar em um link, target="_blank"ele será aberto na mesma janela E em uma nova janela.
precisa
37

Não está totalmente claro qual é a sua pergunta, mas se você deseja apenas eliminar o clique duplo, mantendo o efeito de foco do mouse, meu conselho é:

  • Adicione efeitos de foco em touchstarte mouseenter.
  • Remover efeitos de foco em mouseleave , touchmovee click.

fundo

Para simular um mouse, navegadores como o Webkit mobile acionam os seguintes eventos se um usuário tocar e soltar um dedo na tela de toque (como o iPad) (fonte: Touch And Mouse no html5rocks.com):

  1. touchstart
  2. touchmove
  3. touchend
  4. Atraso de 300 ms, em que o navegador garante um toque único, não um toque duplo
  5. mouseover
  6. mouseenter
    • Nota : Se um mouseover, mouseenterou mousemoveevento muda o conteúdo da página, os seguintes eventos não são disparados.
  7. mousemove
  8. mousedown
  9. mouseup
  10. click

Não parece possível simplesmente dizer ao navegador da web para pular os eventos do mouse.

O que é pior: se um evento de mouseover altera o conteúdo da página, o evento de clique nunca é acionado, conforme explicado no Guia de Conteúdo da Web do Safari - Manipulação de Eventos , em particular a figura 6.4 em Eventos com um dedo . O que exatamente é uma "alteração de conteúdo" depende do navegador e da versão. Descobri que, para o iOS 7.0, uma alteração na cor do plano de fundo não é (ou não é mais?).

Solução explicada

Para recapitular:

  • Adicione efeitos de foco instantâneo touchstartemouseenter.
  • Remova os efeitos de foco emmouseleave , touchmovee click.

Observe que não há ação no touchend !

Isso claramente funciona para eventos de mouse: mouseentere mouseleave(versões ligeiramente aprimoradas de mouseovere mouseout) são acionadas, e adicione e remova o foco.

Se o usuário realmente for clickum link, o efeito de foco instantâneo também será removido. Isso garante que ele seja removido se o usuário pressionar o botão Voltar no navegador da web.

Isso também funciona para eventos de toque: touchstarto efeito de foco é adicionado. É '' 'não' '' removido em touchend. Ele é adicionado novamente mouseentere, como isso não causa alterações no conteúdo (já foi adicionado), o clickevento também é acionado e o link é seguido sem a necessidade do usuário clicar novamente!

Os 300 ms de atraso que um navegador possui entre um touchstartevento e clicksão realmente utilizados porque o efeito de foco será mostrado durante esse curto período de tempo.

Se o usuário decidir cancelar o clique, um movimento do dedo fará o mesmo normalmente. Normalmente, isso é um problema, pois nenhum mouseleaveevento é disparado e o efeito de foco permanece no lugar. Felizmente, isso pode ser facilmente corrigido removendo o efeito de foco em touchmove.

É isso aí!

Observe que é possível remover o atraso de 300ms, por exemplo, usando a biblioteca FastClick , mas isso está fora do escopo desta pergunta.

Soluções alternativas

Encontrei os seguintes problemas com as seguintes alternativas:

  • detecção de navegador: extremamente propenso a erros. Assume que um dispositivo possui mouse ou toque, enquanto uma combinação de ambos se tornará cada vez mais comum quando o toque for prolifirado.
  • Detecção de mídia CSS: a única solução somente CSS que eu conheço. Ainda propenso a erros e ainda pressupõe que um dispositivo tenha mouse ou toque, enquanto ambos são possíveis.
  • Emule o evento click em touchend: Isso seguirá incorretamente o link, mesmo se o usuário quiser apenas rolar ou ampliar, sem a intenção de realmente clicar no link.
  • Use uma variável para suprimir os eventos do mouse: define uma variável touchendusada como condição if nos eventos subsequentes do mouse para impedir alterações de estado naquele momento. A variável é redefinida no evento click. Esta é uma solução decente se você realmente não deseja um efeito de foco instantâneo nas interfaces de toque. Infelizmente, isso não funciona se um touchendé acionado por outro motivo e nenhum evento de clique é acionado (por exemplo, o usuário rolou ou aumentou o zoom) e, posteriormente, tenta seguir o link com um mouse (ou seja, em um dispositivo com interface de mouse e touch) )

Leitura adicional

Consulte também o problema de clique duplo do iPad / iPhone e Desativar efeitos de foco instantâneo em navegadores móveis .

MacFreek
fonte
2
parece ser a melhor explicação para quem quer mais do que a solução exata. Thanx
antiplayer
Agradecimentos especiais pelas informações sobre a cor de fundo para> iOS7. Passei algum tempo tentando descobrir quando isso começou a funcionar.
staffang
20

Parece que existe uma solução CSS, afinal. O motivo pelo qual o Safari aguarda um segundo toque é devido à imagem (ou elementos) de plano de fundo que você normalmente atribui ao evento: hover. Se não houver nenhum para ser mostrado - você não terá problemas. A solução é direcionar a plataforma iOS com um arquivo CSS secundário (ou estilo no caso de uma abordagem JS) que substitua: passe o plano de fundo para herdar, por exemplo, e oculte os elementos que você exibiria ao passar o mouse:

Aqui está um exemplo de CSS e HTML - um bloco de produto com um rótulo com estrela no mouse sobre:

HTML:

<a href="#" class="s"><span class="s-star"></span>Some text here</a>

CSS:

.s {
   background: url(some-image.png) no-repeat 0 0;

}
.s:hover {
   background: url(some-image-r.png) no-repeat 0 0;
}

.s-star {
   background: url(star.png) no-repeat 0 0;
   height: 56px;
   position: absolute;
   width: 72px;
   display:none;
}

.s:hover .s-star {
   display:block;
}

Solução (CSS secundário):

/* CSS */
/* Keep hovers the same or hidden */
.s:hover {
   background:inherit;
}
.s:hover .s-star {
   display:none;
}
Pavel Bogatinov
fonte
Esta resposta é voltada para imagens de fundo, mas você tem uma solução para alterações simples de opacidade? Esta solução não funciona para isso.
31515 Ian
5

Não há necessidade de complicar demais.

$('a').on('touchend', function() {
    $(this).click();
});
Jsonras
fonte
5

O que funcionou para mim é o que os outros aqui já disseram:

Não mostre / oculte elementos em hover ou mousemove (que é o evento no meu caso).

Veja o que a Apple diz ( https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html ):

Um elemento clicável é um link, elemento de formulário, área de mapa de imagem ou qualquer outro elemento com manipuladores de remoção de mouse, remoção de mouse, mouse ou onclick

Se o usuário tocar em um elemento clicável, os eventos chegarão nesta ordem: mouseover, mousemove, mousedown, mouseup e click. Além disso, se o conteúdo da página mudar no evento mousemove, nenhum evento subsequente na sequência será enviado. Esse comportamento permite que o usuário toque no novo conteúdo.

Portanto, você pode usar a solução do @ woop: detecte o userAgent, verifique se é um dispositivo iOS e ligue o evento. Acabei usando essa técnica porque atende às minhas necessidades e faz mais sentido não vincular eventos de foco quando você não deseja.

Mas ... se você não quiser mexer com userAgents e ainda ocultar / mostrar elementos em hover / mousemove, descobri que você pode fazer isso usando javascript nativo, assim:

$("body").on("mouseover", function() {
       document.getElementsByTagName("my-class")[0].style.display = 'block'; //show element
       document.querySelector(".my-selector div").style.display = 'none'; // hide element
});

Isso funcionará na versão Desktop e não fará nada na versão móvel.

E para um pouco mais de compatibilidade ...

$("body").on("mouseover", function() {
   if (document.getElementsByTagName && document.querySelector) { // check compatibility
       document.getElementsByTagName("my-class")[0].style.display = 'block'; //show element
       document.querySelector(".my-selector div").style.display = 'none'; // hide element
    } else {
        $(".my-class").show();
        $(".my-selector div").hide();
    }
});
Adauto
fonte
1
Esse bit "se o conteúdo da página mudar no evento mousemove, nenhum evento subsequente na sequência será enviado" realmente fez isso por mim. Eu tinha uma página em que os links de cabeçalho exigiriam um toque duplo, onde os botões do conteúdo (com todas as transições felizes do css3 em em) exigiriam apenas um único toque. Apareceu que os links do cabeçalho tinham um pseudo-elemento que passou de opacidade: 0 para opacidade: 1 ao passar o mouse. A remoção desse efeito resolveu imediatamente o problema e eu encontrei uma solução alternativa em CSS para ainda obter a aparência desejada.
Fake Haak
3

A solução do cduruk foi bastante eficaz, mas causou problemas em algumas partes do meu site. Como eu já estava usando o jQuery para adicionar a classe de foco CSS, a solução mais fácil era simplesmente não adicionar a classe de foco CSS em dispositivos móveis (ou, mais precisamente, SOMENTE adicioná-la quando NÃO estiver em um dispositivo móvel).

Aqui estava a ideia geral:

var device = navigator.userAgent.toLowerCase();
var ios = device.match(/(iphone|ipod|ipad)/);

if (!(ios)) {
    $(".portfolio-style").hover(
        function(){
            $(this).stop().animate({opacity: 1}, 100);
            $(this).addClass("portfolio-red-text");
        },
        function(){
            $(this).stop().animate({opacity: 0.85}, 100);
            $(this).removeClass("portfolio-red-text");
        }
    );
}

* código reduzido para fins ilustrativos

woop
fonte
1
Esta é claramente a resposta. As outras "soluções" não corrigem o problema. O safari para iOS é claramente falho ao pensar que queremos passar o mouse primeiro. Outros sistemas operacionais têm recursos de foco real quando você passa o mouse sobre um item.
Joshua pacote de
Essa foi a única coisa que funcionou para mim. Muito obrigado!
Tx291
2

Eu acho que seria sensato tentar mouseenterno lugar de mouseover. É o que é usado internamente ao vincular .hover(fn,fn)e geralmente é o que você deseja.

Paul Irish
fonte
1

Eu tive os seguintes problemas com as soluções existentes e encontrei algo que parece resolver todas elas. Isso pressupõe que você está buscando algo entre navegadores, dispositivos e não deseja farejar dispositivos.

Os problemas que isso resolve

Usando apenas touchstartou touchend:

  • Faz com que o evento seja acionado quando as pessoas estão tentando rolar o conteúdo e passou o dedo sobre esse elemento quando começaram a passar o dedo - acionando a ação inesperadamente.
  • Pode fazer com que o evento seja acionado por pressão longa , semelhante ao clique com o botão direito do mouse na área de trabalho. Por exemplo, se o evento de clique for para o URL X, e o usuário pressionar para abrir o X em uma nova guia, o usuário ficará confuso ao encontrar o X aberto nas duas guias. Em alguns navegadores (por exemplo, iPhone), pode até impedir que o menu de pressão longa apareça.

Desencadeando mouseovereventos do touchstarte mouseoutno touchmovetem consequências menos graves, mas não interfere com o comportamento habitual navegador, por exemplo:

  • Uma pressão longa acionaria um mouseover que nunca termina.
  • Muitos navegadores Android tratam a localização do dedo touchstartcomo um mouseover, que é mouseouteditado a seguir touchstart. Uma maneira de ver o conteúdo do mouse no Android é, portanto, tocar na área de interesse e mexer o dedo, rolando a página levemente. Tratar touchmovecomo mouseoutquebra isso.

A solução

Em teoria, você pode simplesmente adicionar uma bandeira com touchmove, mas os iPhones acionam o touchmove mesmo que não haja movimento. Em teoria, você poderia simplesmente comparar o touchstarte touchendeventos pageXe pageY , mas em iPhones, não há nenhuma touchend pageXoupageY .

Infelizmente, para cobrir todas as bases, acaba um pouco mais complicado.

$el.on('touchstart', function(e){
    $el.data('tstartE', e);
    if(event.originalEvent.targetTouches){
        // store values, not reference, since touch obj will change
        var touch = e.originalEvent.targetTouches[0];
        $el.data('tstartT',{ clientX: touch.clientX, clientY: touch.clientY } );
    }
});
$el.on('touchmove', function(e){
    if(event.originalEvent.targetTouches){
        $el.data('tstartM', event.originalEvent.targetTouches[0]);
    }
});

$el.on('click touchend', function(e){
    var oldE = $el.data('tstartE');
    if( oldE && oldE.timeStamp + 1000 < e.timeStamp ) {
        $el.data('tstartE',false);
        return;
    }
    if( $el.data('iosTouchM') && $el.data('tstartT') ){
        var start = $el.data('tstartT'), end = $el.data('tstartM');
        if( start.clientX != end.clientX || start.clientY != end.clientY ){
            $el.data('tstartT', false);
            $el.data('tstartM', false);
            $el.data('tstartE',false);
            return;
        }
    }
    $el.data('tstartE',false);

Em teoria, existem maneiras de obter o tempo exato usado para uma impressão longa, em vez de apenas usar 1000 como uma aproximação, mas na prática não é tão simples e é melhor usar um proxy razoável .

user56reinstatemonica8
fonte
1

A resposta de MacFreak foi extremamente útil para mim. Aqui estão alguns códigos práticos, caso ajudem.

PROBLEMA - aplicando touchend significa que toda vez que você o dedo sobre um elemento, ele responde como se você o tivesse pressionado, mesmo se você estivesse apenas tentando passar o mouse.

Estou criando um efeito com o jQuery que diminui uma linha sob alguns botões para "destacar" o botão pairado. Não quero que isso signifique que você deve pressionar o botão duas vezes nos dispositivos sensíveis ao toque para seguir o link.

Aqui estão os botões:

<a class="menu_button" href="#">
    <div class="menu_underline"></div>
</a>

Eu quero que a div "menu_underline" desapareça no mouseover e desapareça no mouseout. MAS quero que os dispositivos de toque possam seguir o link em um único clique, não em dois.

SOLUÇÃO - Aqui está o jQuery para fazê-lo funcionar:

//Mouse Enter
$('.menu_button').bind('touchstart mouseenter', function(){
    $(this).find(".menu_underline").fadeIn();
});

//Mouse Out   
$('.menu_button').bind('mouseleave touchmove click', function(){
    $(this).find(".menu_underline").fadeOut();
});

Muito obrigado pela sua ajuda neste MacFreak.

Mad Dog Cadogen
fonte
1

Acabei de descobrir que funciona se você adicionar um ouvinte vazio, não me pergunte por que, mas testei no iPhone e iPad com o iOS 9.3.2 e funcionou bem.

if(/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream){
    var elements = document.getElementsByTagName('a');
    for(var i = 0; i < elements.length; i++){
        elements[i].addEventListener('touchend',function(){});
    }
}
freek van der wand
fonte
0

Eu tive o mesmo problema, mas não em um dispositivo de toque. O evento é acionado toda vez que você clica. Há algo sobre enfileiramento de eventos ou algo assim.

No entanto, minha solução foi a seguinte: no evento de clique (ou toque?), Você define um cronômetro. Se o link for clicado novamente dentro de X ms, você retornará false.

Para definir por timer de elemento, você pode usar $.data().

Isso também pode corrigir o problema do @Ferdy descrito acima.

Ionuț Staicu
fonte
Você pode postar como esse código se parece? Estou tendo esse problema do evento de clique sendo acionado duas vezes.
fantasia
0

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

No entanto, prefiro usar uma combinação de Modernizr.touch e 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));

function Tipsy(element, options) {
    this.$element = $(element);
    this.options = options;
    this.enabled = !isTouchDevice;
    this.fixTitle();
};

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

Observe também que o teste do agente do usuário iemobile oferecerá uma gama mais ampla de dispositivos móveis Microsoft detectados que o Windows Phone.

Peter-Pan
fonte
0

Você pode usar click touchend,

exemplo:

$('a').on('click touchend', function() {
    var linkToAffect = $(this);
    var linkToAffectHref = linkToAffect.attr('href');
    window.location = linkToAffectHref;
});

O exemplo acima afetará todos os links em dispositivos touch.

Se você deseja direcionar apenas links específicos, pode fazer isso definindo uma classe neles, ou seja:

HTML:

<a href="example.html" class="prevent-extra-click">Prevent extra click on touch device</a>

Jquery:

$('a.prevent-extra-click').on('click touchend', function() {
    var linkToAffect = $(this);
    var linkToAffectHref = linkToAffect.attr('href');
    window.location = linkToAffectHref;
});

Felicidades,

Jeroen

Jeroen W
fonte
0

Encontrei uma situação semelhante em que eventos vinculados aos estados mouseenter / mouseleave / click de um elemento, mas em um iPhone, o usuário teve que clicar duas vezes no elemento para acionar primeiro o evento mouseenter e, em seguida, novamente para acionar o evento click .

Resolvi isso usando um método semelhante ao descrito acima, mas fiz uso do plugin jQuery $ .browser (para jQuery 1.9>) e adicionei um evento .trigger ao evento de ligação do mouseenter, da seguinte maneira:

// mouseenter event
$('.element').on( "mouseenter", function() {
    // insert mouseenter events below

    // double click fix for iOS and mouseenter events
    if ($.browser.iphone || $.browser.ipad) $(this).trigger('click');
});
// mouseleave event
$('.element').on( "mouseleave", function() { 
    // insert mouseout events below
});
// onclick event
$('.element').on( "click", function() {
    // insert click events below
});

O .trigger evita a necessidade de clicar duas vezes no elemento acionando o manipulador de eventos .click no mouseenter (ou clique inicial) do elemento quando visualizado em iPhones ou iPads. Pode não ser a solução mais elegante, mas funciona muito bem no meu caso e utiliza um plug-in que eu já tinha instalado, e exigi que eu adicionasse uma única linha de código para que meus eventos existentes funcionassem nesses dispositivos.

Você pode obter o plugin jQuery $ .browser aqui: https://github.com/gabceb/jquery-browser-plugin

ouija
fonte
0

Apenas uma melhoria para evitar o redirecionamento quando você desliza o dedo em um link por engano.

// tablet "one touch (click)" X "hover" > link redirection
$('a').on('touchmove touchend', function(e) {

    // if touchmove>touchend, set the data() for this element to true. then leave touchmove & let touchend fail(data=true) redirection
    if (e.type == 'touchmove') {
        $.data(this, "touchmove_cancel_redirection", true );
        return;
    }

    // if it's a simple touchend, data() for this element doesn't exist.
    if (e.type == 'touchend' && !$.data(this, "touchmove_cancel_redirection")) {
        var el = $(this);
        var link = el.attr('href');
        window.location = link;
    }

    // if touchmove>touchend, to be redirected on a future simple touchend for this element
    $.data(this, "touchmove_cancel_redirection", false );
});
Lenor
fonte
0

Com inspiração no MacFreak, montei algo que funciona para mim.

Esse método js evita que o cursor fique preso em um ipad e evita que o clique seja registrado como dois cliques em alguns casos. No CSS, se você tiver alguma: classes hover psudo em seu css, altere-as para .hover Por exemplo .some-class: hover para .some-class.hover

Teste este código em um ipad para ver como o método css e js hover se comportam de maneira diferente (apenas no efeito hover). O botão CSS não possui um alerta de clique sofisticado. http://jsfiddle.net/bensontrent/ctgr6stm/

function clicker(id, doStuff) {
  id.on('touchstart', function(e) {
    id.addClass('hover');
  }).on('touchmove', function(e) {
    id.removeClass('hover');
  }).mouseenter(function(e) {
    id.addClass('hover');
  }).mouseleave(function(e) {
    id.removeClass('hover');
  }).click(function(e) {
    id.removeClass('hover');
    //It's clicked. Do Something
    doStuff(id);
  });
}

function doStuff(id) {
  //Do Stuff
  $('#clicked-alert').fadeIn(function() {
    $(this).fadeOut();
  });
}
clicker($('#unique-id'), doStuff);
button {
  display: block;
  margin: 20px;
  padding: 10px;
  -webkit-appearance: none;
  touch-action: manipulation;
}
.hover {
  background: yellow;
}
.btn:active {
  background: red;
}
.cssonly:hover {
  background: yellow;
}
.cssonly:active {
  background: red;
}
#clicked-alert {
  display: none;
}
<button id="unique-id" class="btn">JS Hover for Mobile devices<span id="clicked-alert"> Clicked</span>

</button>
<button class="cssonly">CSS Only Button</button>
<br>This js method prevents hover from sticking on an ipad, and prevents the click registering as two clicks. In CSS, if you have any :hover in your css, change them to .hover For example .some-class:hover to .some-class.hover

Benson
fonte
0

Para que os links funcionem sem interromper a rolagem por toque, resolvi isso com o evento "tap" do jQuery Mobile:

    $('a').not('nav.navbar a').on("tap", function () {
        var link = $(this).attr('href');
        if (typeof link !== 'undefined') {
            window.location = link;
        }
    });
alces
fonte
0

Estou muito atrasado, eu sei, mas esta é uma das soluções mais fáceis que encontrei:

    $('body').on('touchstart','*',function(){   //listen to touch
        var jQueryElement=$(this);  
        var element = jQueryElement.get(0); // find tapped HTML element
        if(!element.click){
            var eventObj = document.createEvent('MouseEvents');
            eventObj.initEvent('click',true,true);
            element.dispatchEvent(eventObj);
        }
    });

Isso não funciona apenas para links (tags âncora), mas também para outros elementos. Espero que isto ajude.

writeToBhuwan
fonte
0

Este pequeno trecho parece funcionar. Acione o evento de clique quando o link for tocado:

  $('a').on('touchstart', function() {
    $(this).trigger('click');
  });
Flo Develop
fonte
0

Nenhuma da outra resposta funciona para mim. Meu aplicativo tem muitos ouvintes de eventos, caixas de seleção e links próprios que têm ouvintes e links sem ouvintes.

Eu uso isso:

var selector = "label, a, button";
var timer;
var startX;
var startY;
$(document).on("click", selector, function (e) {
    if ($(this).data("touched") === true) {
        e.stopImmediatePropagation();
        return false;
    }
    return;
}).on("touchend", selector, function (e) {
    if (Math.abs(startX - e.originalEvent.changedTouches[0].screenX) > 10 || Math.abs(startY - e.originalEvent.changedTouches[0].screenY) > 10)
        // user action is not a tap
        return;
    var $this = $(this);
    // Visit: http://stackoverflow.com/questions/1694595/can-i-call-jquery-click-to-follow-an-a-link-if-i-havent-bound-an-event-hand/12801548#12801548
    this.click();
    // prevents double click
    $this.data("touched", true);
    if (timer)
        clearTimeout(timer);
    setTimeout(function () {
        $this.data("touched", false);
    }, 400);
    e.stopImmediatePropagation();
    return false;
}).on("touchstart", function (e) {
    startX = e.originalEvent.changedTouches[0].screenX;
    startY = e.originalEvent.changedTouches[0].screenY;
});
Magu
fonte
0

Isso funciona para mim quando você tem o menu suspenso jquery ui

if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
      $('.ui-autocomplete').off('menufocus hover mouseover');
}
Makubex
fonte
0

Evite alterar o estilo "display" dentro do evento hover css. Eu tinha "display: block" no estado de foco. Depois de remover o ios, lins passou por um único toque. A propósito, parece que as atualizações mais recentes do IOS corrigiram esse "recurso"

Hellbyte
fonte
0

A maneira mais simples de resolver clique duas vezes no IPad é agrupar seu css para efeito de foco na consulta de mídia @media (pointer: fine):

@media (pointer: fine) {
  a span {
    display: none;
  }
  a:hover span {
    display: inline-block;
  }
}

O CSS envolvido nesta consulta de mídia será aplicado apenas na área de trabalho.

A explicação desta solução está aqui https://css-tricks.com/annoying-mobile-double-tap-link-issue/

Galina
fonte
-1

Você pode verificar navigator.userAgentassim:

if(!navigator.userAgent.match(/iPhone/i) || !navigator.userAgent.match(/iPad/i)) {
    //bind your mouseovers...
}

mas você precisaria procurar amoras, dróides e outros dispositivos touchscreen. Você também pode vincular os mouseovers apenas se o userAgent contiver Mozilla, IE, Webkit ou Opera, mas ainda precisar rastrear alguns dispositivos, porque o Droid, por exemplo, relata sua string userAgent como:

Mozilla/5.0 (Linux; U; Android 2.0.1; en-us; Droid Build/ESD56) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17

A string do iPhone é semelhante. Se você apenas tela para iPhone, iPod, iPad, Android e Blackberry, pode obter a maioria dos computadores de mão, mas não todos.

jasongetsdown
fonte
Eu acho que, por enquanto, para não ficar louco, a melhor coisa a fazer poderia ser apenas um script que pule os eventos pairados ... então eu acho que a primeira resposta foi boa ... e sim, você está certo ... eu deveria pense em todos os outros dispositivos ... eu gostaria que o Jquery ou algum plugin tivesse esse tipo de recurso de detecção ..!
Francesco
wurfl.sourceforge.net Esta pode ser sua resposta. É um banco de dados de dispositivos sem fio. Não será tão simples quanto um plugin jQuery, mas você sempre pode escrever um! Há também o tera-wurfl.com, que usa um banco de dados em vez de um arquivo xml. Não foi feito muito trabalho de escavação, mas pode haver uma versão hospedada por aí, para que você não precise se preocupar em manter seu arquivo wurfl ou o banco de dados tera-wurfl atualizados.
jasongetsdown
1
Estou faltando alguma coisa ou a pergunta NÃO foi sobre a detecção de iPads, mas sobre como solucionar um comportamento específico nos iPads?
Andrew Hedges
5
UA cheirando? Como os anos 90: P
Macha
-1

Basta fazer uma consulta de mídia CSS que exclua tablets e dispositivos móveis e colocar o cursor sobre ele. Você realmente não precisa de jQuery ou JavaScript para isso.

@media screen and (min-device-width:1024px) {
    your-element:hover {
        /* Do whatever here */
    }
}

E não se esqueça de adicionar isso ao seu cabeçalho html para garantir que ele calcule com os pixels reais e não com a resolução.

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
Dalibor
fonte