.drag() and mousemove event propagation

1,214 views
Skip to first unread message

Mark Longair

unread,
Jul 9, 2011, 2:10:13 PM7/9/11
to Raphaël Mailing List
I have a confusing problem, which I've tried asking about on
Stack Overflow [1] (suspecting it was just a misunderstanding of
mine about Javascript's event model) but since I've had no
replies, perhaps this is something Raphaël-specific that it
would be better to ask about here.

I am trying to debug an event handling bug in a complicated web
application, but the effect I'm seeing can be reproduced by this
simple example (based one of the Raphaël examples):

https://gist.github.com/965efd95d3b5fffe9f23

That version works as expected — you can drag the red circle
around — but uncommenting the e.stopPropagation() line breaks
dragging. If you have Firebug or Chrome and uncomment the
console.log lines, you can see that the move function is
never called - somehow the mousemove handler for the body
element is being called before the event gets to the circle's
handler.

I don't understand how this can be, since the mousemove
handler on the body element is set in the bubble phase of
event handling. If I understand the order in which events are
processed, as explained here:

http://www.quirksmode.org/js/events_order.html

... the order in which mousemove handlers would be called here
is approximately:

1. the body element's mousemove in the capture phase (null)

2. the svg element's mousemove in the capture phase (null)

3. the circle's mousemove in the capture phase (null)

4. the circle's mousemove in the bubble phase (set by Raphaël
when dragging starts, and which calls the move function)

5. the svg element's mousemove in the bubble phase (null)

6. the body element's mousemove in the bubble phase (set in
the example code, and which stops propagation)

If that's right, I don't understand how stopping propagation of
the event in the mousemove handler of body in the bubble phase
could break dragging, since it should happen *after* the circle
has already dealt with the event.

It would be great if someone could explain what's going on in
this example - have I misunderstood something about the event
model or does Raphaël implement drag() in a surprising way?

Many thanks for any help,
Mark

[1] http://stackoverflow.com/q/6617548/223092

Dmitry Baranovskiy

unread,
Jul 9, 2011, 7:04:12 PM7/9/11
to raph...@googlegroups.com
Circle doesn’t deal with move event. Move attached to the body, as well as up event. Circle only listening for down event.

Han

unread,
Jul 10, 2011, 3:47:42 PM7/10/11
to Raphaël
For drag and drop, you never attach the mousemove and mouseup handlers
to the element being dragged, you always attach it to the document
(which is a parent of the body, hence why the event bubbles to it
after the body).

The reason is, what if the mouse moves too quickly or leaves the area
the circle can be, and so is no longer over the circle? Then the
element being dragged no longer gets mousemove or mouseup events, and
just stays there until you mousemove over it again. If you're like me,
if you're dragging something and it suddenly stops moving, what do you
think happened to it? You think you accidentally dropped it. So you
let go of the mouse--you mouseup, but the event isn't handled by the
element being dragged--and then you move your mouse back over the
element being dragged, only to find to your surprise (and chagrin, if
you've seen this before and know what mistake the developer made),
that before you even mousedown to start dragging, as soon as you
mouseover the element it starts following your mouse again. Why?
Because the mouseup handler that unbinds the mousemove handler was on
the element, and you let go of the mouse outside the element when it
stopped moving.

To illustrate, play around with dragging these things outside the
iframe and back: http://jsfiddle.net/vznJs/

Han

Mark Longair

unread,
Jul 10, 2011, 5:29:33 PM7/10/11
to raph...@googlegroups.com
Thank-you to both Dmitry and Han for your helpful replies - that
clears up everything. My reading of the code in Raphaël was
completely wrong, but in any case it's good to hear an
explanation of why dragging has to be implemented like that.

regards,
mark

Reply all
Reply to author
Forward
0 new messages