Page 1 of 2 12 LastLast
Results 1 to 10 of 18

Thread: Click/touch activates mouseover/jq mouseenter event?

  1. #1
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default Click/touch activates mouseover/jq mouseenter event?

    I'm usually the one who answers these type of questions. But I'm just starting to become aware of this as a potential issue and have only an emulator at the moment to test on, so it might just be an artifact of the emulator (Chrome Device Emulator).

    Here's the basic idea. You have an event that is activated on mouseover, more specifically in this case on a jQuery mouseenter event (which is basically just a regular mouseover event filtered through event propagation subroutines so as not to have numerous enter and leave events on a nested element or its children and to activate only when the specific element is entered.

    OK got that. Now I'm emulating an iPhone 6 in Landscape default mode under a Chrome browser under Win 7 on a laptop. If I click on the element, it's mouseover (jq mouseenter) event fires. Is this an artifact of the emulator? Or is this what actually what happens when you touch an element that has a mouseover event?
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  2. #2
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    OK, here's a very simple test page. The emulator will fire the alert on click, which is supposed to emulate a touch/tap event:

    Code:
    <!DOCTYPE html>
    <html>
    <head>
    <title>WTF?</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    
    </head>
    <body>
    <input id="wtf" type="button" value="WTF">
    <script type="text/javascript">
    document.getElementById('wtf').addEventListener('mouseover', function(){alert('wtf');}, false);
    </script>
    </body>
    </html>
    Do actual touch devices do that?
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  3. #3
    Join Date
    Jul 2008
    Location
    Derbyshire, UK
    Posts
    3,033
    Thanks
    25
    Thanked 599 Times in 575 Posts
    Blog Entries
    40

    Default

    I've done a quick test on iPhone 5S.

    These are the events that fire with a tap;
    Onclick
    Onmousedown
    Onmouseover
    Onmouseup

    This doesn't fire when tapped;
    Onmouseenter

    Give me a few hours I'll test on Android when I'm back in the office.

    Ps - I hit trouble with this while I've been making popups for my calendar (event management) script. I wanted to use mouseenter for the same reason (propagation) but decided to change to mouseover to get them working on touch.
    Focus on Function Web Design
    Fast Edit (A flat file, PHP web page editor & CMS. Small, FREE, no database!) | Fast Edit BE (Snippet Manager) (Web content editor for multiple editable regions!) | Fast Apps

  4. The Following User Says Thank You to Beverleyh For This Useful Post:

    jscheuer1 (03-04-2016)

  5. #4
    Join Date
    Jul 2008
    Location
    Derbyshire, UK
    Posts
    3,033
    Thanks
    25
    Thanked 599 Times in 575 Posts
    Blog Entries
    40

    Default

    Same for Android, except that onmouseenter *sometimes* fires if the event is on a focusable element.
    Focus on Function Web Design
    Fast Edit (A flat file, PHP web page editor & CMS. Small, FREE, no database!) | Fast Edit BE (Snippet Manager) (Web content editor for multiple editable regions!) | Fast Apps

  6. The Following User Says Thank You to Beverleyh For This Useful Post:

    jscheuer1 (03-04-2016)

  7. #5
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    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.
    Last edited by jscheuer1; 03-04-2016 at 09:57 PM. Reason: add bit about detection, later about management strategy
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  8. #6
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    Here's a simplified version of the best solution I think so far:

    Code:
    <!DOCTYPE html>
    <html>
    <head>
    <title>WTF? II - A Solution</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    
    </head>
    <body>
    <input id="wtf" type="button" value="WTF">
    <script type="text/javascript">
    var alertcancel, alertcanceltimer;
    function amitouchingormousing(e){
    	if(e.type === 'touchstart'){
    		clearTimeout(alertcanceltimer);
    		alertcancel = true;
    		alertcanceltimer = setTimeout(function(){alertcancel = false;}, 600);
    	}
    	if(!alertcancel){
    		alert('wtf');
    	}
    }
    document.getElementById('wtf').addEventListener('touchstart', amitouchingormousing, false);
    document.getElementById('wtf').addEventListener('mouseover', amitouchingormousing, false);
    </script>
    </body>
    </html>
    If a mouse moves over, we should get the alert. If a touchevent happens on the element (even though that fires a pseudo mouseover event), we should not. If a device has both a mouse and a touchscreen, the result should depend upon which input device is used.
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  9. #7
    Join Date
    Sep 2007
    Location
    The Netherlands
    Posts
    1,881
    Thanks
    49
    Thanked 266 Times in 258 Posts
    Blog Entries
    56

    Default

    Quote Originally Posted by jscheuer1 View Post
    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.
    Mobile devices are 'made' for touchscreen (tap) events, not for mouse events. So instead of trying to make mobile devices understand what an arbitrary mouse instruction is supposed to perform, I would prefer to distinguish between tap and mouse by mobile device / desktop detection.

  10. #8
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    Quote Originally Posted by molendijk View Post
    Mobile devices are 'made' for touchscreen (tap) events, not for mouse events. So instead of trying to make mobile devices understand what an arbitrary mouse instruction is supposed to perform, I would prefer to distinguish between tap and mouse by mobile device / desktop detection.
    If you read more carefully, I actually had already moved on from the earlier position of mine that you quote:

    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.
    No big deal, I admit this thread is confusing. And I will have a look at your linked resource. That said, for now I've solved my original problem - which was by the way that touch devices generally fire a mouseover event when a user taps, but fail to fire the mouseout event when they stop tapping, only to fire it, if at all, when the user taps outside the element.

    So in simpler terms, I wanted a way to either prevent this pseudo mouseover event from firing, or a way to know when it had and to clean up after it. I ended up with neither. I now let it happen, but detect if it was precipitated by a touchstart event, if so I set a timer that prevents what are now the undesired parts of the genuine mouseover effect until that timer expires (600 milliseconds) because it is possible the user tapping also has a mouse and might use it later on the same page prior to reloading. I believe the concept is called "input agnostic". Or maybe not. In any case I don't know if there is a mouse or not. I don't know if there is a touch device or not. And I don't need to. Response is determined by the event.type property of the first in whatever chain of events are triggered upon the element. Which I like, because, on the same device, it could be a touch event one minute, and a mouse or a keyboard event later. If the device is more limited, that's OK too. I don't need to know. See this post: http://www.dynamicdrive.com/forums/s...007#post317007 for a simplified example of my current approach to this issue as regards a mouseover event that I want to fire if a real mouse enters the element, but not if somebody just taps on it.

    Bottom line, in the grand old tradition of "sniffing is usually not the best approach", I just react to the event that happens.
    Last edited by jscheuer1; 03-06-2016 at 12:29 AM. Reason: add last line "Bottom line . . ."
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  11. #9
    Join Date
    Sep 2007
    Location
    The Netherlands
    Posts
    1,881
    Thanks
    49
    Thanked 266 Times in 258 Posts
    Blog Entries
    56

    Default

    What I ment was that we should restrain ourselves from invoking mouse events (except for 'click', maybe) in scripts that are supposed to (also) work on mobile devices. We should separate mobile devices from desktop as much as we can, because mobile devices may understand mouse instructions in an unpredictable way. For instance, the script in #6 does what it is supposed to do on a iPad (no alert), but behaves differently on Android (sometimes there's an alert, sometimes there's not).

    I agree that sniffing is not the best practice. Here's a script that doesn't rely on sniffing:
    Code:
    <!DOCTYPE html>
    <html>
    <head>
    <title>WTF? II - A Solution</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    </head>
    <body>
    <input id="wtf" type="button" value="WTF" >
    <script>
    function amitouchingormousing()
    {
    if ('ontouchstart' in window)alert('touching')
    else {if (!('ontouchstart' in window))alert('mousing')}
    }
    if ('ontouchstart' in window)document.getElementById('wtf').addEventListener('touchstart', amitouchingormousing, false);
    if (!('ontouchstart' in window))document.getElementById('wtf').addEventListener('mouseover', amitouchingormousing, false);
    </script>
    </body>
    </html>

  12. The Following User Says Thank You to molendijk For This Useful Post:

    jscheuer1 (03-06-2016)

  13. #10
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    Sorry Arie, that:

    Code:
    if ('ontouchstart' in window)
    is sniffing regardless of where/when you do it. It makes no difference if you establish that value on dom load and then use it whenever it might apply, or check it each time you might use it, because it will never change.

    I wish I had an Android simulator. However, for my application, I think an occasional slip up is OK. If it were something as annoying as an alert, it would not be. However, in this particular case, it's actually highlighting, which would appear slightly counter intuitive on some touch devices on some occasions. In my opinion, that's acceptable for still allowing it whenever a mouse is used. I could sniff android though and block for that, worth considering. Again, if I had one or an emulator to test on, I think I'd like to find another way. What I had read on Android said that it might not always work there, particularly in Firefox and Chrome, due to those browsers not always issuing a delay between touchstart and their pseudo mouse (in this case mouseover) event(s). What I read said this was if a meta tag:

    HTML Code:
    <meta name="viewport" content="user-scalable=no">
    or similar viewport meta tag when that and other content values was used. However, with such a simple test page, I imagine the browser might take it upon itself to consider it not scalable, if for some reason the programmers wrote that in. After all, who should need to scale such a simple page with only one standard button on it? I've seen programmers jump to far less tenable conclusions.

    In any case, the article I read seem to feel such behavior was likely to be phased out. That's a place I sometimes now take more liberties than in the past. Like, unless someone specifically requests it, I would NOT go out of my way to support IE.

    With, what I consider thorny, issues like these, I usually start out sniffing - then toy with just not using the feature, and finally (if I'm lucky) find a way to work with it without sniffing. With more basic features, things central to - say the activation of a menu, I long ago abandoned using mouseover/out. That's just asking for trouble. Speaking of menus, I did have one where even using click activation some one thing was acting weird on some touch devices. So I resorted to sniffing and a different pathway in those cases for that one thing. I actually forget the exact thing it was (it was many years ago). If I ever revisit that menu, knowing what I know now, I may attack the issue in a different manner.

    I wonder if using the opposite value meta tag might 'fix' Android, or at least make it more cooperative? If you'd be so kind:

    Code:
    <!DOCTYPE html>
    <html>
    <head>
    <title>WTF? III - A Solution</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="user-scalable=yes">
    <!-- The above META tag MIGHT 'fix' the occasional hiccup with this code in Android -->
    </head>
    <body>
    <input id="wtf" type="button" value="WTF">
    <script type="text/javascript">
    var alertcancel, alertcanceltimer;
    function amitouchingormousing(e){
    	if(e.type === 'touchstart'){
    		clearTimeout(alertcanceltimer);
    		alertcancel = true;
    		alertcanceltimer = setTimeout(function(){alertcancel = false;}, 600);
    	}
    	if(!alertcancel){
    		alert('wtf');
    	}
    }
    document.getElementById('wtf').addEventListener('touchstart', amitouchingormousing, false);
    document.getElementById('wtf').addEventListener('mouseover', amitouchingormousing, false);
    </script>
    </body>
    </html>
    Worth a shot. Thanks in advance.
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

Similar Threads

  1. Replies: 8
    Last Post: 03-28-2015, 03:03 AM
  2. adding on click event
    By noobie123 in forum Dynamic Drive scripts help
    Replies: 2
    Last Post: 10-09-2014, 01:09 PM
  3. dropdown box value activates a setCookie
    By motormichael12 in forum Other
    Replies: 10
    Last Post: 05-24-2014, 05:03 AM
  4. How to fire click event of an LI tag?
    By round in forum JavaScript
    Replies: 12
    Last Post: 01-16-2013, 01:59 PM
  5. The Mousepoint event - an alternative to the mouseover event
    By Page Notes in forum Submit a DHTML or CSS code
    Replies: 7
    Last Post: 09-06-2010, 07:44 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •