Thanks Beverley. That's kind of sucky though and seems to confirm what the emulator was doing. What I'm seeing there is that when you click (which again is supposed to emulate a tap), the element's mouseover event fires. But what's not so great about it is that when you remove the mouse either by dragging it away or just releasing it, the mouseout event doesn't fire. That doesn't happen unless or until you tap somewhere outside the element.
In the past I just thought touch devices ignored mouseover/out. Now it seems they fire them in ways that are at least potentially counter to what one might expect.
So now I'm thinking I either need to detect touch and not assign any potentially confusing mouseover events for those devices, or I need to find a way to fire the mouseout sequence of events at the appropriate time even if the touch device doesn't fire them in the way a mouse device would.
BTW - The bit about mouseenter is a bit of a red herring. It's simply mouseover in jQuery with a few extras added*. So, first of all one wouldn't expect it to fire at all on any device unless the page loaded had jQuery, though I'm sure some browsers might fire it that way. Those would be in the minority I would think. But if the page has jQuery on it, any firing of mouseover that isn't merely the result of propagation, should and probably will fire the jQuery mouseenter IF it's assigned to the element.
For now, I'm going with this for touch/mouse detection as virtually all browsers are now touch capable whether the device using them is or not:
Code:
jQuery(function($) { // determine upon first interaction if touch or mouse is used (not perfect, but better than any other method I'm currently aware of)
var $body = $('body'); // 'fails' if both mouse and touch are available and the non-preferred method is employed by the user first, or if they always use both about evenly
var detectMouse = function(e){ // but since this isn't critical we can let that go for those few individuals
fadeSlideShow.prototype.mouseortouch = e.type;
$body.off('mousedown touchstart', detectMouse);
}
$body.on('mousedown touchstart', detectMouse);
});
Since that, I'm now trying out capturing the touchstart event on the element itself. It will in most cases fire before the pseudo mouseover event it generates. I can use the touchstart event to set a timer window during which the undesirable parts of mouseover in a touch situation will not happen, example:
Code:
$nav.css({opacity: eb.navfade}).on('touchstart mouseenter', function(e){
$nav.stop(true, true).animate({opacity: eb.navfade});
if(e.type === 'touchstart'){ // prevent potentially counterintuitive opacity changes on touch enabled devices
clearTimeout(eb.cancelopchangetimer);
eb.cancelopchange = true;
eb.cancelopchangetimer = setTimeout(function(){eb.cancelopchange = false;}, 600);
}
if(!eb.cancelopchange){ // if this is not a touch enabled device firing on touchstart rather than true mouseover
$(this).stop(true, true).animate({opacity: 1});
}
})
This last has the advantage that, if the device has both mouse and touch, whichever is in use at the moment should determine the outcome.
*In javascript there's this big deal about if you mouseover something, it's mouseout event fires when you subsequently mouseover a child element, at least sometimes. And there are different ways to trap that and ignore it when you only want the one that fires when you actually leave the element and visa versa with mouseout events. These were normalized across browsers using jQuery mouseenter/leave. But none of that has taken into account the behavior of the mouseover/out events on touch devices. Apparently that is left to the coder for now. I'm sure some sort of normalization or cancellation routine will be available at some point. Either that or they (mouseover/out) will simply not be used due to attrition.
Bookmarks