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


125

Ich habe einige Websites, die ich vor einiger Zeit erstellt habe und die jquery mouse-Ereignisse verwenden ... Ich habe gerade ein iPad erhalten und festgestellt, dass alle Mouse-Over-Ereignisse in Klicks übersetzt werden ... also muss ich zum Beispiel zwei Klicks anstelle von einem machen .. (der erste Schwebeflug als der eigentliche Klick)

Gibt es eine Problemumgehung, um dieses Problem zu lösen? Vielleicht ein JQuery-Befehl, den ich anstelle von Mouseover / Out usw. verwendet habe. Danke!


1
Womit sind Ihre Veranstaltungen verbunden? zB Onclick-Ereignisse sollten gut funktionieren ... onmouseover, onmouseout und das CSS: Hover sind diejenigen, die etwas schwierig zu handhaben sind, da für einen Touchscreen kein "Hover" verfügbar ist. Haben Sie ein Codebeispiel?
Scunliffe

Eine Sache, die ich vorschlagen würde, ist, Ihre Benutzeroberfläche zu überdenken, wenn dies überhaupt möglich ist. Die Interaktion auf dem iPad / iPhone entspricht nicht genau der auf einem PC, und es ist wahrscheinlich eine kluge Sache, Ihrer Website das Gefühl zu geben, für das iPad / iPhone / andere Touch-Geräte mit ähnlichen Multitouch-Mechanismen geschrieben zu sein. Nur ein Gedanke.
jer

Ich stimme "jer" zu. Dies ist eine seltsame Frage, ich denke nicht, dass die Lösung hier eine "Problemumgehung" ist. Ich halte es für sinnvoll, einen "Maus-Hover" in einem Desktop-Browser in einen "Finger-Tipp" in einem Touchscreen-Browser zu übersetzen. Wenn Sie mit dieser Übersetzung einverstanden sind, aber ein Tippen anstelle von zwei wünschen, würde ich wahrscheinlich die Funktionserkennung für die iPad-Ereignisse (z. B. "Touchstart") durchführen und Ihre Ereignishandler ändern. Vielleicht extrahieren Sie Ihren Code in eine Art "Touch or Click" -Funktion des JQuery-Plugins, die je nach Funktionen unterschiedlich ausgelöst wird, mir aber für Ihre Website / App spezifisch erscheint.
Andy Atkinson

1
Ich betrachte diese Übersetzung tatsächlich als ein Merkmal. Wenn Sie Hover-Ereignisse eingerichtet haben, muss es ein Dienstprogramm gegeben haben, um sie anzuzeigen. Ein einzelnes Tippen zeigt ein schwebendes Element an, ein zweites Tippen folgt dem Link "hinter" dem Schwebeflug.
Aaron

Antworten:


205

Ich habe dies noch nicht vollständig getestet, aber da iOS Touch-Ereignisse auslöst, könnte dies funktionieren, vorausgesetzt, Sie befinden sich 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 touchendam Ende eines Tippvorgangs ein Ereignis auslöst, also warten wir darauf und leiten den Browser um, sobald ein touchendEreignis auf einen Link ausgelöst wurde.


17
Wo ist mein Kopfgeld? : P
cduruk

2
Geduld, Padwan. SO sagte, es dauert 24 Stunden, um wirksam zu werden.
Andrew Hedges

2
Ab jQuery 1.7 .onwird bevorzugt .live. Nachdem ich diese Antwort gelesen hatte, stellte ich fest, dass das Ändern meines Codes $('a').on('click touchend', function(e) {...})hervorragend funktioniert.
Blazemonger

23
Nun, dies löst das anfängliche Problem, erstellt aber ein neues: Beim Wischen über werden die angeklickt. Dies ist keine Lösung.
Luksak

9
Das hat seine Mängel. Wenn Sie auf einen Link klicken target="_blank", wird dieser im selben Fenster UND in einem neuen Fenster geöffnet.
Rybo111

37

Es ist nicht ganz klar, was Ihre Frage ist, aber wenn Sie nur den Doppelklick eliminieren möchten, während Sie den Hover-Effekt für die Maus beibehalten, ist mein Rat:

  • Fügen Sie Hover-Effekte auf touchstartund hinzu mouseenter.
  • Entfernen Sie Hover - Effekte auf mouseleave, touchmoveund click.

