views:

810

answers:

1

I have a small div above (hover) a big one.
I assign onmouseover and onmouseout events to the wrapper div.
For image caption roll-over animation.

The problem is when the mouse is above the caption itself, causing an unwanted result(probably event bubbling).

And another problem: sometimes when you move mouse from outside to container you get a a triple sequence: (it should be just 2):
-I am over- -I am out- -I am over-

How to make it work? (no jquery)
must work on all browsers.

Demo

I have added firebug console log, to a better debugging.

UPDATE:
I've added this (not in the online demo) in RollOverDescription:

if (!eventHandle) var eventHandle = window.event;               
var srcEle = eventHandle.srcElement.id;             
if(srcEle=="imageDescription" ){
    return;
}

But it doesn't help.

A: 

This article on quirksmode ( near the bottom ) has an explanation of what you are experiencing and a script that might help you. There is a lot of cross browser info regarding mouse events too

OK, here's some working code. I don't promise this is the most efficient or that it won't cause memory leaks in IE (or that it works in IE - please let me know ). This is why people use libraries, much safer and easier.

// a general purpose, cross browser event adder
// returns a function that if run removes the event
function addEvent( el, eventType, handler, capturing ) {
    if( el.addEventListener ) {
        el.addEventListener( eventType, handler, capturing || false );
        var removeEvent = function() { el.removeEventListener( eventType, handler, capturing || false ) };
    } else if( el.attachEvent ) {
        var fn = function() {
            handler.call( el, normalise( window.event ) );
        };
        el.attachEvent( 'on'+eventType, fn );
        var removeEvent = function(){ el.detachEvent( 'on'+eventType, fn ) };
    }
    function normalise( e ) {
        e.target = e.srcElement;
        e.relatedTarget = e.toElement;

        e.preventDefault = function(){ e.returnValue = false };
        e.stopPropagation = function(){ e.cancelBubble = true };
        return e;
    };
    return removeEvent;
};



// adds mouseover and mouseout event handlers to a dom element
// mouseover and out events on child elements are ignored by this element
// returns a function that when run removes the events
// you need to send in both handlers - an empty function will do
function addMouseOverOutEvents( element, overHandler, outHandler ) {

    function out( e ) {
        var fromEl = e.target;
        var toEl = e.relatedTarget;
        // if the mouseout didn't originate at our element we can ignore it
        if( fromEl != element ) return;
        // if the element we rolled onto is a child of our element we can ignore it
        while( toEl  ) {
            toEl = toEl.parentNode;
            if( toEl == element ) return;
        }
        outHandler.call( element, e );
    }

    function over( e ) {
        var toEl = e.target;
        var fromEl = e.relatedTarget;
        // if the mouseover didn't originate at our element we can ignore it
        if( toEl != element ) return;
        // if the element we rolled from is a child of our element we can ignore it
        while( fromEl  ) {
            fromEl = fromEl.parentNode;
            if( fromEl == element ) return;
        }
        overHandler.call( element, e );
    }

    var killers = [];
    killers.push( addEvent( element, 'mouseover', over ) );
    killers.push( addEvent( element, 'mouseout', out ) );
    return function() {
        killers[0]();
        killers[1]();
    }
}

Example of use:

// add the events
var remover = addMouseOverOutEvents(
    document.getElementById( 'elementId' ),
    function( e ) {
        this.style.background = 'red';
        console.log( 'rolled in: '+e.target.id );
    },
    function( e ) {
        this.style.background = 'blue'
        console.log( 'rolled out: '+e.target.id );
    }    
);

//remove the events
remover();
meouw
I've read this article already, but I still can't understand how to use it in my scenario? Do i have to check where mouse came from and came to? Do I need to check this inside RollOverDescription function?
luppi
yes, if you capture a mouseout event you check if the relatedTarget i.e the element that you have rolled onto, is a child of your element and if it is you do nothing. You can do this for the mouseover event too but it doesn't matter as much. I'll write an example if you can wait a small while
meouw
i can wait, thanks
luppi
see my update please
luppi
WOW! so much just for mouse over/out events? Maybe there is a simple workaround for my scenario?
luppi
Well I guess if you don't want to use a library, you could position a transparent div over your image and description and listen for the mouse events on that
meouw
And if I set the events on the img instead of the imageContainer?
luppi