/ Published in: JavaScript
since the script observes mouseout, it should fire mouseleave events before mouseenter to preserve correct order.
Expand |
Embed | Plain Text
Copy this code and paste it in your HTML
(function(){ function firstCommonAncestor(elm1, elm2){ var p = elm1.up(); while( !elm2.descendantOf(p) ){ p = p.up(); } return p; } function stopEvent(e){ try{ e.stop(); }catch(ex){} } Event.observe(document, 'mouseout', function(e){ var from = e.element(); var to = e.relatedTarget; p = null; if ( !to || (from !== to && !to.descendantOf(from))) { /* mouseleave should bubble up until the to element because we have left all elements up to that one */ var stopOn = null; if( to ){ if( from.descendantOf(to) ){ stopOn = to.childElements(); }else{ p = firstCommonAncestor(from, to); if( p && to.descendantOf(p) ){ stopOn = p.childElements(); } } } if( stopOn ){ stopOn.invoke('observe', 'custom:mouseleave', stopEvent); } from.fire('custom:mouseleave'); if( stopOn ){ stopOn.invoke('stopObserving', 'custom:mouseleave', stopEvent); } } var p = null; if( to && !from.descendantOf(to)){ /* mouseenter can bubble, no problem! */ var stopOn = null; if( to.descendantOf(from)){ stopOn = from.childElements(); }else{ // do first common ancestor's children, see below. p = firstCommonAncestor(to, from); stopOn = p.childElements(); } if( stopOn ){ stopOn.invoke('observe', 'custom:mouseenter', stopEvent); } to.fire('custom:mouseenter'); if( stopOn ){ stopOn.invoke('stopObserving', 'custom:mouseenter', stopEvent); } } }); })();