Hintergrund

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

  1. touchstart
  2. touchmove
  3. touchend
  4. 300 ms Verzögerung, wobei der Browser sicherstellt, dass es sich um ein einfaches Tippen handelt, nicht um ein doppeltes Tippen
  5. mouseover
  6. mouseenter
    • Hinweis : Wenn ein mouseover, mouseenteroder mousemoveEreignis den Seiteninhalt ändert, werden die folgenden Ereignisse nie gebrannt.
  7. mousemove
  8. mousedown
  9. mouseup
  10. click

Es scheint nicht möglich zu sein, den Webbrowser einfach anzuweisen, die Mausereignisse zu überspringen.

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

Lösung erklärt

Um es noch einmal zusammenzufassen:

  • Fügen Sie Hover-Effekte auf touchstartund hinzu mouseenter.
  • Entfernen Sie Hover - Effekte auf mouseleave, touchmoveund click.

Beachten Sie, dass keine Aktion aktiviert ist touchend!

Dies funktioniert eindeutig für Mausereignisse: mouseenterund mouseleave(leicht verbesserte Versionen von mouseoverund mouseout) werden ausgelöst und fügen den Hover hinzu und entfernen ihn.

Wenn der Benutzer tatsächlich einen clickLink hat, wird auch der Hover-Effekt entfernt. Dadurch wird sichergestellt, dass es entfernt wird, wenn der Benutzer die Zurück-Taste im Webbrowser drückt.

Dies funktioniert auch bei Berührungsereignissen: Beim touchstartHover wird der Effekt hinzugefügt. Es wird am nicht entfernt touchend. Es wird am erneut hinzugefügt mouseenter, und da dies keine Inhaltsänderungen verursacht (es wurde bereits hinzugefügt), wird das clickEreignis ebenfalls ausgelöst und der Link wird verfolgt, ohne dass der Benutzer erneut klicken muss!

Die Verzögerung von 300 ms, die ein Browser zwischen einem touchstartEreignis hat und clickdie tatsächlich gut genutzt wird, da der Hover-Effekt in dieser kurzen Zeit angezeigt wird.

Wenn der Benutzer beschließt, den Klick abzubrechen, erfolgt eine Bewegung des Fingers wie gewohnt. Normalerweise ist dies ein Problem, da kein mouseleaveEreignis ausgelöst wird und der Hover-Effekt bestehen bleibt. Zum Glück kann dies leicht behoben werden, indem der Hover-Effekt auf entfernt wird touchmove.

Das ist es!

Beachten Sie, dass es möglich ist, die Verzögerung von 300 ms zu entfernen, z. B. mithilfe der FastClick-Bibliothek . Dies ist jedoch für diese Frage nicht zulässig .

Alternativlösungen

Ich habe die folgenden Probleme mit den folgenden Alternativen gefunden:

  • Browsererkennung: Extrem fehleranfällig. Angenommen, ein Gerät verfügt entweder über eine Maus oder eine Berührung, während eine Kombination aus beiden immer häufiger wird, wenn sich die Anzeige von Berührungen vermehrt.
  • CSS-Medienerkennung: Die einzige CSS-Lösung, die mir bekannt ist. Immer noch fehleranfällig und geht immer noch davon aus, dass ein Gerät entweder Maus oder Touch hat, während beide möglich sind.
  • Emulieren Sie das Klickereignis in touchend: Dies folgt falsch dem Link, selbst wenn der Benutzer nur scrollen oder zoomen wollte, ohne die Absicht, tatsächlich auf den Link zu klicken.
  • Verwenden Sie eine Variable, um Mausereignisse zu unterdrücken: Hiermit wird eine Variable festgelegt touchend, die als if-Bedingung in nachfolgenden Mausereignissen verwendet wird, um Statusänderungen zu diesem Zeitpunkt zu verhindern. Die Variable wird im Klickereignis zurückgesetzt. Dies ist eine anständige Lösung, wenn Sie wirklich keinen Hover-Effekt auf Touch-Interfaces wünschen. Leider funktioniert dies nicht, wenn a aus einem touchendanderen Grund ausgelöst wird und kein Klickereignis ausgelöst wird (z. B. wenn der Benutzer gescrollt oder gezoomt hat) und anschließend versucht, dem Link mit einer Maus zu folgen (dh auf einem Gerät mit Maus- und Touch-Oberfläche) ).

Weiterführende Literatur

