Opened 8 years ago

Closed 8 years ago

Last modified 8 years ago

#13849 closed defect (fixed)

delegation for mouse.enter doesn't work

Reported by: bill Owned by: Kris Zyp
Priority: high Milestone: 1.7
Component: Events Version: 1.6.1
Keywords: Cc:
Blocked By: Blocking:

Description

The documentation lists an example:

define(["dojo/on", "dojo/mouse"], function(on, mouse){
  on(node, on.selector(".myClass", mouse.enter), myClassHoverHandler);
});

That's not working for me (will attach test case). The problem seems to be in the mouse.js code, in the test:

if(!dom.isDescendant(evt.relatedTarget, node))

node here is the node specified in the on() call above, rather than the .myClass node. Thus dom.isDescendant() returns true.

Attachments (1)

selector.html (972 bytes) - added by bill 8 years ago.
test file, console.log() should print when mouse over gray borders

Download all attachments as: .zip

Change History (12)

Changed 8 years ago by bill

Attachment: selector.html added

test file, console.log() should print when mouse over gray borders

comment:1 Changed 8 years ago by bill

In attached test case, console.log() should fire when mousing over the gray border, but not when mousing over the numbers inside the gray border. It's not printing anything for me on IE8 or FF5/mac.

comment:2 Changed 8 years ago by bill

Summary: descendant selector using mouse.enter brokendelegation for mouse.enter doesn't work

comment:3 Changed 8 years ago by Kris Zyp

The mouseenter/mouseleave events don't bubble, and therefore are not compatible with event delegation. This is documentation bug (the example), and should be fixed.

comment:4 Changed 8 years ago by bill

Hmm, that's disappointing, I thought you could trivially make it work by changing mouse.js so

if(!dom.isDescendant(evt.relatedTarget, node)){

becomes

if(!dom.isDescendant(evt.relatedTarget, evt.target)){

or something like that.

If you can't use on.selector() for mouse.enter/mouse.leave it seems like you can't use it for anything, but maybe I'm misunderstanding. Anyway I'm looking forward to see your updated documentation example about when to use on.selector().

comment:5 Changed 8 years ago by Kris Zyp

If that change will fix it, I would be glad to give to do it. I'll give it a try.

comment:6 Changed 8 years ago by bill

Of course, that would mean dropping the IE specific code that connects to mouseenter/mouseleave, rather than mouseover/mouseout.

comment:7 Changed 8 years ago by Kris Zyp

I think I see what you are doing, but the purpose of mouse.enter and mouse.leave is to emulate the mouseenter/mouseleave which is a non-bubbling (and descending-only) version of mouseover/mouseout. Your fix makes the event descending-only, but does follow the non-bubbling behavior of mouseenter/mouseleave. How do use mouse.enter/leave to get only mouse entering and leaving on a specific target? For example, with your test case if I do:

on(dom.byId("table"), mouse.enter, ...

Based on the "mouseenter" behavior I would expect that to only fire an event when you hover over the table, not when any of the td's are hovered, but it fires for every element being hovered (in descendant fashion).

I suppose we could create our own event that is descending-only but bubbling, maybe mouse.into and mouse.outof. Or maybe we could have the extension type detect that it is being used in delegation and switch to bubbling for that case. Not sure...

comment:8 Changed 8 years ago by bill

I agree that new custom events would solve the issue, as they would allow apps to do both:

on(table, mouse.enter, myClassHoverHandler);

and

on(table, on.selector("td", mouse.in), myClassHoverHandler);

Ideally, to reduce API surface area, mouse.enter would work in both cases above. You could possibly achieve that by either:

a) Pass in a third flag to the mouse.enter "constructor" indicating whether or not it was wrapped in an on.selector()

b) Have a bubbling: false flag inside mouse.enter. If dojo/on sees that flag then it treats

on(table, mouse.enter, myClassHoverHandler);

to be something like:

on(table, on.selector(function(evt){ return evt.target == table},
      mouse.enter), myClassHoverHandler);

(It probably wouldn't actually call on.selector(), but would be similar code.)

comment:9 Changed 8 years ago by Kris Zyp

Resolution: fixed
Status: newclosed

In [26515]:

Add option for only selecting exact matches of selector and add bubbling form of mouse.enter/leave, fixes #13849 !strict

comment:10 Changed 8 years ago by Kenneth G. Franqueiro

In [26522]:

De-lint mouse.js, refs #13849 !strict - mixed spaces/tabs, now-unused variables, var declared then function w/ same name defined.

comment:11 Changed 8 years ago by bill

Milestone: tbd1.7
Note: See TracTickets for help on using tickets.