Prototype custom event mouseenter mouseleave implementation


/ Published in: JavaScript
Save to your folder(s)

since the script observes mouseout, it should fire mouseleave events before mouseenter to preserve correct order.


Copy this code and paste it in your HTML
  1. (function(){
  2. function firstCommonAncestor(elm1, elm2){
  3. var p = elm1.up();
  4. while( !elm2.descendantOf(p) ){
  5. p = p.up();
  6. }
  7. return p;
  8. }
  9. function stopEvent(e){
  10. try{
  11. e.stop();
  12. }catch(ex){}
  13. }
  14. Event.observe(document, 'mouseout', function(e){
  15. var from = e.element();
  16. var to = e.relatedTarget;
  17. p = null;
  18. if ( !to || (from !== to && !to.descendantOf(from))) {
  19. /* mouseleave should bubble up until the to element because we have left all elements up to that one */
  20. var stopOn = null;
  21. if( to ){
  22. if( from.descendantOf(to) ){
  23. stopOn = to.childElements();
  24. }else{
  25. p = firstCommonAncestor(from, to);
  26. if( p && to.descendantOf(p) ){
  27. stopOn = p.childElements();
  28. }
  29. }
  30. }
  31. if( stopOn ){
  32. stopOn.invoke('observe', 'custom:mouseleave', stopEvent);
  33. }
  34. from.fire('custom:mouseleave');
  35. if( stopOn ){
  36. stopOn.invoke('stopObserving', 'custom:mouseleave', stopEvent);
  37. }
  38. }
  39. var p = null;
  40. if( to && !from.descendantOf(to)){
  41. /* mouseenter can bubble, no problem! */
  42. var stopOn = null;
  43. if( to.descendantOf(from)){
  44. stopOn = from.childElements();
  45. }else{
  46. // do first common ancestor's children, see below.
  47. p = firstCommonAncestor(to, from);
  48. stopOn = p.childElements();
  49. }
  50. if( stopOn ){
  51. stopOn.invoke('observe', 'custom:mouseenter', stopEvent);
  52. }
  53. to.fire('custom:mouseenter');
  54. if( stopOn ){
  55. stopOn.invoke('stopObserving', 'custom:mouseenter', stopEvent);
  56. }
  57. }
  58. });
  59. })();

Report this snippet


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.