Siehe auch iPad / iPhone-Doppelklickproblem und Hover-Effekte in mobilen Browsern deaktivieren .


2
scheint die beste Erklärung für diejenigen zu sein, die mehr als eine genaue Problemlösung wollen. Danke
Antiplayer

Besonderer Dank für die Informationen zur Hintergrundfarbe für> iOS7. Ich habe einige Zeit damit verbracht herauszufinden, wann dies zu funktionieren begann.
Staffang

20

Es scheint doch eine CSS-Lösung zu geben. Der Grund, warum Safari auf eine zweite Berührung wartet, liegt in dem Hintergrundbild (oder den Elementen), die Sie normalerweise für das Ereignis: hover zuweisen. Wenn keine angezeigt werden soll, haben Sie keine Probleme. Die Lösung besteht darin, auf eine iOS-Plattform mit einer sekundären CSS-Datei (oder einem Stil im Falle eines JS-Ansatzes) abzuzielen, die Folgendes überschreibt: Bewegen Sie den Hintergrund, um beispielsweise zu erben, und verbergen Sie die Elemente, die Sie mit der Maus anzeigen möchten:

Hier ist ein Beispiel für CSS und HTML - ein Produktblock mit einem Sternchen mit der Maus über:

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


Diese Antwort ist auf Hintergrundbilder ausgerichtet. Haben Sie jedoch eine Lösung für einfache Änderungen der Deckkraft? Diese Lösung funktioniert hierfür nicht.
Ian S

5

Keine Notwendigkeit, überkompliziert zu machen.

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

5

Was für mich funktioniert hat, ist das, was andere hier bereits gesagt haben:

Elemente beim Hover oder Mousemove nicht ein- oder ausblenden (was in meinem Fall der Fall ist).

Folgendes sagt Apple ( https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html ):

Ein anklickbares Element ist ein Link, ein Formularelement, ein Imagemap-Bereich oder ein anderes Element mit Mausbewegungs-, Mausklick-, Mouseup- oder Onclick-Handlern

Wenn der Benutzer auf ein anklickbares Element tippt, werden Ereignisse in dieser Reihenfolge angezeigt: Mouseover, Mousemove, Mousedown, Mouseup und Click. Auch wenn die Inhalte der Seite Änderungen an dem mousemove- Ereignisse, keine nachfolgenden Ereignisse in der Reihenfolge gesendet werden . Durch dieses Verhalten kann der Benutzer auf den neuen Inhalt tippen.

Sie könnten also die Lösung von @ woop verwenden: Erkennen Sie den userAgent, überprüfen Sie, ob es sich um ein iOS-Gerät handelt, und binden Sie das Ereignis. Am Ende habe ich diese Technik verwendet, weil sie meinen Anforderungen entspricht und es sinnvoller ist, Schwebeereignisse nicht zu binden, wenn Sie sie nicht möchten.

Aber ... wenn Sie sich nicht mit userAgents anlegen und dennoch Elemente auf Hover / Mousemove ausblenden / anzeigen möchten, habe ich herausgefunden, dass Sie dies mit nativem Javascript wie folgt tun können:

$("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 in der mobilen Version nicht.

Und für ein bisschen 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();
    }
});

1
Dieses Bit "Wenn sich der Inhalt der Seite beim Mousemove-Ereignis ändert, werden keine nachfolgenden Ereignisse in der Sequenz gesendet" hat es wirklich für mich getan. Ich hatte eine Seite, auf der Header-Links ein doppeltes Tippen erfordern würden, während Schaltflächen im Inhalt (mit allen glücklichen CSS3-Übergängen auf em) nur ein einziges Tippen erfordern würden. Es schien, dass die Header-Links ein Pseudoelement hatten, das beim Hover von Deckkraft: 0 auf Deckkraft: 1 ging. Das Entfernen dieses Effekts löste das Problem sofort und ich fand eine CSS-Problemumgehung, um immer noch das gewünschte Aussehen zu erhalten.
Fake Haak

3

Die Lösung von cduruk war recht effektiv, verursachte jedoch Probleme auf einigen Teilen meiner Website. Da ich bereits jQuery zum Hinzufügen der CSS-Hover-Klasse verwendet habe, bestand die einfachste Lösung darin, die CSS-Hover-Klasse auf Mobilgeräten einfach nicht hinzuzufügen (oder genauer gesagt, NUR hinzuzufügen, wenn sie NICHT auf einem Mobilgerät vorhanden ist).

