132 Stimmen

iPad/iPhone-Hover-Problem führt dazu, dass der Benutzer doppelt auf einen Link klickt

Ich habe einige Websites, die ich vor einiger Zeit gebaut habe, die Jquery-Mausereignisse verwenden... Ich habe gerade ein iPad bekommen und bemerkt, dass alle Mouse-Over-Ereignisse in Klicks übersetzt werden... so muss ich zum Beispiel zwei Klicks statt einem machen (der erste Hover, dann der eigentliche Klick)

Gibt es einen Workaround, um dieses Problem zu lösen? vielleicht ein Jquery-Befehl, den ich anstelle von mouseover/out etc. verwendet haben sollte. Danke!

207voto

cduruk Punkte 2515

Ich habe dies nicht vollständig getestet, aber da iOS Touch-Ereignisse auslöst, könnte dies funktionieren, vorausgesetzt, Sie sind in einer jQuery-Einstellung.

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

Die Idee ist, dass Mobile WebKit eine touchend Ereignis am Ende eines Taps, also hören wir darauf und leiten den Browser um, sobald ein touchend Ereignis auf einen Link ausgelöst wurde.

39voto

MacFreek Punkte 2957

Es ist nicht ganz klar, was Ihre Frage ist, aber wenn Sie nur den Doppelklick beseitigen wollen, während der Hover-Effekt für die Maus beibehalten wird, ist mein Rat zu:

  • Hover-Effekte hinzufügen auf touchstart y mouseenter .
  • Hover-Effekte entfernen bei mouseleave , touchmove y click .

Hintergrund

Um eine Maus zu simulieren, lösen Browser wie Webkit mobile die folgenden Ereignisse aus, wenn ein Benutzer einen Finger auf einem Touchscreen (wie dem iPad) berührt und loslässt (Quelle: Berührung und Maus auf html5rocks.com):

  1. touchstart
  2. touchmove
  3. touchend
  4. 300 ms Verzögerung, wobei der Browser sicherstellt, dass es sich um einen einzelnen Tap und nicht um einen Doppeltap handelt
  5. mouseover
  6. mouseenter
    • Hinweis : Wenn ein mouseover , mouseenter o mousemove Ereignis den Seiteninhalt ändert, werden die folgenden Ereignisse nie ausgelöst.
  7. mousemove
  8. mousedown
  9. mouseup
  10. click

Es scheint nicht möglich zu sein, dem Webbrowser einfach zu sagen, dass er die Mausereignisse überspringen soll.

Was noch schlimmer ist: Wenn ein Mouseover-Ereignis den Seiteninhalt ändert, wird das Click-Ereignis nie ausgelöst, wie auf Safari Web Content Guide - Handhabung von Ereignissen insbesondere die Abbildung 6.4 in Ein-Finger-Ereignisse . Was genau eine "Inhaltsänderung" ist, hängt vom Browser und der Version ab. Ich habe festgestellt, dass unter iOS 7.0 eine Änderung der Hintergrundfarbe keine Inhaltsänderung ist (oder nicht mehr?).

Die Lösung wird erklärt

Um es kurz zu machen:

  • Hover-Effekte hinzufügen auf touchstart y mouseenter .
  • Hover-Effekte entfernen bei mouseleave , touchmove y click .

Beachten Sie, dass es keine Aktion auf touchend !

Dies funktioniert eindeutig für Mausereignisse: mouseenter y mouseleave (leicht verbesserte Versionen von mouseover y mouseout ) ausgelöst werden, und den Schwebezustand hinzufügen und entfernen.

Wenn der Benutzer tatsächlich click s einen Link, wird auch der Hover-Effekt entfernt. Dadurch wird sichergestellt, dass er entfernt wird, wenn der Benutzer im Webbrowser auf die Schaltfläche "Zurück" drückt.

Dies funktioniert auch bei Berührungsereignissen: bei touchstart wird der Schwebeeffekt hinzugefügt. Er wird '''nicht''' entfernt bei touchend . Es wird wieder hinzugefügt am mouseenter und da dies keine inhaltlichen Änderungen bewirkt (es wurde bereits hinzugefügt), wird die click wird ebenfalls ausgelöst, und der Link wird weiterverfolgt, ohne dass der Benutzer erneut klicken muss!

Die 300 ms Verzögerung, die ein Browser zwischen einer touchstart Veranstaltung und click wird tatsächlich sinnvoll genutzt, denn während dieser kurzen Zeit wird der Hover-Effekt angezeigt.

Wenn der Benutzer beschließt, den Klick abzubrechen, geschieht dies ganz normal durch eine Bewegung des Fingers. Normalerweise ist dies ein Problem, da keine mouseleave ausgelöst, und der Schwebeeffekt bleibt bestehen. Zum Glück kann dies leicht behoben werden, indem der Hover-Effekt auf touchmove .

