Problem z najechaniem kursorem na iPada / iPhone'a powoduje dwukrotne kliknięcie łącza


125

Mam kilka stron internetowych, które zbudowałem kilka razy temu, które używają zdarzeń myszy jQuery ... Właśnie dostałem iPada i zauważyłem, że wszystkie zdarzenia myszy nad kursorem są tłumaczone na kliknięcia ... więc na przykład muszę zrobić dwa kliknięcia zamiast jednego .. (pierwsze najechanie kursorem, a nie faktyczne kliknięcie)

czy istnieje rozwiązanie gotowe do rozwiązania tego problemu? może komenda jquery, której powinienem użyć zamiast przesuwania kursora / wyjścia itp .. dzięki!


1
jakie są twoje wydarzenia? np. zdarzenia onclick powinny działać dobrze ... onmouseover, onmouseout i CSS: hover to te, które są nieco trudne w obsłudze, ponieważ nie ma opcji „hover” dostępnej dla ekranu dotykowego. Czy masz próbkę kodu?
scunliffe

Jedną rzeczą, którą proponuję, jest ponowne przemyślenie interfejsu, jeśli to w ogóle możliwe. interakcja na iPadzie / iPhonie nie odzwierciedla dokładnie interakcji na komputerze PC i prawdopodobnie mądrze jest sprawić, aby Twoja witryna wyglądała tak, jakby była napisana dla iPada / iPhone'a / innych urządzeń dotykowych z podobnymi mechanizmami multitouch. Tylko myśl.
jer

Zgadzam się z „jer”. To dziwne pytanie, nie sądzę, aby rozwiązaniem było „obejście” osobiście. Myślę, że tłumaczenie „najechania myszą” w przeglądarce na komputerze stacjonarnym na „dotknięcie palcem” w przeglądarce na ekranie dotykowym ma sens. Jeśli zgadzasz się z tym tłumaczeniem, ale chcesz jedno dotknięcie zamiast dwóch, prawdopodobnie wykrywam funkcje dla zdarzeń iPada (np. „Touchstart”) i zmieniam obsługę zdarzeń. Może wyodrębnij swój kod do wtyczki jquery typu „dotknij lub kliknij”, która uruchamia się różnie w zależności od funkcji, ale wydaje mi się specyficzna dla Twojej witryny / aplikacji.
Andy Atkinson

1
Właściwie uważam to tłumaczenie za funkcję. Jeśli masz ustawione zdarzenia najechania kursorem, musiało być jakieś narzędzie do ich zobaczenia. Pojedyncze dotknięcie pokazuje element najechany kursorem, drugie kliknięcie następuje po linku „za” najechaniem kursorem.
Aaron

Odpowiedzi:


205

Nie testowałem tego w pełni, ale ponieważ iOS uruchamia zdarzenia dotykowe, może to zadziałać, zakładając, że jesteś w ustawieniu jQuery.

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

Chodzi o to, że Mobile WebKit uruchamia touchendzdarzenie na końcu dotknięcia, więc nasłuchujemy tego, a następnie przekierowujemy przeglądarkę, gdy tylko touchendzdarzenie zostanie uruchomione na łączu.


17
Gdzie moja nagroda? : P
cduruk

2
Cierpliwości, Padwanie. WIĘC powiedział, że zastosowanie ma 24 godziny.
Andrew Hedges

2
Od wersji jQuery 1.7 .onpreferowane jest .live. Po przeczytaniu tej odpowiedzi stwierdziłem, że zmiana kodu na $('a').on('click touchend', function(e) {...})działa znakomicie.
Blazemonger

23
Cóż, to rozwiązuje początkowy problem, ale tworzy nowy: po przesunięciu palcem po kliknięciu. To nie jest rozwiązanie.
luksak

9
To ma swoje wady. Jeśli klikniesz link z target="_blank"nim, otworzy się w tym samym oknie ORAZ w nowym oknie.
rybo111

37

Nie jest do końca jasne, o co chodzi, ale jeśli chcesz po prostu wyeliminować podwójne kliknięcie, zachowując efekt najechania myszą, radzę:

  • Dodaj efekty najechania na touchstarti mouseenter.
  • Usuń unosić skutki mouseleave, touchmovei click.

tło

