Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

What would be the best way to implement a mouseenter/mouseleave like event in Javascript without jQuery? What's the best strategy for cross browser use? I'm thinking some kind of checking on the event.relatedTarget/event.toElement property in the mouseover/mouseout event handlers?

Like to hear your thoughts.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
227 views
Welcome To Ask or Share your Answers For Others

1 Answer

(Totally changed my terrible answer. Let's try again.)

Let's assume you have the following base, cross-browser event methods:

var addEvent = window.addEventListener ? function (elem, type, method) {
        elem.addEventListener(type, method, false);
    } : function (elem, type, method) {
        elem.attachEvent('on' + type, method);
    };

var removeEvent = window.removeEventListener ? function (elem, type, method) {
        elem.removeEventListener(type, method, false);
    } : function (elem, type, method) {
        elem.detachEvent('on' + type, method);
    };

(Pretty simple, I know.)

Whenever you implement mouseenter/mouseleave, you just attach events to the normal mouseover/mouseout events, but then check for two important particulars:

  1. The event's target is the right element (or a child of the right element)
  2. The event's relatedTarget is not a child of the target

So we also need a function that checks whether one element is a child of another:

function contains(container, maybe) {
    return container.contains ? container.contains(maybe) :
        !!(container.compareDocumentPosition(maybe) & 16);
}

The last "gotcha" is how we would remove the event listener. The quickest way to implement it is by just returning the new function that we're adding.

So we end up with something like this:

function mouseEnterLeave(elem, type, method) {
    var mouseEnter = type === 'mouseenter',
        ie = mouseEnter ? 'fromElement' : 'toElement',
        method2 = function (e) {
            e = e || window.event;
            var target = e.target || e.srcElement,
                related = e.relatedTarget || e[ie];
            if ((elem === target || contains(elem, target)) &&
                !contains(elem, related)) {
                    method();
            }
        };
    type = mouseEnter ? 'mouseover' : 'mouseout';
    addEvent(elem, type, method2);
    return method2;
}

Adding a mouseenter event would look like this:

var div = document.getElementById('someID'),
    listener = function () {
        alert('do whatever');
    };

mouseEnterLeave(div, 'mouseenter', listener);

In order to remove the event, you'd have to do something like this:

var newListener = mouseEnterLeave(div, 'mouseenter', listener);

// removing...
removeEvent(div, 'mouseover', newListener);

It's hardly ideal, but all that's left is just implementation details. The important part was the if clause: mouseenter/mouseleave is just mouseover/mouseout, but checking if you're targeting the right element, and if the related target is a child of the target.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...