27

I was trying to answer an issue with custom drop down, but challenged by an inconsistent behavior in Chrome and Firefox.

DEMO: http://jsfiddle.net/fyeht/ [Added scroll event for more clarity]

See below image, The list items can be navigated using arrow keys.

To Reproduce the issue:

  1. Open console in Chrome (F12)
  2. Click on an item in the list (you would notice some events getting logged in the console)
  3. Use down arrow key to navigate to the next item in the list
  4. Finally, the issue is noticed when you reach the last item in the view and hitting down arrow would scroll. Check the log to see 'scroll', 'mouse enter' and 'mouse move' [check the new demo]

The issue is after reaching the end of items in view, it scrolls. Even though the mouse is untouched, it triggers mouseenter and mousemove events in Chrome. In FF, on scroll it triggers just the mouseenter which make sense.

enter image description here

Question(s):

  • Why is mousemove triggered when mouse is untouched?
  • Is this just browser inconsistency? Could not find documentation on events triggered when scrolling? (never knew it did)

Submitted a bug report: https://code.google.com/p/chromium/issues/detail?id=241476

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Selvakumar Arumugam
  • 79,297
  • 15
  • 120
  • 134
  • This is the question that I was trying to answer but failed in Chrome http://stackoverflow.com/a/16524715/297641 – Selvakumar Arumugam May 13 '13 at 20:05
  • If you move your mouse outside of the scrollable area, it does not trigger mousemove...seems as though Chrome thinks that mousemove should be triggered by either your mouse moving, or the page moving under your mouse. – Jeff May 16 '13 at 17:25
  • @jlbruno This is a control in which the user could navigate using both mouse and keyboard arrow keys. It wouldn't be nice to ask to mouse the mouse outside when using arrow keys. – Selvakumar Arumugam May 16 '13 at 17:32
  • @jlbruno _the page moving under your mouse._ <-- this seems to be the cause but I think it should not. – Selvakumar Arumugam May 16 '13 at 17:47
  • 1
    You might be able to code around the issue by saving the mouse coords the first time mousemove is triggered, and checking against those coords next time it's triggered. If they haven't changed, the mouse hasn't really moved. – Jeff May 16 '13 at 18:00
  • @jlbruno Thanks, I used to flag as a temporary work around. At this point, I am trying to see if this is a bug or a simple inconsistency which I need to fix using a workaround. – Selvakumar Arumugam May 16 '13 at 18:06
  • If you think it's a bug, log it here and I'm sure they'll let you know: http://www.chromium.org/for-testers/bug-reporting-guidelines My guess is it's just an inconsistency based on how they think it should be implemented, and not a bug. – Jeff May 16 '13 at 18:24
  • @jlbruno logged already :) https://code.google.com/p/chromium/issues/detail?id=241476 – Selvakumar Arumugam May 16 '13 at 18:40
  • It is not happening to me you probably need to change your mouse. – Mehdi Karamosly May 22 '13 at 19:07
  • @MehdiKaramosly Are you trying this in Chrome? Did you follow the steps in the OP. – Selvakumar Arumugam May 22 '13 at 19:09
  • @Vega Yes I am in Chrome, I followed all the steps, I only saw `scrol` and `keydown` no mouse events whatsoever, and `scrol` event is understandable because when dropdown box is scrolling down when changing items, so from my side there is nothing wrong. (I can not reproduce your issue) This is my Chrome version : `Version 26.0.1410.64 m` – Mehdi Karamosly May 22 '13 at 19:39
  • 1
    @Vega sorry I was enabling `emulate touch` in my browser, now I am able to reproduce your problem , this is only happening if the cursor is on the dropdown box control. – Mehdi Karamosly May 22 '13 at 19:45
  • @MehdiKaramosly I am using same version of Chrome and I can see it clearly. Couple of questions, **1.** Are you running this on Windows, because I am testing this on windows and don't know how it is on Mac. **2.** Is your mouse cursor is over the `UL` (red box) when you use keys to go to next item. – Selvakumar Arumugam May 22 '13 at 19:45
  • Is this a Chrome-only or a WebKit issue? Has anyone tested this on Safari? I agree it's inconsistent, at least. It would be interesting to see if mousemove is triggered when JS is used to slide an element beneath the cursor.. no time at the moment to create a fiddle, but feel free. – Noyo Jun 22 '13 at 10:10
  • This issue should shed some light on the origins of this behavior: https://bugs.webkit.org/show_bug.cgi?id=17052 – Noyo Jun 23 '13 at 15:35

