Je travaille sur un site Web mobile qui doit fonctionner sur une variété d'appareils. Celui qui me fait mal à la tête en ce moment est BlackBerry.
Nous devons prendre en charge les clics sur le clavier ainsi que les événements tactiles.
Idéalement, j'utiliserais simplement:
$thing.click(function(){...})
mais le problème que nous rencontrons est que certains de ces appareils BlackBerry ont un délai très gênant entre le moment où le toucher et le déclenchement d'un clic.
Le remède consiste à utiliser plutôt le démarrage tactile:
$thing.bind('touchstart', function(event){...})
Mais comment puis-je lier les deux événements, mais n'en déclencher qu'un? J'ai toujours besoin de l'événement click pour les périphériques clavier, mais bien sûr, je ne veux pas que l'événement click se déclenche si j'utilise un périphérique tactile.
Une question bonus: existe-t-il de toute façon de le faire et d'accueillir en outre des navigateurs qui n'ont même pas d'événement tactile? En recherchant cela, il semble que BlackBerry OS5 ne prend pas en charge le démarrage tactile, il devra donc également s'appuyer sur les événements de clic pour ce navigateur.
ADDENDA:
Peut-être une question plus globale est:
Avec jQuery, est-il possible / recommandé de gérer à la fois les interactions tactiles et les interactions avec la souris avec les mêmes liaisons?
Idéalement, la réponse est oui. Sinon, j'ai quelques options:
1) Nous utilisons WURFL pour obtenir des informations sur les appareils afin de créer notre propre matrice d'appareils. Selon l'appareil, nous utiliserons le démarrage tactile OU cliquez sur.
2) Détecter la prise en charge tactile dans le navigateur via JS (j'ai besoin de faire plus de recherches à ce sujet, mais il semble que cela soit faisable).
Cependant, cela laisse toujours un problème: qu'en est-il des appareils qui prennent en charge les deux. Certains des téléphones que nous prenons en charge (à savoir les Nokias et les Blackberry) ont à la fois des écrans tactiles et des claviers. Donc, ce genre de chose me ramène à la question d'origine ... existe-t-il un moyen de permettre les deux à la fois d'une manière ou d'une autre?
.bind('touchstart mouseup')
le résoudra (basé sur l'un des commentaires ci-dessous)Réponses:
Mise à jour : Découvrez le projet jQuery Pointer Events Polyfill qui vous permet de vous lier à des événements "pointeur" au lieu de choisir entre la souris et le toucher.
Liez aux deux, mais créez un indicateur pour que la fonction ne se déclenche qu'une fois toutes les 100 ms environ.
la source
click
changer enmousedown
... peut-être le long délai est la différence entremousedown
etmouseup
qui est la façon dont aclick
est déterminé.touchend
en appliquant une classe detouched
. Cela se déclenche avant l'appel à l'événement click. J'ajoute ensuite un événement click qui vérifie d'abord l'existence de cette classe. Si c'est le cas, nous supposons que les événements tactiles ont été déclenchés et nous ne faisons rien d'autre avec un clic que de supprimer le nom de la classe pour le «réinitialiser» pour la prochaine interaction. Si la classe n'est pas là, nous supposons qu'ils ont utilisé un clavier pour cliquer sur l'élément et déclencher la fonction à partir de là.C'est le correctif que je "crée" et il supprime le GhostClick et implémente le FastClick. Essayez par vous-même et faites-nous savoir si cela a fonctionné pour vous.
la source
event.handled
sera donc égal àundefined
chaque fois que l'événement est déclenché. Voici une solution: définissez l'indicateur «géré» dans l'élément cible lui-même à l'aide dejQuery.data()
.event.stopPropagation();
et d'event.preventDefault();
après ma compréhension (et mes tests), l'événement ne peut être déclenché qu'une seule fois avec cela. alors pourquoi même vérifierif(event.handled !== true)
? Pour moi, ce n'est pas nécessaire ou je manque quelque chose?event.handled
être vérifié pour la valeurtrue
? Pour autant que je sache, ce n'est jamaisfalse
. Il commence parundefined
, puis vous voulez savoir s'il a été défini surtrue
.Vous pouvez essayer quelque chose comme ceci:
la source
Habituellement, cela fonctionne aussi:
la source
Un simple ajout
return false;
à la fin de laon("click touchstart")
fonction d'événement peut résoudre ce problème.De la documentation jQuery sur .on ()
la source
J'ai dû faire quelque chose de similaire. Voici une version simplifiée de ce qui a fonctionné pour moi. Si un événement tactile est détecté, supprimez la liaison de clic.
Dans mon cas, l'événement click était lié à un
<a>
élément, j'ai donc dû supprimer la liaison click et relier un événement click qui a empêché l'action par défaut de l'<a>
élément.la source
J'ai réussi par la voie suivante.
Peasy facile...
la source
e
paramètre dansfunction()
Je crois que la meilleure pratique consiste maintenant à utiliser:
EXEMPLE
EDIT (2017)
Depuis 2017, les navigateurs commençant par Chrome et effectuant des étapes vers la création de l'événement de clic
.on("click")
plus compatible pour la souris et le toucher en éliminant le retard généré par les événements tap sur les demandes de clic.Cela conduit à la conclusion que le retour à l'utilisation de l'événement click serait la solution la plus simple pour aller de l'avant.
Je n'ai pas encore fait de tests croisés pour voir si cela est pratique.
la source
mouseup
des résultats imprévisibles, surtout lorsque j'utilise un trackpad au lieu d'une souris traditionnelle.Généralement, vous ne voulez pas mélanger les API tactile et non tactile (clic) par défaut. Une fois que vous entrez dans le monde du toucher, il est plus facile de traiter uniquement les fonctions liées au toucher. Voici un pseudo-code qui ferait ce que vous voulez.
Si vous vous connectez à l'événement touchmove et suivez les emplacements, vous pouvez ajouter d'autres éléments dans la fonction doTouchLogic pour détecter les gestes et ainsi de suite.
la source
vérifier les boutons rapides et enregistrer les clics sur google https://developers.google.com/mobile/articles/fast_buttons
la source
Eh bien ... Tout cela est super compliqué.
Si vous avez modernizr, c'est une évidence.
la source
Une autre implémentation pour une meilleure maintenance. Cependant, cette technique fera également event.stopPropagation (). Le clic n'est détecté sur aucun autre élément ayant cliqué pendant 100 ms.
la source
Juste à des fins de documentation, voici ce que j'ai fait pour le clic le plus rapide / le plus réactif sur le bureau / appuyez sur la solution mobile à laquelle je pourrais penser:
J'ai remplacé la
on
fonction de jQuery par une fonction modifiée qui, chaque fois que le navigateur prend en charge les événements tactiles, a remplacé tous mes événements de clic par TouchStart.L'utilisation serait la même qu'avant, comme:
Mais il utiliserait le démarrage tactile lorsqu'il est disponible, cliquez dans le cas contraire. Aucun retard d'aucune sorte nécessaire: D
la source
Je suis juste venu avec l'idée de mémoriser si
ontouchstart
jamais cela se déclenchait. Dans ce cas, nous sommes sur un appareil qui le prend en charge et voulons ignorer l'onclick
événement. Puisqueontouchstart
devrait toujours être déclenché avantonclick
, j'utilise ceci:la source
Vous pouvez essayer comme ceci:
la source
Dans mon cas, cela a parfaitement fonctionné:
Le problème principal était quand à la place mouseup j'ai essayé avec le clic, sur les appareils tactiles, déclenchait le clic et le toucher en même temps, si j'utilise le clic, certaines fonctionnalités ne fonctionnaient pas du tout sur les appareils mobiles. Le problème avec le clic est qu'il s'agit d'un événement global qui déclenche le reste de l'événement, y compris le toucher.
la source
Cela a fonctionné pour moi, le mobile écoute les deux, alors évitez celui qui est l'événement tactile. le bureau n'écoute que la souris.
la source
Étant pour moi la meilleure réponse que celle donnée par Mottie, j'essaie juste de rendre son code plus réutilisable, c'est donc ma contribution:
la source
Je travaille également sur une application web Android / iPad, et il semble que si seulement "touchmove" suffit pour "déplacer des composants" (pas besoin de toucher au démarrage). En désactivant le démarrage tactile, vous pouvez utiliser .click (); de jQuery. Cela fonctionne réellement car il n'a pas été surchargé par le démarrage tactile.
Enfin, vous pouvez binb .live ("touchstart", function (e) {e.stopPropagation ();}); pour demander à l'événement Touchstart d'arrêter de se propager, le salon clique sur () pour se déclencher.
Ça a marché pour moi.
la source
touchstart
?Il y a beaucoup de choses à considérer lorsque vous essayez de résoudre ce problème. La plupart des solutions interrompent le défilement ou ne gèrent pas correctement les événements de clics fantômes.
Pour une solution complète, voir https://developers.google.com/mobile/articles/fast_buttons
NB: Vous ne pouvez pas gérer les événements de clics fantômes par élément. Un clic retardé est déclenché par l'emplacement de l'écran, donc si vos événements tactiles modifient la page d'une certaine manière, l'événement click sera envoyé à la nouvelle version de la page.
la source
Il peut être efficace de l'attribuer aux événements
'touchstart mousedown'
ou'touchend mouseup'
d'éviter les effets secondaires indésirables de l'utilisationclick
.la source
Profitant du fait qu'un clic suivra toujours un événement tactile, voici ce que j'ai fait pour me débarrasser du «clic fantôme» sans avoir à utiliser de timeouts ou de drapeaux globaux.
Fondamentalement, chaque fois qu'un
ontouchstart
événement se déclenche sur l'élément, un indicateur un ensemble, puis supprimé (et ignoré), lorsque le clic arrive.la source
Pourquoi ne pas utiliser l'API jQuery Event?
http://learn.jquery.com/events/event-extensions/
J'ai utilisé cet événement simple avec succès. Il est propre, suffisamment identifiable et suffisamment flexible pour être amélioré.
la source
Si vous utilisez jQuery, les éléments suivants ont très bien fonctionné pour moi:
D'autres solutions sont également bonnes, mais je liais plusieurs événements dans une boucle et j'avais besoin de la fonction d'appel automatique pour créer une fermeture appropriée. De plus, je ne voulais pas désactiver la liaison car je voulais qu'elle puisse être invoquée au prochain clic / toucher.
Pourrait aider quelqu'un dans une situation similaire!
la source
Pour des fonctionnalités simples, reconnaissez simplement le toucher ou cliquez sur J'utilise le code suivant:
Cela renverra "toucher" si l'événement de démarrage tactile est défini et "pas de contact" sinon. Comme je l'ai dit, c'est une approche simple pour les événements click / tap.
la source
J'essaye ceci et jusqu'ici ça marche (mais je ne suis que sur Android / Phonegap donc caveat emptor)
Je n'aime pas le fait que je réaffecte les gestionnaires à chaque contact, mais toutes les choses considérées ne se produisent pas très souvent (en temps d'ordinateur!)
J'ai une tonne de gestionnaires comme celui de '#keypad', donc avoir une fonction simple qui me permet de résoudre le problème sans trop de code est la raison pour laquelle je suis allé de cette façon.
la source
Essayez d'utiliser à
Virtual Mouse (vmouse) Bindings
partir dejQuery Mobile
. C'est un événement virtuel spécialement pour votre cas:http://api.jquerymobile.com/vclick/
Liste de support du navigateur: http://jquerymobile.com/browser-support/1.4/
la source
ÉDITER: Mon ancienne réponse (basée sur les réponses dans ce fil) n'était pas la voie à suivre pour moi. Je voulais un sous-menu à développer lors de la saisie de la souris ou du clic tactile et de réduire le congé de la souris ou un autre clic tactile. Étant donné que les événements de souris sont normalement déclenchés après des événements tactiles, il était assez difficile d'écrire des écouteurs d'événements qui prennent en charge à la fois l'écran tactile et la souris.
Plugin jQuery: Touch Or Mouse
J'ai fini par écrire un plugin jQuery appelé " Touch Or Mouse " (897 octets minifiés) qui peut détecter si un événement a été invoqué par un écran tactile ou une souris (sans tester la prise en charge tactile!). Cela permet la prise en charge de l'écran tactile et de la souris en même temps et sépare complètement leurs événements.
De cette façon, l'OP peut utiliser
touchstart
outouchend
pour répondre rapidement aux clics tactiles etclick
pour les clics invoqués uniquement par une souris.Manifestation
Il faut d'abord faire ie. les événements tactiles de piste de l'élément de corps:
Les événements de souris sont liés aux éléments par défaut et en appelant,
$body.touchOrMouse('get', e)
nous pouvons savoir si l'événement a été invoqué par un écran tactile ou une souris.Voir le plugin à l'œuvre sur http://jsfiddle.net/lmeurs/uo4069nh .
Explication
touchstart
et lestouchend
événements, de cette façon, l'touchend
événement n'a pas à être déclenché sur l'élément déclencheur (c'est-à-dire un lien ou un bouton). Entre ces deux événements tactiles, ce plugin considère que tout événement de souris est appelé par le toucher.touchend
, lorsqu'un événement de souris est déclenché dansghostEventDelay
(option, 1000 ms par défaut) aprèstouchend
, ce plugin considère que l'événement de souris est invoqué par le toucher.:active
état. L'mouseleave
événement n'est déclenché que lorsque l'élément perd cet état par ie. en cliquant sur un autre élément. Étant donné que cela peut se produire quelques secondes (ou minutes!) Après lemouseenter
déclenchement de l' événement, ce plugin conserve la trace du derniermouseenter
événement d'un élément : si le derniermouseenter
événement a été appelé au toucher, l'mouseleave
événement suivant est également considéré comme étant appelé au toucher.la source
Voici un moyen simple de le faire:
Vous enregistrez essentiellement le premier type d'événement qui est déclenché dans la propriété 'trigger' dans l'objet de données de jQuery qui est attaché au document racine, et vous ne l'exécutez que lorsque le type d'événement est égal à la valeur dans 'trigger'. Sur les appareils tactiles, la chaîne d'événements serait probablement «touchstart» suivie de «click»; cependant, le gestionnaire «click» ne sera pas exécuté car «click» ne correspond pas au type d'événement initial enregistré dans «trigger» («touchstart»).
L'hypothèse, et je pense qu'elle est sûre, est que votre smartphone ne passera pas spontanément d'un appareil tactile à un appareil de souris ou bien le robinet ne s'enregistrera jamais car le type d'événement `` déclencheur '' n'est enregistré qu'une fois par le chargement de la page et le «clic» ne correspondraient jamais au «démarrage tactile».
Voici un codepen avec lequel vous pouvez jouer (essayez d'appuyer sur le bouton d'un appareil tactile - il ne devrait pas y avoir de retard de clic): http://codepen.io/thdoan/pen/xVVrOZ
J'ai également implémenté cela comme un simple plugin jQuery qui prend également en charge le filtrage des descendants de jQuery en passant une chaîne de sélection:
Codepen: http://codepen.io/thdoan/pen/GZrBdo/
la source
$.data()
pour stocker des données accessibles par plusieurs fonctions mais qui n'appartiennent pas à la portée globale. Un avantage est que puisque je le stocke dans un élément, il me fournit naturellement plus de contexte.La meilleure méthode que j'ai trouvée consiste à écrire l'événement tactile et à faire en sorte que cet événement appelle l'événement de clic normal par programmation. De cette façon, vous avez tous vos événements de clic normaux, puis vous devez ajouter un seul gestionnaire d'événements pour tous les événements tactiles. Pour chaque nœud que vous souhaitez rendre touchable, ajoutez simplement la classe "touchable" pour invoquer le gestionnaire tactile. Avec Jquery, cela fonctionne comme ça avec une certaine logique pour s'assurer que c'est un véritable événement tactile et non un faux positif.
la source