Is there a preferred alternative or best practice for handling OnMouseOver javascript events on touch devices? All I can think is to convert all events to OnMouseClick. Un
Unfortunately I do not know about best practices or a preferred alternative to onmouseover
on touch-devices, but in encountering the same question I ended up developing this vanillaJS solution where I count the milliseconds between onmouseenter
and onclick
, and am therefore able to distinguish between desktop-clicking and mobile-clicking.
Upon investigating the two events in the desktop vs. mobile environments, I discovered that a mobile touch natively fires both events instantly (both within zero milliseconds), in contrast to the small desktop-delay of a few dozen milliseconds, depending on the user's trigger-happiness.
;(function(){
let
hover_on_mobile = {
timer: 0,
// I don't trust the timer with this,
// so I'm counting myself:
milliseconds: 0,
// also cover the case of the user
// mouseentering, reading or otherwise
// waiting, and clicking *then*.
is_counting: false,
},
item = document.querySelector('.mobile-hoverable')
;
hover_on_mobile.reset = function(){
clearInterval(hover_on_mobile.timer);
hover_on_mobile.milliseconds = 0;
hover_on_mobile.is_counting = false;
};
// hover.
item.onmouseenter = function(){
// preparation for onclick's touch-click detection.
hover_on_mobile.is_counting = true;
// count the milliseconds starting on each
// mouseenter anew.
hover_on_mobile.timer = window.setInterval(function() {
// we only need the first few milliseconds for
// our touch-click detection.
if (hover_on_mobile.milliseconds > 50) {
hover_on_mobile.reset();
} else {
hover_on_mobile.milliseconds++;
}
}, 1);
hover_behavior();
};
// click.
item.onclick = function(ev){
let
condition1 = hover_on_mobile.milliseconds < 10,
condition2 = hover_on_mobile.is_counting
;
console.log('clicked', {
condition1: condition1,
condition2: condition2,
timer: hover_on_mobile.timer,
milliseconds: hover_on_mobile.milliseconds,
is_counting: hover_on_mobile.is_counting,
});
// touch-click detection.
if (condition1 && condition2) {
// don't do anything; let the onmouseenter
// do the hover routine unhinderedly.
//
// if this was an onclick event on an ‹a› tag,
// the ev.preventDefault(); call would go here.
} else {
click_behavior();
}
hover_on_mobile.reset();
};
// ----------------------------------------
// fiddle-specfic.
// reset indicator, not hover_on_mobile.
item.onmouseout = reset_indicator;
function click_behavior() {
document.querySelector('#indicator .click-text').innerText = 'clicked';
}
function hover_behavior() {
document.querySelector('#indicator .hover-text').innerText = 'hovered';
}
function reset_indicator() {
document.querySelector('#indicator .hover-text').innerText = '-';
document.querySelector('#indicator .click-text').innerText = '-';
}
document.querySelector('#indicator .reset').onclick = reset_indicator;
})();
h1 {
font-size: 20px;
line-height: 26px;
}
#indicator {
margin-top: 15px;
padding: 20px;
background-color: #ffffd;
}
.mobile-hoverable {
cursor: pointer;
background-color: antiquewhite;
border: 1px outset blanchedalmond;
border-radius: 4px;
padding: 10px;
}
.notes {
font-style: italic;
font-size: 14px;
}
Imagine you wanted mobile users to click once in order to simulate a desktop-hover and twice for a desktop-click
Hover me, click me, compare with mobile-touch device mode.
-
-
- Don't forget to reload the page after changing the mode, for optimal testing evaluation.
- Click event console.logs hover_on_mobile object.
- The fiddle's CSS is irrelevant for this feature.
- Relevant JavaScript is bundled together; irrelevant JavaScript at the end.
- Didn't test browser compatibility specifically for this fiddle but the feature works in Chrome, Firefox, Safari, IE10+.
- Subsequent clicks without onmouseout will only fire the click event, in both environments.
(… or alternatively as a fiddle)
Here is another fiddle to showcase specifically the timing difference between desktop and mobile environments.