web-dev-qa-db-fra.com

Vous utilisez l'événement mousedown sur mobile sans jQuery mobile?

J'ai construit une webapp, et pour un peu de polissage, je voulais ajouter des gestionnaires de souris et de souris pour échanger des images (dans ce cas, pour donner l'impression qu'un bouton est pressé).

mon code est quelque chose comme ceci:

window.onload = function() {
    //preload mouse down image here via Image()
    $("#button_img").mousedown(function(){$("#button_img").attr("src","button_on.png");});
    $("#button_img").mouseup(function(){$("#button_img").attr("src","button_off.png")});
}

Cela fonctionne parfaitement sur le bureau, mais sur mobile (test dans iOS Safari), les événements mousedown et mouseup se produisent en même temps, donc rien ne se passe effectivement.

J'ai essayé d'utiliser les événements vmousedown et vmouseup dans jQueryMobile, cependant ce code:

//include jquerymobile.js and jquerymobile.css 
window.onload = function() {
    //preload mouse down image here via Image()
    $("#button_img").vmousedown(function(){$("#button_img").attr("src","button_on.png");});
    $("#button_img").vmouseup(function(){$("#button_img").attr("src","button_off.png")});
}

Je viens de me donner les erreurs que vmousedown et vmouseup n'existent pas. De plus, jQueryMobile remplace le CSS que j'ai déjà écrit pour la page.

Existe-t-il donc un moyen de faire fonctionner vmousedown et vmouseup et de le faire sans CSS de jQuery Mobile?

26
Esaevian

Vous recherchez touchstart et touchend. Ce sont les événements que vmousedown et vmouseup tentent d'imiter.

Voici un exemple:

window.onload = function() {
    //preload mouse down image here via Image()
    $("#button_img").bind('touchstart', function(){
        $("#button_img").attr("src","button_on.png");
    }).bind('touchend', function(){
        $("#button_img").attr("src","button_off.png");
    });
}

Cela fonctionnera sans aucun cadre sur aucun appareil qui prend en charge les événements tactiles. Vous pouvez utiliser quelque chose comme Modernizr pour faire ce test et si l'appareil ne prend pas en charge les événements tactiles, liez-les aux événements de bureau habituels.

Lorsque vous utilisez touchstart/touchend/touchmove vous obtenez des informations intéressantes, par exemple le nombre de touches qui se produisent à la fois, afin que vous puissiez détecter si l'utilisateur fait défiler ou tente pour zoomer.

[~ # ~] mise à jour [~ # ~]

Étant donné que l'objet event à l'intérieur d'un gestionnaire d'événements diffère pour les événements tactiles et les événements de souris, si vous voulez connaître les coordonnées de l'événement de toute façon, vous pouvez faire quelque chose comme ceci (l'exemple ci-dessous suppose que Modernizr a été chargé) :

//determine which events to use
var startEventType = 'mousedown',
    endEventType   = 'mouseup';

if (Modernizr.touch === true) {
    startEventType = 'touchstart';
    endEventType   = 'touchend';
}

//bind to determined event(s)
$("#button_img").bind(startEventType, function(event) {

    //determine where to look for pageX by the event type
    var pageX = (startEventType === 'mousedown')
                ? event.pageX
                : event.originalEvent.touches[0].pageX;

    ...
})...

[~ # ~] mise à jour [~ # ~]

Je regardais cela et il semble que vous n'ayez pas besoin de détecter le type d'événement avant de lier le gestionnaire d'événements:

//bind to determined event(s)
$("#button_img").bind('mousedown touchstart', function(event) {

    //determine where to look for pageX by the event type
    var pageX = (event.type.toLowerCase() === 'mousedown')
                ? event.pageX
                : event.originalEvent.touches[0].pageX;

    ...
})...

Si vous craignez de recevoir les deux événements en succession rapide, vous pouvez utiliser un délai d'expiration pour limiter le gestionnaire d'événements:

//create timer
var timer = null;

//bind to determined event(s)
$("#button_img").bind('mousedown touchstart', function(event) {

    //clear timer
    clearTimeout(timer);

    //set timer
    timer = setTimeout(function () {

        //determine where to look for pageX by the event type
        var pageX = (event.type.toLowerCase() === 'mousedown')
                    ? event.pageX
                    : event.originalEvent.touches[0].pageX;

        ...

    }, 50);
})...

Remarque: Vous pouvez forcer les événements mousedown et touchstart en succession rapide avec les outils de développement, mais je ne suis pas sûr du cas d'utilisation réel ici.

59
Jasper

Il existe un moyen d'obtenir les fonctionnalités vmouseup, vmousedown, vmousemove, vclick, etc. de jQueryMobile sans obtenir tout le reste (et surtout le côté effets) de jquerymobile (c.-à-d. amélioration, css supplémentaire, etc.)

  • Allez sur http://jquerymobile.com/download-builder/ (un outil pour télécharger une version personnalisée de jquerymobile avec uniquement les composants dont vous avez besoin)
  • sélectionnez UNIQUEMENT "Liaisons de souris virtuelle (vmouse)"
  • télécharge le.

Le téléchargement ne contiendra qu'un seul fichier .js (en version réduite et non compressée). Pas de CSS.

Liez ce script dans la tête de votre html après un simple jquery, et utilisez-le comme ceci:

<head>
  <script src="http://code.jquery.com/ui/1.10.4/jquery-ui.min.js"></script>
  <script src="whatever/path/jquery.mobile.custom.min.js"></script>
  <script>
    $(function(){ // or replace this with window.onload for that matter
      // Your code here, e.g.
      $("#button_img").on("vmousedown", function() { 
        /*whatever*/
      });
      // CAUTION: this won't work (see note below):
      // $("#button_img").vmousedown(function(){/*whatever*/}); // WON'T WORK
    });
  </script>
</head>

[~ # ~] note [~ # ~] : les méthodes .vmousedown(), .vmouseup(), etc. ne fonctionnera pas. Vous devez lier l'écouteur d'événements avec .on("vmousedown", ...). Je ne sais pas pourquoi: je suppose que c'est parce que la partie de jquerymobile qui crée des méthodes de raccourci avec le même nom que les événements se trouve dans un autre module. Il est peut-être possible de déterminer de quel module il s'agit et de l'inclure dans le téléchargement, mais je pense que cela vous obligerait à inclure d'autres dépendances indésirables.

4
matteo

Avez-vous plutôt pensé à styliser vos boutons en utilisant CSS? les :active l'état sera déclenché lorsqu'un utilisateur cliquera/touchera l'élément. Voici un exemple:

/* Default state */
#button_img {
    background-image: url('button_off.png');
}

/* Clicked/touched state */
#button_img:active { 
    background-image: url('button_on.png');
}

CSS sera beaucoup plus performant et vous pourrez également mieux séparer les préoccupations (affichage vs logique, etc.).

JSBin: http://jsbin.com/beyin/1/

4
pseudosavant