Aby zasymulować mysz, przeglądarki, takie jak Webkit mobile, uruchamiają następujące zdarzenia, jeśli użytkownik dotknie i puści palec na ekranie dotykowym (takim jak iPad) (źródło: Touch And Mouse na html5rocks.com):

  1. touchstart
  2. touchmove
  3. touchend
  4. 300 ms opóźnienia, gdy przeglądarka upewnia się, że jest to jedno dotknięcie, a nie podwójne dotknięcie
  5. mouseover
  6. mouseenter
    • Uwaga : W przypadku mouseover, mouseenterczy mousemovezdarzenie zmienia zawartość strony, następujące zdarzenia nie są wypalane.
  7. mousemove
  8. mousedown
  9. mouseup
  10. click

Wydaje się, że nie jest możliwe po prostu nakazanie przeglądarce pominięcia zdarzeń myszy.

Co gorsza, jeśli zdarzenie najechania kursorem myszy zmieni zawartość strony, zdarzenie kliknięcia nigdy nie zostanie uruchomione, jak wyjaśniono w Przewodniku po treściach internetowych Safari - Obsługa zdarzeń , w szczególności na rysunku 6.4 w Zdarzeniach jednym palcem . Czym dokładnie jest „zmiana treści”, zależy od przeglądarki i wersji. Odkryłem, że w iOS 7.0 zmiana koloru tła nie jest (lub już nie?) Zmianą treści.

Wyjaśnienie rozwiązania

Przypomnę:

  • Dodaj efekty najechania na touchstarti mouseenter.
  • Usuń unosić skutki mouseleave, touchmovei click.

Zauważ, że nie ma żadnej akcji touchend !

To wyraźnie działa w przypadku zdarzeń myszy: mouseenteri mouseleave(nieco ulepszone wersje mouseoverimouseout ) są uruchamiane i dodają i usuwają dymek.

Jeśli użytkownik faktycznie click linkiem, efekt najechania kursorem jest również usuwany. Zapewnia to, że zostanie usunięty, jeśli użytkownik naciśnie przycisk Wstecz w przeglądarce internetowej.

Działa to również w przypadku zdarzeń dotykowych: touchstartdodawany jest efekt najechania kursorem. To jest '' 'nie' '' usunięte touchend. Jest on ponownie dodawany mouseenter, a ponieważ nie powoduje to żadnych zmian treści (zostało już dodane), clickzdarzenie jest również uruchamiane, a odsyłacz jest śledzony bez konieczności ponownego klikania przez użytkownika!

300 ms opóźnienia, które przeglądarka ma między touchstartzdarzeniem i clickjest faktycznie dobrze wykorzystywane, ponieważ efekt najechania kursorem będzie wyświetlany w tym krótkim czasie.

Jeśli użytkownik zdecyduje się anulować kliknięcie, ruch palcem zrobi to normalnie. Zwykle jest to problem, ponieważ niemouseleave zdarzenie jest uruchamiane, a efekt zawisu pozostaje na miejscu. Na szczęście można to łatwo naprawić, usuwając efekt najechania na touchmove.

Otóż ​​to!

Zwróć uwagę, że można usunąć opóźnienie 300 ms, na przykład za pomocą biblioteki FastClick , ale jest to poza zakresem tego pytania.

Alternatywne rozwiązania

Znalazłem następujące problemy z następującymi alternatywami:

  • wykrywanie przeglądarki: wyjątkowo podatne na błędy. Zakłada się, że urządzenie ma mysz lub dotyk, podczas gdy kombinacja obu będzie coraz bardziej powszechna, gdy wyświetlacze dotykowe będą się rozprzestrzeniać.
  • Wykrywanie mediów CSS: jedyne znane mi tylko rozwiązanie CSS. Wciąż podatny na błędy i nadal zakłada, że ​​urządzenie ma mysz lub dotyk, podczas gdy oba są możliwe.
  • Emuluj zdarzenie kliknięcia w touchend: Spowoduje to niepoprawne podążanie za linkiem, nawet jeśli użytkownik chciał tylko przewinąć lub powiększyć, bez zamiaru kliknięcia łącza.
  • Użyj zmiennej, aby powstrzymać zdarzenia myszy: To ustawia zmienną w, touchendktóra jest używana jako warunek jeśli w kolejnych zdarzeniach myszy, aby zapobiec zmianom stanu w tym momencie. Zmienna jest resetowana w przypadku kliknięcia. To przyzwoite rozwiązanie, jeśli naprawdę nie chcesz efektu najechania na interfejsy dotykowe. Niestety, to nie działa, jeśli a touchendjest uruchamiane z innego powodu i nie jest wywoływane żadne zdarzenie kliknięcia (np. Użytkownik przewinął lub powiększył), a następnie próbuje podążać za linkiem za pomocą myszy (tj. Na urządzeniu z myszą i interfejsem dotykowym ).

Dalsze czytanie

Zobacz także Problem podwójnego kliknięcia iPada / iPhone'a i Wyłącz efekty najechania kursorem w przeglądarkach mobilnych .


2
wydaje się najlepszym wytłumaczeniem dla tych, którzy chcą czegoś więcej niż dokładnego rozwiązania problemu. Dzięki
antyplayer Kwietnia

Specjalne podziękowania za informację o kolorze tła dla> iOS7. Spędziłem trochę czasu, próbując dowiedzieć się, kiedy to zaczęło działać.
staffang

20

Wygląda na to, że istnieje rozwiązanie CSS. Powodem, dla którego Safari czeka na drugie dotknięcie, jest obraz tła (lub elementy), które zwykle przypisujesz do zdarzenia: hover. Jeśli nie ma żadnego do pokazania - nie będziesz mieć żadnych problemów. Rozwiązaniem jest docelowa platforma iOS z dodatkowym plikiem CSS (lub stylem w przypadku podejścia JS), który zastępuje: najedź na tło, aby dziedziczyć i ukryć elementy, które chcesz wyświetlić po najechaniu myszą:

Oto przykład CSS i HTML - blok produktu z oznaczoną gwiazdką etykietą po najechaniu myszą:

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;
}

Rozwiązanie (dodatkowy CSS):

/* CSS */
/* Keep hovers the same or hidden */
.s:hover {
   background:inherit;
}
.s:hover .s-star {
   display:none;
}


Ta odpowiedź jest ukierunkowana na obrazy tła, ale czy masz rozwiązanie dla prostych zmian krycia? To rozwiązanie nie działa w tym przypadku.
Ian S

5

Nie ma potrzeby zbytniego komplikowania.

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

5

To, co zadziałało, to to, co inni tutaj już powiedzieli:

Nie pokazuj / nie ukrywaj elementów po najechaniu myszą lub najechaniu myszą (tak jest w moim przypadku).

Oto, co mówi Apple ( https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html ):

Element, który można kliknąć, to łącze, element formularza, obszar mapy obrazu lub jakikolwiek inny element z funkcjami obsługi ruchu myszy, przesuwania kursora, myszy lub przycisku onclick

Jeśli użytkownik dotknie elementu, który można kliknąć, zdarzenia pojawiają się w następującej kolejności: najechanie myszą, przesunięcie myszy, przesunięcie myszy, przesunięcie myszy i kliknięcie. Ponadto, jeśli zawartość strony zmieni się w zdarzeniu mousemove, żadne kolejne zdarzenia w sekwencji nie są wysyłane. To zachowanie pozwala użytkownikowi wykorzystać nową zawartość.

Możesz więc użyć rozwiązania @ woop: wykryć userAgent, sprawdź, czy jest to i urządzenie iOS, a następnie powiązaj zdarzenie. Skończyło się na tym, że użyłem tej techniki, ponieważ odpowiada ona moim potrzebom i ma większy sens, aby nie wiązać zdarzeń najechania kursorem, gdy tego nie chcesz.

Ale ... jeśli nie chcesz zadzierać z userAgents i nadal ukrywać / pokazywać elementy na hover / mousemove, dowiedziałem się, że możesz to zrobić, używając natywnego javascript, na przykład:

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

To zadziała w wersji na komputery stacjonarne i nic nie da w wersji mobilnej.

A dla trochę większej kompatybilności ...

$("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();
    }
});

1
Ten bit „jeśli zawartość strony zmieni się w zdarzeniu mousemove, żadne kolejne zdarzenia w sekwencji nie są wysyłane” naprawdę mi się to udało. Miałem stronę, na której linki nagłówka wymagałyby podwójnego dotknięcia, a przyciski w treści (bez wszystkich szczęśliwych przejść css3 na em) wymagałyby tylko jednego dotknięcia. Okazało się, że linki nagłówkowe miały pseudoelement, który po najechaniu kursorem zmienił się z krycia: 0 do krycia: 1. Usunięcie tego efektu natychmiast rozwiązało problem i znalazłem obejście CSS, aby nadal uzyskać pożądany wygląd.
Fałszywy Haak

