C'est ce que j'ai trouvé jusqu'ici après avoir étudié le reste des réponses. Il devrait pouvoir prendre en charge les utilisateurs tactiles uniquement, souris uniquement ou hybrides.
Créez une classe de survol distincte pour l'effet de survol. Par défaut, ajoutez cette classe de survol à notre bouton.
Nous ne voulons pas détecter la présence du support tactile et désactiver tous les effets de survol dès le début. Comme mentionné par d'autres, les appareils hybrides gagnent en popularité; les gens peuvent avoir un support tactile mais veulent utiliser une souris et vice versa. Par conséquent, supprimez la classe de survol uniquement lorsque l'utilisateur touche réellement le bouton.
Le problème suivant est le suivant: que se passe-t-il si l'utilisateur souhaite revenir à l'utilisation d'une souris après avoir touché le bouton? Pour résoudre cela, nous devons trouver un moment opportun pour rajouter la classe de survol que nous avons supprimée.
Cependant, nous ne pouvons pas le rajouter immédiatement après l'avoir supprimé, car l'état de survol est toujours actif. Nous pouvons également ne pas vouloir détruire et recréer le bouton entier.
J'ai donc pensé à utiliser un algorithme d'attente occupé (en utilisant setInterval) pour vérifier l'état de survol. Une fois l'état de survol désactivé, nous pouvons ensuite rajouter la classe de survol et arrêter l'attente occupée, nous ramenant à l'état d'origine où l'utilisateur peut utiliser la souris ou le toucher.
Je sais que l'attente occupée n'est pas terrible, mais je ne sais pas s'il y a un événement approprié. J'ai envisagé de l'ajouter à l'événement mouseleave, mais ce n'était pas très robuste. Par exemple, lorsqu'une alerte apparaît après avoir touché le bouton, la position de la souris change mais l'événement mouseleave n'est pas déclenché.
var button = document.getElementById('myButton');
button.ontouchstart = function(e) {
console.log('ontouchstart');
$('.button').removeClass('button-hover');
startIntervalToResetHover();
};
button.onclick = function(e) {
console.log('onclick');
}
var intervalId;
function startIntervalToResetHover() {
// Clear the previous one, if any.
if (intervalId) {
clearInterval(intervalId);
}
intervalId = setInterval(function() {
// Stop if the hover class already exists.
if ($('.button').hasClass('button-hover')) {
clearInterval(intervalId);
intervalId = null;
return;
}
// Checking of hover state from
// http://stackoverflow.com/a/8981521/2669960.
var isHovered = !!$('.button').filter(function() {
return $(this).is(":hover");
}).length;
if (isHovered) {
console.log('Hover state is active');
} else {
console.log('Hover state is inactive');
$('.button').addClass('button-hover');
console.log('Added back the button-hover class');
clearInterval(intervalId);
intervalId = null;
}
}, 1000);
}
.button {
color: green;
border: none;
}
.button-hover:hover {
background: yellow;
border: none;
}
.button:active {
border: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id='myButton' class='button button-hover'>Hello</button>
Edit: Une autre approche que j'ai essayée est d'appeler e.preventDefault()
dans ontouchstart ou ontouchend. Il semble arrêter l'effet de survol lorsque le bouton est touché, mais il arrête également l'animation de clic sur le bouton et empêche la fonction onclick d'être appelée lorsque le bouton est touché, vous devez donc les appeler manuellement dans le gestionnaire ontouchstart ou ontouchend. Pas une solution très propre.