javascript - Flera mouseout-händelser utlösta


Jag är medveten om de olika händelsemodellerna i JavaScript (WC3-modellen kontra Microsoft-modellen), samt skillnaden mellan bubbling och capturing. Men efter några timmar av att ha läst olika artiklar om detta ämne, är jag fortfarande osäker på hur jag korrekt ska koda följande till synes enkla beteende:

Om jag har en yttre div och en inre div-element, vill jag att ett enda mouse-out-event ska utlösas när musen lämnar den yttre div:en. När musen korsar från den inre div:en till den yttre div:en ska ingenting hända, och när musen korsar från den yttre div:en till den inre div:en ska ingenting hända. Eventet ska endast utlösas om musen rör sig från den yttre div:en till den omgivande sidan.

<div id="outer" style = "width:20em; height:20em; border:1px solid #F00" align = "center" onmouseout="alert('mouseout event!')" >
<div id="inner" style = "width:18em; height:18em; border:1px solid #000"></div>
</div>

Nu, om jag placerar mouseout-händelsen på ytterdiven, utlöses två mouseout-händelser när musen rör sig från innerdiven till den omgivande sidan, eftersom händelsen utlöses en gång när musen rör sig från inner till ytter, och sedan igen när den rör sig från ytter till den omgivande sidan.

Jag vet att jag kan avbryta händelsen med ev.stopPropagation(), så jag försökte registrera en händelsehanterare med inner-diven för att avbryta händelsens propagation. Detta kommer dock inte att förhindra att händelsen utlöses när musen flyttas från outer-diven till inner-diven.

Så, om jag inte missar något, verkar det för mig som att detta beteende inte kan åstadkommas utan komplexa musspårningsfunktioner. I framtiden planerar jag att implementera om mycket av denna kod med ett mer avancerat ramverk, som jQuery, men just nu undrar jag om det finns ett enkelt sätt att implementera ovanstående beteende i vanlig JavaScript.

Svar #1

Händelsen mouseout på den inre div:en ”bubblar” upp till den yttre div:en. För att upptäcka att detta har hänt från den yttre div:en, kontrollera target-egenskapen hos event:

<div id="outer">
    <div id="inner">x</div>
</div>
document.getElementById('outer').onmouseout= function(event) {
    // deal with IE nonsense
    if (event===undefined) event= window.event;
    var target= 'target' in event? event.target : event.srcElement;

    if (target!==this) return;
    ...
};

Det vanliga problemet med mouseout är att du får det när pekaren rör sig "ut" ur föräldern även om den bara rör sig "in" i barnet. Du kan upptäcka detta fall manuellt genom att titta upp släktlistan för det element som musen rör sig in i:

    var other= 'relatedTarget' in event? event.relatedTarget : event.toElement;
    while ((other= other.parentNode).nodeType===1)
        if (other===this) return;

Detta är mousein/mouseout-modellen: den är bara intresserad av vilket element som är musens omedelbara förälder. Vad du oftare vill ha är mouseenter/mouseleave-modellen, som betraktar elementträd som en helhet, så du skulle bara få mouseleave när pekaren lämnade elementet eller dess underordnade element och inte rörde sig direkt in i elementet eller dess underordnade element.

Tyvärr är mouseenter/mouseleave för närvarande ett enbart IE-evenemangspar. Förhoppningsvis kommer andra webbläsare att ta upp det eftersom det förväntas vara en del av DOM Level 3 Events.