Hier war die allgemeine Idee:

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

* Code zur Veranschaulichung reduziert


1
Dies ist eindeutig die Antwort. Die anderen "Lösungen" beheben das Problem nicht. Die iOS-Safari ist eindeutig fehlerhaft in dem Gedanken, dass wir zuerst schweben wollen. Andere Betriebssysteme verfügen über tatsächliche Hover-Funktionen, wenn Sie mit der Maus über ein Element fahren.
Joshua Pack

Dies war das einzige, was für mich funktioniert hat. Ich danke dir sehr!
tx291

2

Ich denke, es wäre klug, es mouseenteranstelle von zu versuchen mouseover. Es ist das, was intern beim Binden verwendet wird .hover(fn,fn)und im Allgemeinen das, was Sie wollen.


1

Ich hatte die folgenden Probleme mit den vorhandenen Lösungen und fand etwas, das alle zu lösen scheint. Dies setzt voraus, dass Sie etwas zwischen Browser und Gerät anstreben und kein Geräteschnüffeln möchten.

Die Probleme, die dies löst

Verwenden Sie nur touchstartoder touchend:

  • Bewirkt, dass das Ereignis ausgelöst wird, wenn Personen versuchen, über den Inhalt zu scrollen, und zufällig ihren Finger über dieses Element haben, wenn sie mit dem Wischen beginnen - wodurch die Aktion unerwartet ausgelöst wird.
  • Kann dazu führen , dass das Ereignis auf Longpress ausgelöst wird , ähnlich wie beim Klicken mit der rechten Maustaste auf den Desktop. Wenn Ihr Klickereignis beispielsweise zu URL X wechselt und der Benutzer lange drückt, um X in einer neuen Registerkarte zu öffnen, ist der Benutzer verwirrt, dass X in beiden Registerkarten geöffnet ist. In einigen Browsern (z. B. iPhone) wird möglicherweise sogar verhindert, dass das Menü für langes Drücken angezeigt wird.

Auslösende mouseoverEreignisse auf touchstartund mouseoutauf touchmoveweniger schwerwiegende Folgen, aber mit dem üblichen Browserverhalten, zum Beispiel nicht stört:

  • Ein langes Drücken würde einen Mouseover auslösen, der niemals endet.
  • Viele Android-Browser behandeln die Position des Fingers touchstartwie eine mouseover, die mouseoutbeim nächsten Mal bearbeitet wird touchstart. Eine Möglichkeit, Mouseover-Inhalte in Android anzuzeigen, besteht darin, den gewünschten Bereich zu berühren, mit dem Finger zu wackeln und die Seite leicht zu scrollen. Behandeln touchmoveals mouseoutbricht dies.

Die Lösung

Theoretisch könnte man einfach eine Flagge mit hinzufügen touchmove, aber iPhones lösen Touchmove aus, selbst wenn keine Bewegung vorhanden ist. Theoretisch könnte man einfach das vergleichen touchstartund touchendEreignis pageXund pageY aber auf iPhones, gibt es keine touchend pageXoderpageY .

Um alle Grundlagen abzudecken, ist es leider etwas komplizierter.

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

Theoretisch gibt es Möglichkeiten, die genaue Zeit für ein Longpress zu ermitteln, anstatt nur 1000 als Näherungswert zu verwenden. In der Praxis ist dies jedoch nicht so einfach und es ist am besten, einen angemessenen Proxy zu verwenden .


1

Die Antwort von MacFreak war für mich äußerst hilfreich. Hier ist ein praktischer Code für den Fall, dass er Ihnen hilft.

PROBLEM - Touchend anzuwenden bedeutet, dass jedes Mal, wenn Sie mit dem Finger über ein Element scrollen, es so reagiert, als hätten Sie es gedrückt, selbst wenn Sie nur versucht haben, vorbei zu scrollen.

Ich erstelle mit jQuery einen Effekt, bei dem eine Zeile unter einigen Schaltflächen ausgeblendet wird, um die schwebende Schaltfläche "hervorzuheben". Ich möchte nicht, dass dies bedeutet, dass Sie die Taste auf Touch-Geräten zweimal drücken müssen, um dem Link zu folgen.

Hier sind die Schaltflächen:

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