4 Answers4

11

In your example, I see that both Chrome and FF are firing mouseenter DOM events whenever the mouse is left hovering over the <ul> and pressing the key down triggers the browser to scroll in order to bring the selected <li> into view.

However, only Chrome is additionally triggering mousemove events. One obvious difference already in the mouseenter event objects that the two throw is that for Chrome, MouseEvent.offsetX and MouseEvent.offsetY values are included, whereas in FF these properties are undefined. So, when that enter is triggered Chrome has already decided the mouse "has moved".

Since the MouseEvent.screenX and MouseEvent.screenY event context values do not change between scroll-triggered MouseEvent instances, one could perhaps distinguish between an "artificial" mouseenter / mousemove event and an "authentic" one by storing these values from prior events.

DOM Event Specification

The DOM Level 2 Event Specification for mousemove reads:

The mousemove event occurs when the pointing device is moved while it is over an element.

The Level 3 spec (working draft) is essentially the same:

A user agent must dispatch this event when a pointing device is moved while it is over an element.

Seems like it could down to whether one interprets "is moved" relatively or not.

Also, in the section of the Level 3 spec on mouse event order, it states that when a pointer is moved into an element, it triggers mouseover, mouseenter, and mousemove, in that order. Every case that is specified there always has those three together, so perhaps one might interpret it that if you are going to trigger the mouseenter event, you should also be triggering the mousemove event which corresponds to entering the element.