3

Rozwiązanie cduruk było dość skuteczne, ale spowodowało problemy w kilku częściach mojej witryny. Ponieważ używałem już jQuery do dodawania klasy CSS hover, najłatwiejszym rozwiązaniem było po prostu nie dodawanie klasy CSS na urządzeniach mobilnych (a dokładniej, aby dodać ją TYLKO, gdy NIE na urządzeniu mobilnym).

Oto ogólny pomysł:

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");
        }
    );
}

* kod zredukowany w celach ilustracyjnych


1
To jest oczywiście odpowiedź. Inne „rozwiązania” nie rozwiązują problemu. Safari na iOS jest ewidentnie błędne, myśląc, że chcemy najpierw najechać kursorem. Inne systemy operacyjne mają rzeczywiste funkcje po najechaniu kursorem na element.
Joshua Pack

To była jedyna rzecz, która działała dla mnie. Dziękuję bardzo!
tx291

2

Myślę, że mądrze byłoby spróbować mouseenterzamiast tego mouseover. To jest to, co jest używane wewnętrznie podczas wiązania .hover(fn,fn)i jest ogólnie tym, czego chcesz.


1

Miałem następujące problemy z istniejącymi rozwiązaniami i znalazłem coś, co wydaje się rozwiązać je wszystkie. Zakłada się, że celujesz w coś w przeglądarce, na różnych urządzeniach i nie chcesz wąchać urządzenia.

Problemy, które to rozwiązuje

Używając tylko touchstartlub touchend:

  • Powoduje, że zdarzenie uruchamia się, gdy ludzie próbują przewinąć zawartość i po prostu zdarzyło im się przesunąć palcem po tym elemencie, gdy zaczęli przesuwać - uruchamiając akcję nieoczekiwanie.
  • Może spowodować uruchomienie zdarzenia po długim naciśnięciu , podobnie do kliknięcia prawym przyciskiem myszy na pulpicie. Na przykład, jeśli zdarzenie kliknięcia prowadzi do adresu URL X, a użytkownik długo naciska, aby otworzyć X w nowej karcie, będzie zdezorientowany, gdy zobaczy X otwarty w obu kartach. W niektórych przeglądarkach (np. IPhone) może to nawet uniemożliwić wyświetlanie menu długiego naciśnięcia.

Wyzwalanie mouseoverzdarzeń na touchstarti mouseoutna touchmovemniej poważne konsekwencje, ale nie kolidować z zachowaniem zwykłej przeglądarki, na przykład:

  • Długie naciśnięcie wyzwoliłoby najechanie myszą, które nigdy się nie kończy.
  • Wiele przeglądarek na Androidzie traktuje położenie palca touchstartjak znak a mouseover, który jest mouseoutwyświetlany w następnym touchstart. Dlatego jednym ze sposobów wyświetlenia zawartości po najechaniu myszą w systemie Android jest dotknięcie obszaru zainteresowania i poruszenie palcem, lekko przewijając stronę. Traktowanie touchmovejako mouseoutzepsuje to.

Rozwiązanie

Teoretycznie możesz po prostu dodać flagę touchmove, ale iPhone'y wyzwalają ruch dotykowy, nawet jeśli nie ma ruchu. W teorii można po prostu porównywać touchstarti touchendzdarzenia pageXi pageY ale na iPhone, nie ma touchend pageXlubpageY .

Więc niestety, aby objąć wszystkie podstawy, kończy się to trochę bardziej skomplikowane.

$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);

Teoretycznie istnieją sposoby na uzyskanie dokładnego czasu używanego do długiego naciśnięcia, zamiast używać tylko 1000 jako przybliżenia, ale w praktyce nie jest to takie proste i najlepiej jest użyć rozsądnego proxy .


1

Odpowiedź MacFreaka była dla mnie niezwykle pomocna. Oto kilka praktycznych kodów na wypadek, gdyby ci to pomogło.

PROBLEM - zastosowanie touchchend oznacza, że ​​za każdym razem, gdy przesuwasz palcem po elemencie, reaguje on tak, jakbyś go nacisnął, nawet jeśli próbujesz tylko przewinąć.