Ich möchte, dass das Div "menu_underline" beim Mouseover ausgeblendet und beim Mouseout ausgeblendet wird. ABER ich möchte, dass Touch-Geräte dem Link mit einem einzigen Klick folgen können, nicht mit zwei.

LÖSUNG - Hier ist die jQuery, damit es funktioniert:

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

Vielen Dank für Ihre Hilfe bei diesem MacFreak.


1

Ich habe gerade herausgefunden, dass es funktioniert, wenn Sie einen leeren Listener hinzufügen. Fragen Sie mich nicht warum, aber ich habe es auf iPhone und iPad mit iOS 9.3.2 getestet und es hat gut funktioniert.

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

Ich hatte das gleiche Problem, aber nicht auf einem Touch-Gerät. Das Ereignis wird jedes Mal ausgelöst, wenn Sie auf klicken. Event Queuing hat etwas an sich.

Meine Lösung war jedoch wie folgt: Beim Klicken (oder Berühren?) Stellen Sie einen Timer ein. Wenn der Link innerhalb von X ms erneut angeklickt wird, geben Sie einfach false zurück.

Zum Einstellen des Timers pro Element können Sie verwenden $.data() .

Dies kann auch das oben beschriebene @ Frieddy-Problem beheben.


Können Sie posten, wie dieser Code aussieht? Ich habe das Problem, dass ein Klickereignis zweimal ausgelöst wird.
Lust auf den

0

Wenn Sie Modernizr verwenden, ist es sehr einfach, Modernizr.touch zu verwenden, wie bereits erwähnt.

Ich bevorzuge jedoch eine Kombination aus Modernizr.touch und User Agent-Tests, um sicher zu gehen.

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

Wenn Sie Modernizr nicht verwenden, können Sie die Modernizr.touchobige Funktion einfach durch ersetzen('ontouchstart' in document.documentElement)

Beachten Sie außerdem, dass Sie durch das Testen des Benutzeragenten iemobile eine größere Auswahl an erkannten Microsoft-Mobilgeräten als mit Windows Phone erhalten.


0

Sie können verwenden click touchend ,

Beispiel:

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

Das obige Beispiel wirkt sich auf alle Links auf Touch-Geräten aus.

Wenn Sie nur auf bestimmte Links abzielen möchten, können Sie dies tun, indem Sie eine Klasse für diese festlegen, z.

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

Prost,

Jeroen


0

Ich hatte eine ähnliche Situation, in der Ereignisse an die Zustände mouseenter / mouseleave / click eines Elements gebunden waren. Auf einem iPhone musste der Benutzer jedoch auf das Element doppelklicken, um zuerst das mouseenter-Ereignis auszulösen und dann erneut das click-Ereignis auszulösen .

Ich habe dies mit einer ähnlichen Methode wie oben behoben, aber das jQuery $ .browser-Plugin (für jQuery 1.9>) verwendet und dem mouseenter-Bindungsereignis ein .trigger-Ereignis wie folgt hinzugefügt:

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

Der .trigger verhindert, dass ein Doppelklick auf das Element erforderlich ist, indem der .click-Ereignishandler beim Eingeben der Maus (oder beim ersten Klicken) auf das Element ausgelöst wird, wenn er auf iPhones oder iPads angezeigt wird. Vielleicht nicht die eleganteste Lösung, aber sie funktioniert in meinem Fall hervorragend und verwendet ein Plugin, das ich bereits installiert hatte. Ich musste eine einzige Codezeile hinzufügen, damit meine vorhandenen Ereignisse unter diesen Geräten funktionieren.

Sie können das jQuery $ .browser-Plugin hier herunterladen: https://github.com/gabceb/jquery-browser-plugin


0

Nur eine Verbesserung, um eine Umleitung zu vermeiden, wenn Sie versehentlich mit dem Finger über einen Link fahren.

// 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

Mit der Inspiration von MacFreak habe ich etwas zusammengestellt, das für mich funktioniert.

Diese js-Methode verhindert, dass der Hover auf einem iPad bleibt, und verhindert in einigen Fällen, dass der Klick als zwei Klicks registriert wird. Wenn Sie in CSS Folgendes haben: Hover-Psudo-Klassen in Ihrem CSS, ändern Sie diese in .hover. Beispiel: .some-class: Hover in .some-class.hover