merv
  • 67,214
  • 13
  • 180
  • 245
  • _The mousemove event occurs when the pointing device is moved while it is over an element._ -> That is exactly my question. Why `mousemove` event is triggered when mouse is untouched. Check the updated post, which has the coordinates printed for verification. – Selvakumar Arumugam May 16 '13 at 17:46
  • 1
    @Vega Thanks, for the update. I already analyzed the event data myself, and that's how I took note of the `offsetX` and `offsetY` values in the Chrome events. My answer is trying to argue the possibility that the Chrome team could either be 1) considering the motion *relative* to the underlying motion of the element the pointer is over to be "motion" or 2) interpreting the sequencing section of the DOM Level 3 spec to require the firing of a **mousemove** immediately following a **mouseenter** event. That is, the spec might actually be ambiguous enough for this not to be a bug. – merv May 16 '13 at 21:08
  • 2
    Would this test be a clue: https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/LayoutTests/fast/events/frame-scroll-fake-mouse-move.html ? (See also overflow-scroll-...) It seems to be expressly checking for the mousemove (mouseover, really) event on scroll. (Possibly related: there's a comment that says "WebKit schedules a fake mouse move event as part of installing the WebView in a window. ...". The test has also been reported as flaky: https://bugs.webkit.org/show_bug.cgi?id=103043 . Not sure how much of this is useful info.) – Noyo Jun 22 '13 at 14:57
  • @Noyo, good find. That pretty much makes it clear that the behavior is "by design" and that the Chrome team is interpreting relative motion as "motion" proper. Thanks for pointing this out. – merv Jun 23 '13 at 01:51
  • Also this: https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/core/page/EventHandler.cpp&q=fakemousemove&sq=package:chromium&l=116&type=cs :/ – Noyo Jun 23 '13 at 14:32
  • And finally, the culprit (I suppose): https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/core/page/FrameView.cpp&sq=package:chromium&l=1619&type=cs&rcl=1371968058 – Noyo Jun 23 '13 at 14:43
  • I would suggest that those who want more direct information and possibly a change in behavior follow the issue at https://code.google.com/p/chromium/issues/detail?id=241476 and/or what seems to be the direct origin of this behavior: https://bugs.webkit.org/show_bug.cgi?id=17052 – Noyo Jun 23 '13 at 15:34
1

I really doubt there's a browser inconsistency here. You should create a mousemove event that prints out the x and y coordinate. You'll probably see that the mouse has indeed moved a little bit. If that's the case, try using the plugin hoverIntent to eliminate issues like this.

EDIT:

Using the up and down arrow keys, I'm now able to replicate the issue. Yeah, it sure looks like some kind of bug! I bet the mousemove coordinate delta is tiny. Maybe the cursor moves one or two pixels? I would say, to overcome this, add a check to the mousemove function that compares previous mousemove's x-y coordinates to the current mousemove's x-y coordinates. Determine if it's more than just a few pixels. If so, you know it's a real mousemove. If it's less, you can chalk that up as a chrome bug.

FURTHER EDIT:

It seems like you uncovered a bug where mousemove is being fired in chrome when it probably shouldn't be. There may be workarounds that you could figure out if you hack it enough. But the best solution might be just to avoid using mousemove in this situation. In general, mousemove is one of those expensive events that should be used only when you really need it.

Ringo
  • 5,097
  • 3
  • 31
  • 46
  • 1
    It's not clear in your question that one should actually use the arrow keys to replicate the bug. Only that one CAN use the arrow keys. Anyway, I see the problem now. Yeah, it sure looks like some kind of bug! I bet the mousemove coordinate delta is tiny. Maybe the cursor moves one or two pixels? I would say, to overcome this, add a check to the mousemove function that compares previous mousemove's x-y coordinates to the current mousemove's x-y coordinates. Determine if it's more than just a few pixels. If so, you know it's a real mousemove. If it's less, you can chalk that up as a chrome bug. – Ringo May 16 '13 at 01:39
  • Thanks.. The suggestion in the comment seems to be a valid workaround to consider. Updated the post with instruction to reproduce the issue. – Selvakumar Arumugam May 16 '13 at 18:10
  • makes me think you might consider avoiding mousemove altogether, at least in this context. do you really need it? the fact that you seemed to uncover this bug really shows how little practical use it has for standard web interactions. – Ringo May 17 '13 at 00:36
  • You have some good points and you should post them in the answer instead of hanging them in comments. Edit your answer and you will definitely get my vote. – Selvakumar Arumugam May 18 '13 at 03:40
  • ah, ok, i'll just copy and paste the comments into the answer, then. thanks for the tip. – Ringo May 18 '13 at 04:28
1

This is a nice demo. In Chrome mouse movement for elements is definitely relative. In chrome I can get keydown and scroll events only if the mouse pointer is over the scroll bar. I can also get scroll only events if i use the wheel to scroll and leave the mouse over the scroll bar. It is and isn't very odd that scroll by dragging causes "mouse move", and "mouse over" events.

Not only are mouse move and mouse over events produced in profusion by the browser they are not a very good indication of a users intent. Infact these events are a useful entropy source. To the degree that there are some minor differences this is in the context of how useful these "micro events" are individually. To work with them you must devise a way to filter them for user intention you want to link to higher level actions. Any reasonable method you choose to make sense of these events will probably detect these move - on scroll events as garbage. This is where your point is really worth noting and taking under consternation. A first stage would be to Filter out events based on the elements and values of coordinates. It might help to create a state machine model. You might register and registered handlers in response to other events. You've identified this case where you'd want to change responsive state if or reaction criteria if a key element has a scroll bar. IF an element or it's parent has a vertical scroll bar throw out mouse moves with relatively high X values.

You might want to also ignore mouse overs if it's fired with a mouse move in that context. It starts to become impractical to handle each of these micro event one at a time even if you are changing state by registering or deregistering handlers. More information can be extracted by creating an event sequence fifo buffer. Register event handlers to add a new event to the buffer. You might also want to collect information from timer events in this buffer to establish more context. You might create an object that keeps a fifo in an array. This would be like a queue but not in the sense of it being a place where the events are waiting to be processed. Instead your program is waiting to calculate patterns in the buffer and based on the patterns fire higher level events, accept or reject different types of events and extend, contract or save the contents of the buffer. You can then evaluate move events for changes in x and y and also create conditions given the patter of scroll mouse over and mouse move events you've demonstrated.

John Hall
  • 556
  • 1
  • 4
  • 10
1

This is not a bug. The mousemove is relative to element that the event is attached to. In your case, you see that your mouse is not moving because you took the browser window as the reference. But for that scrolling list, whenever the list is scrolled, the mouse pointing over some element of the list moved to over different element

Imagine that you as the Earth, a cup of coffee stand still on a table as the mouse, the scrollable list as the Sun : if you (window) don't move, the position of the cup of coffee (mouse) is at the same place for you; but for the Sun (list), it will see that the Earth and the cup of coffee are both moving.

Thanh Trung
  • 3,566
  • 3
  • 31
  • 42