Das war's!

Beachten Sie, dass es möglich ist, die 300 ms Verzögerung zu entfernen, zum Beispiel mit der Option FastClick-Bibliothek aber das würde den Rahmen dieser Frage sprengen.

Alternative Lösungen

Ich habe die folgenden Probleme mit den folgenden Alternativen gefunden:

  • Browser-Erkennung: Äußerst fehleranfällig. Geht davon aus, dass ein Gerät entweder über eine Maus oder einen Touchscreen verfügt, während eine Kombination aus beidem mit der zunehmenden Verbreitung von Touchscreens immer üblicher werden wird.
  • CSS-Medienerkennung: Die einzige reine CSS-Lösung, die mir bekannt ist. Immer noch anfällig für Fehler, und immer noch davon ausgegangen, dass ein Gerät entweder Maus oder Touch hat, während beide möglich sind.
  • Emulieren Sie das Klick-Ereignis in touchend : Dies führt dazu, dass der Link fälschlicherweise verfolgt wird, auch wenn der Benutzer nur scrollen oder zoomen wollte, ohne die Absicht, den Link tatsächlich anzuklicken.
  • Verwenden Sie eine Variable, um Mausereignisse zu unterdrücken: Dies setzt eine Variable in touchend die als if-Bedingung in nachfolgenden Mausereignissen verwendet wird, um Zustandsänderungen zu diesem Zeitpunkt zu verhindern. Die Variable wird im Klick-Ereignis zurückgesetzt. Dies ist eine gute Lösung, wenn Sie wirklich keinen Hover-Effekt auf Touch-Oberflächen wünschen. Leider funktioniert dies nicht, wenn ein touchend aus einem anderen Grund ausgelöst wird und kein Klick-Ereignis ausgelöst wird (z. B. weil der Benutzer gescrollt oder gezoomt hat) und anschließend versucht, dem Link mit der Maus zu folgen (d. h. auf einem Gerät mit Maus- und Touch-Oberfläche).

Weitere Lektüre

Siehe auch iPad/iPhone Doppelklick-Problem y Hover-Effekte auf mobilen Browsern deaktivieren .

20voto

Pavel Bogatinov Punkte 201

Es scheint, als gäbe es doch eine CSS-Lösung. Der Grund, warum Safari auf eine zweite Berührung wartet, ist das Hintergrundbild (oder -elemente), das Sie normalerweise beim :hover-Ereignis zuweisen. Wenn keins angezeigt wird, haben Sie keine Probleme. Die Lösung besteht darin, die iOS-Plattform mit einer sekundären CSS-Datei (oder einem Stil im Falle eines JS-Ansatzes) anzusteuern, die den :hover-Hintergrund überschreibt, um z. B. die Elemente, die beim Überfahren mit der Maus angezeigt werden sollen, zu übernehmen und auszublenden:

Hier ist ein Beispiel für CSS und HTML - ein Produktblock mit einem Sternchen-Label bei Mouseover:

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

Lösung (sekundäres CSS):

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

6voto

Jsonras Punkte 952

Es gibt keinen Grund, das Ganze zu kompliziert zu machen.

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

5voto

Adauto Punkte 569

Bei mir hat das funktioniert, was andere hier schon gesagt haben:

Elemente bei Hover oder Mousemove nicht anzeigen/ausblenden (was in meinem Fall das Ereignis ist).

Hier ist, was Apple sagt ( https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html ):

Ein klickbares Element ist ein Link, ein Formularelement, ein Image-Map-Bereich oder ein anderes Element mit Mousemove-, Mousedown-, Mouseup- oder Onclick-Handlern

Wenn der Benutzer auf ein klickbares Element tippt, treten Ereignisse in dieser Reihenfolge auf: mouseover, mousemove, mousedown, mouseup und click. Auch, Wenn sich der Inhalt der Seite beim Mausbewegungsereignis ändert, werden keine weiteren Ereignisse in der Sequenz gesendet. Dieses Verhalten ermöglicht es dem Benutzer, den neuen Inhalt einzutippen.

Sie könnten also die Lösung von @woop verwenden: den userAgent erkennen, prüfen, ob es sich um ein iOS-Gerät handelt, und dann das Ereignis binden. Ich endete mit dieser Technik, weil es meinen Bedürfnissen entspricht und es macht mehr Sinn nicht binden Hover-Ereignisse, wenn Sie es nicht wollen.

Aber ... wenn Sie nicht wollen, Chaos mit userAgents und immer noch verstecken/anzeigen Elemente auf Hover/Mousemove, fand ich heraus, dass Sie so tun können, indem Sie native Javascript, wie diese:

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

Dies funktioniert in der Desktop-Version und nicht in der mobilen Version.

Und für ein wenig mehr Kompatibilität...

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X