Testen Sie diesen Code auf einem iPad, um festzustellen, wie sich die Schwebemethoden von CSS und JS unterschiedlich verhalten (nur im Hover-Effekt). Die CSS-Schaltfläche hat keine ausgefallene Klickwarnung. 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

Damit die Links funktionieren, ohne das Scrollen durch Berühren zu unterbrechen, habe ich dies mit dem "Tap" -Ereignis von jQuery Mobile gelöst:

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

0

Ich bin zu spät, ich weiß, aber dies ist eine der einfachsten Problemumgehungen, die ich gefunden habe:

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

Dies funktioniert nicht nur für Links (Ankertags), sondern auch für andere Elemente. Hoffe das hilft.


0

Dieser kurze Ausschnitt scheint zu funktionieren. Lösen Sie das Klickereignis aus, wenn Sie auf den Link tippen:

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

0

Keine der anderen Antworten funktioniert für mich. Meine App hat viele Ereignis-Listener, eigene Kontrollkästchen und Links mit Listenern und Links ohne Listener.

Ich benutze das:

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

Dies funktioniert für mich, wenn Sie jquery ui Dropdown haben

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

0

Vermeiden Sie es, den "Anzeigestil" innerhalb des Hover-CSS-Ereignisses zu ändern. Ich hatte "display: block" im Schwebezustand. Nach dem Entfernen von ios ging es durch einmaliges Tippen auf Lins. Übrigens scheinen die neuesten IOS-Updates diese "Funktion" behoben zu haben.


0

Der einfachste Weg, einen Doppelklick auf das IPad aufzulösen, besteht darin, Ihr CSS für den Hover-Effekt in eine Medienabfrage zu verpacken @media (pointer: fine):

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

CSS, das in diese Medienabfrage eingeschlossen wurde, wird nur auf dem Desktop angewendet.

Eine Erklärung dieser Lösung finden Sie hier https://css-tricks.com/annoying-mobile-double-tap-link-issue/


-1

Sie könnten dies überprüfen navigator.userAgent:

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

Sie müssten jedoch nach Brombeeren, Droiden und anderen Touchscreen-Geräten suchen. Sie können die Mouseover auch nur binden, wenn der userAgent Mozilla, IE, Webkit oder Opera enthält. Sie müssen jedoch weiterhin nach einigen Geräten suchen, da der Droid beispielsweise die userAgent-Zeichenfolge wie folgt meldet:

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

Die Zeichenfolge des iPhones ist ähnlich. Wenn Sie nur nach iPhone, iPod, iPad, Android und Blackberry suchen, erhalten Sie möglicherweise die meisten Handhelds, jedoch nicht alle.


Ich denke, um nicht verrückt zu werden, könnte das Beste, was zu tun ist, nur ein Skript sein, das die Schwebeereignisse überspringt. Ich denke, die erste Antwort war gut. Und ja, Sie haben Recht. Ich sollte Denken Sie an alle anderen Geräte ... Ich wünschte, Jquery oder ein Plugin hätte diese Art von Dection-Funktion ..!
Francesco

wurfl.sourceforge.net Dies könnte Ihre Antwort sein. Es ist eine Datenbank mit drahtlosen Geräten. Wird nicht so einfach sein wie ein jQuery-Plugin, aber Sie können immer eines schreiben! Es gibt auch tera-wurfl.com , das eine Datenbank anstelle einer XML-Datei verwendet. Ich habe nicht viel gegraben, aber es gibt möglicherweise eine gehostete Version, sodass Sie sich keine Sorgen machen müssen, dass Ihre wurfl-Datei oder Ihre tera-wurfl-Datenbank auf dem neuesten Stand gehalten werden.
Jasongetsdown

1
Vermisse ich etwas oder ging es NICHT darum, iPads zu erkennen, sondern darum, ein bestimmtes Verhalten auf iPads zu umgehen?
Andrew Hedges

5
UA schnüffeln? Wie 90er Jahre: P
Macha

-1

Stellen Sie einfach eine CSS-Medienabfrage, bei der Tablets und mobile Geräte ausgeschlossen sind, und setzen Sie den Hover dort ein. Sie brauchen dafür nicht wirklich jQuery oder JavaScript.

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

Und stellen Sie sicher, dass Sie dies Ihrem HTML-Kopf hinzufügen, um sicherzustellen, dass er mit den tatsächlichen Pixeln und nicht mit der Auflösung berechnet wird.

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.