From 9d7a981e4c434ee7ca5a1219ab5a150552c411d1 Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Sat, 28 Feb 2009 10:07:08 -0600 Subject: [PATCH] Add first-class support for `mouseenter` and `mouseleave` events in non-IE browsers (IE supports them natively). [#350 state:resolved] (Nick Stakenburg, Andrew Dupont) --- CHANGELOG | 2 ++ src/dom/event.js | 55 +++++++++++++++++++++++++++++++------- test/functional/event.html | 19 +++++++++++++ 3 files changed, 66 insertions(+), 10 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index b2bfd82..8ae576b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,5 @@ +* Add first-class support for `mouseenter` and `mouseleave` events in non-IE browsers (IE supports them natively). [#350 state:resolved] (Nick Stakenburg, Andrew Dupont) + * Make sure `_extendedByPrototype`, `_countedByPrototype`, and `prototypeUID` node expandos are accessed with `typeof` to prevent errors in some environments. [#354 state:resolved] (Hilberty, kangax, Andrew Dupont) * Fix issue where Opera 9.x returns incorrect results on certain Selector queries with descendant combinators. [#395 state:resolved] (Arpan, fearphage, kangax, Andrew Dupont) diff --git a/src/dom/event.js b/src/dom/event.js index 0fa3fec..89b6bf1 100644 --- a/src/dom/event.js +++ b/src/dom/event.js @@ -286,11 +286,33 @@ handler.call(element, event); }; } else { - // Ordinary event. - responder = function(event) { - Event.extend(event, element); - handler.call(element, event); - }; + // Non-custom event. + if (!Prototype.Browser.IE && + (eventName === "mouseenter" || eventName === "mouseleave")) { + // If we're dealing with mouseenter or mouseleave in a non-IE browser, + // we create a custom responder that mimics their behavior within + // mouseover and mouseout. + if (eventName === "mouseenter" || eventName === "mouseleave") { + responder = function(event) { + Event.extend(event, element); + + var parent = event.relatedTarget; + while (parent && parent !== element) { + try { parent = parent.parentNode; } + catch(e) { parent = element; } + } + + if (parent === element) return; + + handler.call(element, event); + }; + } + } else { + responder = function(event) { + Event.extend(event, element); + handler.call(element, event); + }; + } } responder.handler = handler; @@ -317,7 +339,16 @@ // object when page is returned to via the back button using its bfcache. if (Prototype.Browser.WebKit) window.addEventListener('unload', Prototype.emptyFunction, false); - + + + var _getDOMEventName = Prototype.K; + + if (!Prototype.Browser.IE) { + _getDOMEventName = function(eventName) { + var translations = { mouseenter: "mouseover", mouseleave: "mouseout" }; + return eventName in translations ? translations[eventName] : eventName; + }; + } /** * Event.observe(element, eventName, handler) -> Element @@ -342,11 +373,13 @@ element.attachEvent("onfilterchange", responder); } } else { + var actualEventName = _getDOMEventName(eventName); + // Ordinary event. if (element.addEventListener) - element.addEventListener(eventName, responder, false); + element.addEventListener(actualEventName, responder, false); else - element.attachEvent("on" + eventName, responder); + element.attachEvent("on" + actualEventName, responder); } return element; @@ -396,6 +429,8 @@ var responder = responders.find( function(r) { return r.handler === handler; }); if (!responder) return element; + var actualEventName = _getDOMEventName(eventName); + if (eventName.include(':')) { // Custom event. if (element.removeEventListener) @@ -407,9 +442,9 @@ } else { // Ordinary event. if (element.removeEventListener) - element.removeEventListener(eventName, responder, false); + element.removeEventListener(actualEventName, responder, false); else - element.detachEvent('on' + eventName, responder); + element.detachEvent('on' + actualEventName, responder); } registry.set(eventName, responders.without(responder)); diff --git a/test/functional/event.html b/test/functional/event.html index 611d5e6..77c2a32 100644 --- a/test/functional/event.html +++ b/test/functional/event.html @@ -225,6 +225,25 @@ }) +

mouseenter test

+ + +

Add unload events