Tworzę efekt za pomocą jQuery, który zanika linię pod niektórymi przyciskami, aby „podświetlić” przycisk najechany kursorem. Nie chcę, aby to oznaczało, że musisz dwukrotnie nacisnąć przycisk na urządzeniach dotykowych, aby kliknąć łącze.

Oto przyciski:

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

Chcę, aby element div "menu_underline" zanikał po najechaniu kursorem myszy i znikał po wygaśnięciu wskaźnika myszy. ALE chcę, aby urządzenia dotykowe mogły podążać za linkiem jednym kliknięciem, a nie dwoma.

ROZWIĄZANIE - Oto jQuery, aby to działało:

//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();
});

Wielkie dzięki za pomoc w tym MacFreak.


1

Właśnie się dowiedziałem, że działa, jeśli dodasz pusty odbiornik, nie pytaj mnie dlaczego, ale przetestowałem to na iPhonie i iPadzie z iOS 9.3.2 i działało dobrze.

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(){});
    }
}


0

Miałem ten sam problem, ale nie na urządzeniu dotykowym. Zdarzenie jest wyzwalane za każdym razem, gdy klikniesz. Jest coś takiego w kolejce zdarzeń.

Jednak moje rozwiązanie było takie: w przypadku kliknięcia (lub dotknięcia?) Ustawiałeś licznik czasu. Jeśli link zostanie kliknięty ponownie w ciągu X ms, po prostu zwrócisz false.

Aby ustawić licznik czasu na element, możesz użyć $.data().

Może to również rozwiązać opisany powyżej problem @Ferdy.


Czy możesz opublikować, jak wygląda ten kod? Mam problem z dwukrotnym wyzwalaniem zdarzenia kliknięcia.
fantazyjny

0

Jeśli używasz Modernizr, korzystanie z Modernizr.touch jest bardzo łatwe, jak wspomniano wcześniej.

Jednak wolę używać kombinacji Modernizr.touch i testowania agenta użytkownika, aby być bezpiecznym.

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();
};

Jeśli nie używasz Modernizr, możesz po prostu zamienić Modernizr.touchpowyższą funkcję na('ontouchstart' in document.documentElement)

Pamiętaj również, że testowanie klienta użytkownika iemobile zapewni szerszy zakres wykrytych urządzeń mobilnych Microsoft niż Windows Phone.


0

Możesz użyć click touchend,

przykład:

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

Powyższy przykład wpłynie na wszystkie linki na urządzeniach dotykowych.

Jeśli chcesz kierować reklamy tylko na określone linki, możesz to zrobić, ustawiając dla nich klasę, tj .:

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;
});

Twoje zdrowie,

Jeroen


0

Wpadłem na podobną sytuację, w której miałem zdarzenia powiązane ze stanami mouseenter / mouseleave / click elementu, ale na iPhonie użytkownik musiał dwukrotnie kliknąć element, aby najpierw wywołać zdarzenie mouseenter, a następnie ponownie, aby uruchomić zdarzenie kliknięcia .

Rozwiązałem to przy użyciu podobnej metody jak powyżej, ale użyłem wtyczki jQuery $ .browser (dla jQuery 1.9>) i dodałem zdarzenie .trigger do zdarzenia wiązania myszy w następujący sposób:

// 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
});

.Trigger zapobiega konieczności dwukrotnego kliknięcia elementu, uruchamiając procedurę obsługi zdarzenia .click po naciśnięciu przycisku myszy (lub pierwszym kliknięciu) elementu podczas przeglądania na iPhone'ach lub iPadach. Może nie jest to najbardziej eleganckie rozwiązanie, ale działa świetnie w moim przypadku i wykorzystuje wtyczkę, którą już miałem na miejscu i wymagała ode mnie dodania jednej linii kodu, aby moje istniejące zdarzenia działały na tych urządzeniach.

Możesz pobrać wtyczkę jQuery $ .browser tutaj: https://github.com/gabceb/jquery-browser-plugin


0

To tylko ulepszenie, aby uniknąć przekierowania, gdy przez pomyłkę przesuwasz palcem po linku.

// 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 );
});

0

Inspirując się MacFreak, stworzyłem coś, co działa na mnie.

