Ich arbeite an einer mobilen Website, die auf einer Vielzahl von Geräten funktionieren muss. Die, die mir im Moment Kopfschmerzen bereiten, sind BlackBerry.
Wir müssen sowohl Tastaturklicks als auch Berührungsereignisse unterstützen.
Idealerweise würde ich nur verwenden:
$thing.click(function(){...})
Das Problem ist jedoch, dass einige dieser Blackberry-Geräte eine sehr ärgerliche Verzögerung vom Zeitpunkt der Berührung bis zum Auslösen eines Klicks aufweisen.
Das Mittel ist, stattdessen Touchstart zu verwenden:
$thing.bind('touchstart', function(event){...})
Aber wie gehe ich vor, um beide Ereignisse zu binden, aber nur eines auszulösen? Ich benötige das Klickereignis weiterhin für Tastaturgeräte, möchte aber natürlich nicht, dass das Klickereignis ausgelöst wird, wenn ich ein Touch-Gerät verwende.
Eine Bonusfrage: Gibt es überhaupt eine Möglichkeit, dies zu tun und zusätzlich Browser aufzunehmen, die nicht einmal ein Touchstart-Ereignis haben? Es sieht so aus, als ob BlackBerry OS5 Touchstart nicht unterstützt und sich daher auch auf Klickereignisse für diesen Browser verlassen muss.
NACHTRAG:
Vielleicht ist eine umfassendere Frage:
Ist es mit jQuery möglich / empfohlen, sowohl Berührungsinteraktionen als auch Mausinteraktionen mit denselben Bindungen zu behandeln?
Im Idealfall lautet die Antwort ja. Wenn nicht, habe ich einige Optionen:
1) Wir verwenden WURFL, um Geräteinformationen abzurufen und so unsere eigene Gerätematrix zu erstellen. Je nach Gerät verwenden wir Touchstart ODER Klicken.
2) Erkennen Sie die Touch-Unterstützung im Browser über JS (ich muss noch etwas darüber recherchieren, aber es scheint, dass dies machbar ist).
Damit bleibt jedoch noch ein Problem: Was ist mit Geräten, die BEIDE unterstützen? Einige der von uns unterstützten Telefone (nämlich Nokias und BlackBerries) verfügen sowohl über Touchscreens als auch über Tastaturen. Damit schließt sich der Kreis zurück zur ursprünglichen Frage ... gibt es eine Möglichkeit, beides irgendwie gleichzeitig zuzulassen?
quelle
.bind('touchstart mouseup')
wird es lösen (basierend auf einem der Kommentare unten)Antworten:
Update : Schauen Sie sich das jQuery Pointer Events Polyfill- Projekt an, mit dem Sie an "Zeiger" -Ereignisse binden können, anstatt zwischen Maus und Berührung zu wählen.
Binden Sie an beide, aber machen Sie ein Flag, damit die Funktion nur einmal pro 100 ms oder so ausgelöst wird.
quelle
click
change it tomousedown
... zu verwenden, ist möglicherweise die lange Verzögerung der Unterschied zwischenmousedown
undmouseup
wie aclick
bestimmt wird.touchend
indem ich eine Klasse von anwendetouched
. Dies wird ausgelöst, bevor das Klickereignis aufgerufen wird. Ich füge dann ein Klickereignis hinzu, das zuerst die Existenz dieser Klasse überprüft. Wenn es dort ist, nehmen wir an, dass die Berührungsereignisse ausgelöst wurden, und wir tun nichts anderes mit einem Klick, als den Klassennamen zu entfernen, um ihn für die nächste Interaktion zurückzusetzen. Wenn die Klasse nicht vorhanden ist, nehmen wir an, dass sie eine Tastatur verwendet haben, um auf das Element zu klicken und die Funktion von dort aus auszulösen.Dies ist das Update, das ich "erstelle" und das den GhostClick entfernt und den FastClick implementiert. Probieren Sie es selbst aus und lassen Sie uns wissen, ob es für Sie funktioniert hat.
quelle
event.handled
beiundefined
jedem Auslösen des Ereignisses gleich ist. Hier ist eine Lösung: Setzen Sie das Flag 'behandelt' im Zielelement selbst mitjQuery.data()
.event.stopPropagation();
undevent.preventDefault();
nach meinem Verständnis (und Testen) kann das Ereignis nur einmal damit ausgelöst werden. Warum also überhaupt nachsehenif(event.handled !== true)
? Für mich ist es nicht nötig oder vermisse ich etwas?event.handled
auf den Wert überprüft werdentrue
? Soweit ich das beurteilen kann, ist es niefalse
. Es beginnt alsundefined
, und dann möchten Sie feststellen, ob es eingestellt wurdetrue
.Sie könnten so etwas versuchen:
quelle
Normalerweise funktioniert das auch:
quelle
Nur das Hinzufügen
return false;
am Ende deron("click touchstart")
Ereignisfunktion kann dieses Problem lösen.Aus der jQuery-Dokumentation zu .on ()
quelle
Ich musste etwas Ähnliches tun. Hier ist eine vereinfachte Version dessen, was für mich funktioniert hat. Wenn ein Berührungsereignis erkannt wird, entfernen Sie die Klickbindung.
In meinem Fall war das
<a>
Klickereignis an ein Element gebunden, sodass ich die Klickbindung entfernen und ein Klickereignis erneut binden musste, wodurch die Standardaktion für das<a>
Element verhindert wurde.quelle
Es gelang mir auf folgende Weise.
Kinderleicht...
quelle
e
Parameter infunction()
Ich glaube, die beste Vorgehensweise ist jetzt:
BEISPIEL
BEARBEITEN (2017)
Ab 2017 können Browser, die mit Chrome beginnen und Schritte unternehmen, um das Klickereignis
.on("click")
für Maus und Berührung kompatibler zu machen, die Verzögerung beseitigen, die durch Tippereignisse bei Klickanforderungen entsteht.Dies führt zu der Schlussfolgerung, dass die Rückkehr zur Verwendung nur des Klickereignisses die einfachste Lösung für die Zukunft wäre.
Ich habe noch keine Cross-Browser-Tests durchgeführt, um festzustellen, ob dies praktisch ist.
quelle
mouseup
unvorhersehbare Ergebnisse erzielt, insbesondere wenn ich ein Trackpad anstelle einer herkömmlichen Maus verwendet habe.Im Allgemeinen möchten Sie die Standard-Touch- und Non-Touch-API (Klick) nicht mischen. Sobald Sie sich in der Welt der Berührung befinden, ist es einfacher, sich nur mit den berührungsbezogenen Funktionen zu befassen. Unten finden Sie einen Pseudocode, der genau das tut, was Sie möchten.
Wenn Sie im Touchmove-Ereignis eine Verbindung herstellen und die Positionen verfolgen, können Sie der doTouchLogic-Funktion weitere Elemente hinzufügen, um Gesten und so weiter zu erkennen.
quelle
Überprüfen Sie die schnellen Schaltflächen und Chost-Klicks von Google https://developers.google.com/mobile/articles/fast_buttons
quelle
Nun ... All dies ist super kompliziert.
Wenn Sie modernizr haben, ist es ein Kinderspiel.
quelle
Eine weitere Implementierung für eine bessere Wartung. Diese Technik führt jedoch auch event.stopPropagation () aus. Der Klick wird von keinem anderen Element erfasst, das 100 ms lang geklickt hat.
quelle
Nur zu Dokumentationszwecken habe ich Folgendes getan, um den schnellsten / reaktionsschnellsten Klick auf den Desktop / Tippen auf eine mobile Lösung zu erzielen, die mir einfällt:
Ich habe die Funktion von jQuery
on
durch eine modifizierte ersetzt, die, wenn der Browser Berührungsereignisse unterstützt, alle meine Klickereignisse durch Berührungsstart ersetzte.Verwendung als wäre genau die gleiche wie zuvor, wie:
Aber es würde Touchstart verwenden, wenn verfügbar, klicken Sie, wenn nicht. Keine Verzögerungen jeglicher Art erforderlich: D.
quelle
Ich hatte gerade die Idee, mir zu merken, ob
ontouchstart
es jemals ausgelöst wurde. In diesem Fall befinden wir uns auf einem Gerät, das dies unterstützt, und möchten dasonclick
Ereignis ignorieren . Daontouchstart
sollte immer vorher ausgelöst werdenonclick
, benutze ich dies:quelle
Sie könnten es so versuchen:
quelle
In meinem Fall hat das perfekt funktioniert:
Das Hauptproblem war, als ich stattdessen mit einem Mausklick versuchte, auf Touch-Geräten Klick und Touchend gleichzeitig auszulösen. Wenn ich den Klick-Off verwende, funktionierten einige Funktionen auf Mobilgeräten überhaupt nicht. Das Problem beim Klicken ist, dass es sich um ein globales Ereignis handelt, das den Rest des Ereignisses einschließlich Touchend auslöst.
quelle
Das hat bei mir funktioniert, Mobile hört auf beide, also verhindere das, was das Touch-Ereignis ist. Desktop nur Maus hören.
quelle
Da ich für mich die beste Antwort von Mottie bin, versuche ich nur, seinen Code wiederverwendbarer zu machen. Das ist also mein Beitrag:
quelle
Ich arbeite auch an einer Android / iPad-Web-App, und es scheint, dass die Verwendung von "touchmove" ausreicht, um "Komponenten zu verschieben" (kein Touchstart erforderlich). Durch Deaktivieren von Touchstart können Sie .click () verwenden. von jQuery. Es funktioniert tatsächlich, weil es nicht durch Touchstart überlastet wird.
Schließlich können Sie binb .live ("touchstart", Funktion (e) {e.stopPropagation ();}); Um das Touchstart-Ereignis zu bitten, die Ausbreitung zu stoppen, klicken Sie im Wohnzimmer auf (), um ausgelöst zu werden.
Es hat bei mir funktioniert.
quelle
touchstart
?Bei der Lösung dieses Problems sind viele Dinge zu beachten. Die meisten Lösungen unterbrechen entweder das Scrollen oder behandeln Ghost-Click-Ereignisse nicht richtig.
Eine vollständige Lösung finden Sie unter https://developers.google.com/mobile/articles/fast_buttons
NB: Sie können Ghost-Click-Ereignisse nicht pro Element verarbeiten. Ein verzögerter Klick wird nach Bildschirmposition ausgelöst. Wenn Ihre Berührungsereignisse die Seite auf irgendeine Weise ändern, wird das Klickereignis an die neue Version der Seite gesendet.
quelle
Es kann effektiv sein, die Ereignisse zuzuordnen
'touchstart mousedown'
oder'touchend mouseup'
unerwünschte Nebenwirkungen der Verwendung zu vermeidenclick
.quelle
Unter Ausnutzung der Tatsache, dass ein Klick immer auf ein Berührungsereignis folgt, habe ich Folgendes getan, um den "Geisterklick" zu beseitigen, ohne Zeitüberschreitungen oder globale Flags verwenden zu müssen.
Grundsätzlich wird jedes Mal, wenn ein
ontouchstart
Ereignis auf das Element ausgelöst wird, ein Flag gesetzt und anschließend entfernt (und ignoriert), wenn der Klick erfolgt.quelle
Warum nicht die jQuery-Ereignis-API verwenden?
http://learn.jquery.com/events/event-extensions/
Ich habe dieses einfache Ereignis mit Erfolg genutzt. Es ist sauber, namenreich und flexibel genug, um es zu verbessern.
quelle
Wenn Sie jQuery verwenden, hat Folgendes für mich ziemlich gut funktioniert:
Andere Lösungen sind ebenfalls gut, aber ich habe mehrere Ereignisse in einer Schleife gebunden und benötigte die selbstaufrufende Funktion, um einen geeigneten Abschluss zu erstellen. Außerdem wollte ich die Bindung nicht deaktivieren, da ich wollte, dass sie beim nächsten Klick / Touchstart aufgerufen werden kann.
Könnte jemandem in einer ähnlichen Situation helfen!
quelle
Für einfache Funktionen erkennen Sie einfach Berührung oder klicken Sie auf Ich verwende den folgenden Code:
Dies gibt "touch" zurück, wenn das touchstart-Ereignis definiert ist, und "no touch", wenn nicht. Wie ich bereits sagte, ist dies ein einfacher Ansatz für Click / Tap-Ereignisse.
quelle
Ich versuche dies und bis jetzt funktioniert es (aber ich bin nur auf Android / Phonegap also Vorbehalt Emptor)
Ich mag die Tatsache nicht, dass ich Handler bei jeder Berührung neu binde, aber alles, was als Berührungen betrachtet wird, kommt nicht sehr oft vor (in der Computerzeit!)
Ich habe eine TONNE Handler wie den für '#keypad'. Eine einfache Funktion, mit der ich das Problem ohne zu viel Code lösen kann, ist der Grund, warum ich diesen Weg gegangen bin.
quelle
Versuchen Sie , verwenden
Virtual Mouse (vmouse) Bindings
ausjQuery Mobile
. Es ist ein virtuelles Ereignis speziell für Ihren Fall:http://api.jquerymobile.com/vclick/
Browser-Support-Liste: http://jquerymobile.com/browser-support/1.4/
quelle
EDIT: Meine frühere Antwort (basierend auf den Antworten in diesem Thread) war nicht der richtige Weg für mich. Ich wollte, dass ein Untermenü beim Eingeben oder Klicken mit der Maus erweitert und beim Verlassen der Maus oder einem anderen Klick ausgeblendet wird. Da Mausereignisse normalerweise nach Berührungsereignissen ausgelöst werden, war es schwierig, Ereignis-Listener zu schreiben, die sowohl Touchscreen- als auch Mauseingaben gleichzeitig unterstützen.
jQuery-Plugin: Berühren oder Maus
Am Ende habe ich ein jQuery-Plugin namens " Touch Or Mouse " (897 Byte minimiert) geschrieben, das erkennen kann, ob ein Ereignis von einem Touchscreen oder einer Maus aufgerufen wurde (ohne auf Touch-Unterstützung zu testen!). Dies ermöglicht die Unterstützung von sowohl Touchscreen und Maus gleichzeitig und vollständig trennen ihre Veranstaltungen.
Auf diese Weise kann das OP Touch-Klicks und Klicks, die nur von einer Maus aufgerufen werden, verwenden
touchstart
odertouchend
schnell darauf reagieren .click
Demonstration
Zuerst muss man also machen. das Körperelement verfolgt Berührungsereignisse:
$body.touchOrMouse('get', e)
Mausereignisse sind standardmäßig an Elemente gebunden. Durch Aufrufen können wir herausfinden, ob das Ereignis über einen Touchscreen oder eine Maus aufgerufen wurde.Siehe das Plugin bei der Arbeit unter http://jsfiddle.net/lmeurs/uo4069nh .
Erläuterung
touchstart
undtouchend
Ereignisse, auf diese Weise dastouchend
Ereignis nicht auf dem Auslöseelement gebrannt werden muss (dh. ein Link oder eine Schaltfläche). Zwischen diesen beiden Berührungsereignissen betrachtet dieses Plugin jedes Mausereignis als durch Berühren aufgerufen.touchend
Mausereignisse werden erst ausgelöst , nachdem ein Mausereignis innerhalb derghostEventDelay
Option (Option 1000 ms standardmäßig) ausgelösttouchend
wurde. Dieses Plugin betrachtet das Mausereignis als durch Berühren aufgerufen.:active
Status. Dasmouseleave
Ereignis wird erst ausgelöst, nachdem das Element diesen Zustand um dh verloren hat. Klicken Sie auf ein anderes Element. Da dies Sekunden (oder Minuten!) Nach demmouseenter
Auslösen des Ereignisses sein kann, verfolgt dieses Plugin das letztemouseenter
Ereignis eines Elements : Wenn das letztemouseenter
Ereignis durch Berühren aufgerufen wurde, gilt das folgendemouseleave
Ereignis auch als durch Berühren aufgerufen.quelle
Hier ist eine einfache Möglichkeit, dies zu tun:
Grundsätzlich speichern Sie den ersten Ereignistyp, der ausgelöst wird, in der Eigenschaft 'trigger' im Datenobjekt von jQuery, das an das Stammdokument angehängt ist, und führen ihn nur aus, wenn der Ereignistyp dem Wert in 'trigger' entspricht. Auf Touch-Geräten lautet die Ereigniskette wahrscheinlich "Touchstart", gefolgt von "Klicken". Der 'click'-Handler wird jedoch nicht ausgeführt, da "click" nicht mit dem ursprünglichen Ereignistyp übereinstimmt, der in' trigger '("touchstart") gespeichert ist.
Die Annahme, und ich glaube, es ist sicher, ist, dass Ihr Smartphone nicht spontan von einem Touch-Gerät zu einem Mausgerät wechselt oder dass sich der Tipp niemals registriert, da der Ereignistyp "Auslöser" nur einmal pro gespeichert wird Seitenladen und "Klicken" würden niemals mit "Touchstart" übereinstimmen.
Hier ist ein Codepen, mit dem Sie herumspielen können (versuchen Sie, auf einem Touch-Gerät auf die Schaltfläche zu tippen - es sollte keine Klickverzögerung geben): http://codepen.io/thdoan/pen/xVVrOZ
Ich habe dies auch als einfaches jQuery-Plugin implementiert, das auch das Filtern von Nachkommen von jQuery durch Übergeben einer Auswahlzeichenfolge unterstützt:
Codepen: http://codepen.io/thdoan/pen/GZrBdo/
quelle
$.data()
Speichern von Daten, auf die mehrere Funktionen zugreifen können, die jedoch nicht zum globalen Bereich gehören. Ein Plus ist, dass ich, da ich es in einem Element speichere, natürlich mehr Kontext habe.Die beste Methode, die ich gefunden habe, besteht darin, das Berührungsereignis zu schreiben und dieses Ereignis das normale Klickereignis programmgesteuert aufrufen zu lassen. Auf diese Weise haben Sie alle Ihre normalen Klickereignisse und müssen dann nur einen Ereignishandler für alle Berührungsereignisse hinzufügen. Fügen Sie für jeden Knoten, den Sie berührbar machen möchten, einfach die Klasse "berührbar" hinzu, um den Berührungshandler aufzurufen. Mit Jquery funktioniert es mit einer gewissen Logik, um sicherzustellen, dass es sich um ein echtes Berührungsereignis und nicht um ein falsches Positiv handelt.
quelle