Ta metoda js zapobiega przyklejaniu się wskaźnika do iPada, aw niektórych przypadkach zapobiega rejestrowaniu kliknięcia jako dwóch kliknięć. W CSS, jeśli masz jakieś: hover klasy psudo w swoim css, zmień je na .hover Na przykład .some-class: hover na .some-class.hover

Przetestuj ten kod na iPadzie, aby zobaczyć, jak różnie zachowują się metody css i js hover (tylko w przypadku efektu hover). Przycisk CSS nie ma fantazyjnego powiadomienia o kliknięciu. 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


0

Aby linki działały bez przerywania przewijania dotykowego, rozwiązałem ten problem za pomocą zdarzenia „tap” w jQuery Mobile:

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

0

Wiem, że jestem za późno, ale jest to jedno z najłatwiejszych obejść, jakie znalazłem:

    $('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);
        }
    });

Działa to nie tylko w przypadku linków (znaczników kotwicy), ale także innych elementów. Mam nadzieję że to pomoże.


0

Ten krótki fragment wydaje się działać. Wywołaj zdarzenie kliknięcia po dotknięciu linku:

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

0

Żadna z odpowiedzi drugiej nie działa dla mnie. Moja aplikacja ma wiele odbiorników zdarzeń, własne pola wyboru i linki, które mają słuchaczy i linki bez słuchaczy.

Używam tego:

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;
});

0

Działa to dla mnie, gdy masz menu rozwijane jQuery ui

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

0

Unikaj zmiany stylu „display” wewnątrz zdarzenia hover css. Miałem "display: block" w stanie najechania. Po usunięciu ios poszło na liny jednym dotknięciem. Swoją drogą wygląda na to, że najnowsze aktualizacje IOS naprawiły tę „funkcję”


0

Najprostszym sposobem rozwiązania problemu dwukrotnego kliknięcia na iPadzie jest zawijanie CSS w celu uzyskania efektu najechania kursorem w zapytaniu o media @media (pointer: fine):

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

CSS zawarty w tym zapytaniu o media będzie obowiązywał tylko na komputerach stacjonarnych.

Wyjaśnienie tego rozwiązania znajduje się tutaj https://css-tricks.com/annoying-mobile-double-tap-link-issue/


-1

Możesz sprawdzić navigator.userAgenttak:

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

ale musiałbyś sprawdzić jeżyny, droidy, puste inne urządzenia z ekranem dotykowym. Możesz również powiązać ruchy myszy tylko wtedy, gdy userAgent zawiera Mozilla, IE, Webkit lub Opera, ale nadal musisz sprawdzać niektóre urządzenia, ponieważ na przykład Droid zgłasza swój ciąg userAgent jako:

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

Sznurek iPhone'a jest podobny. Jeśli korzystasz tylko z iPhone'a, iPoda, iPada, Androida i Blackberry, możesz dostać większość urządzeń przenośnych, ale nie wszystkie.


Myślę, że na razie, aby nie zwariować, najlepszą rzeczą do zrobienia może być po prostu skrypt, który pomija zdarzenia najechania kursorem… więc myślę, że pierwsza odpowiedź była dobra… i tak, masz rację… powinienem pomyśl o wszystkich innych urządzeniach ... chciałbym, żeby Jquery lub jakaś wtyczka miały tego rodzaju funkcję wykrywania ...!
Francesco

wurfl.sourceforge.net To może być Twoja odpowiedź. Jest to baza danych urządzeń bezprzewodowych. Nie będzie tak proste, jak wtyczka jQuery, ale zawsze możesz ją napisać! Istnieje również witryna tera-wurfl.com, która korzysta z bazy danych zamiast pliku xml. Nie robiłem zbyt wiele, ale może istnieć wersja hostowana, więc nie musisz się martwić o aktualizowanie pliku wurfl lub bazy danych tera-wurfl.
jasongetsdown

1
Czy coś mi brakuje, czy też pytanie NIE dotyczy wykrywania iPadów, ale obejścia określonego zachowania na iPadach?
Andrew Hedges

5
UA wącha? How 90's: P
Macha

-1

Po prostu wykonaj zapytanie o media CSS, które wyklucza tablety i urządzenia mobilne, i umieść tam kursor. Naprawdę nie potrzebujesz do tego jQuery ani JavaScript.

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

I pamiętaj, aby dodać to do swojej głowy HTML, aby upewnić się, że oblicza się z rzeczywistymi pikselami, a nie rozdzielczością.

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.