Prevent onmouseout when hovering child element of the parent absolute div WITHOUT jQuery
Asked Answered
M

23

228

I am having trouble with the onmouseout function in an absolute positoned div. When the mouse hits a child element in the div, the mouseout event fires, but I do not want it to fire until the mouse is out of the parent, absolute div.

How can I prevent the mouseout event from firing when it hits a child element WITHOUT jquery.

I know this has something to do with event bubbling, but I am having no luck on finding out how to work this out.

I found a similar post here: How to disable mouseout events triggered by child elements?

However that solution uses jQuery.

Menarche answered 15/1, 2011 at 3:20 Comment(4)
I ended up solving the problem using a timeout and clearing it on hover of the child elementsMenarche
Hi, I have looked at your demo but when I go over the elements in the bottom right panel nothing happens?Menarche
Found this answer if you are looking to prevent a mouseout on the parent event when you mouseover a child element: javascript mouseover/mouseout.Sulfatize
Check out @Zach Saucier answer buried belowDelicatessen
W
102
function onMouseOut(event) {
        //this is the original element the event handler was assigned to
        var e = event.toElement || event.relatedTarget;
        if (e.parentNode == this || e == this) {
           return;
        }
    alert('MouseOut');
    // handle mouse event here!
}



document.getElementById('parent').addEventListener('mouseout',onMouseOut,true);

I made a quick JsFiddle demo, with all the CSS and HTML needed, check it out...

EDIT FIXED link for cross-browser support http://jsfiddle.net/RH3tA/9/

NOTE that this only checks the immediate parent, if the parent div had nested children then you have to somehow traverse through the elements parents looking for the "Orginal element"

EDIT example for nested children

EDIT Fixed for hopefully cross-browser

function makeMouseOutFn(elem){
    var list = traverseChildren(elem);
    return function onMouseOut(event) {
        var e = event.toElement || event.relatedTarget;
        if (!!~list.indexOf(e)) {
            return;
        }
        alert('MouseOut');
        // handle mouse event here!
    };
}

//using closure to cache all child elements
var parent = document.getElementById("parent");
parent.addEventListener('mouseout',makeMouseOutFn(parent),true);

//quick and dirty DFS children traversal, 
function traverseChildren(elem){
    var children = [];
    var q = [];
    q.push(elem);
    while (q.length > 0) {
      var elem = q.pop();
      children.push(elem);
      pushAll(elem.children);
    }
    function pushAll(elemArray){
      for(var i=0; i < elemArray.length; i++) {
        q.push(elemArray[i]);
      }
    }
    return children;
}

And a new JSFiddle, EDIT updated link

Wellwisher answered 15/1, 2011 at 5:47 Comment(11)
You should add a mouseout event to the fiddle so it can be tested. An alert or something should do.Menarche
Sorry looks like you have alert('MouseOut') , however it does not work for me? I have hit run with no JS library optionMenarche
Tested on safari and chrome, but should work on everything! what is your browser?Wellwisher
What if you have grand children? or great grand children? i.e. can you have a recursive solution instead of just immidiate children ?Marela
It works great. But please can you help me detatching it :-)? I've been trying for hours, but it keeps adding eventhandlers to my div.Eleanoreleanora
Here is an edited version for subchilds jsfiddle.net/RH3tA/622 you can add some conditions to add subchild levels (une condition per subchild level)Deduce
Some small change to avoid error when there is more than one cascade level of element. function OnMouseOut(event) { //this is the original element the event handler was assigned to var e = event.toElement || event.relatedTarget; while( e != null ) { if( e == this ) { return; } e = e.parentNode; } alert('MouseOut'); }Woolly
By the way if you were to create the child elements in Javascript by using innerHTML this wont work. They must be created using the createElement method - and before the event is added to the parent.Zina
This doesn't work. mouseleave is the correct answerShakeup
@itcouldevenbeaboat Both seem to work for me, though mouseleave only seems to work within the eventlistener (so html DOM or simply element.mouseleave = onMouseOut(); won't work)..Iconium
This is quite an old answer - nowadays you can use contains which makes it a much more elegant solution: function makeMouseOutFn(event) { e = event.toElement || event.relatedTarget; if (this.contains(e)) return; //handle mouse event here }Furthermost
G
186

Use onmouseleave.

Or, in jQuery, use mouseleave()

It is the exact thing you are looking for. Example:

<div class="outer" onmouseleave="yourFunction()">
    <div class="inner">
    </div>
</div>

or, in jQuery:

$(".outer").mouseleave(function(){
    //your code here
});

an example is here.

Grimace answered 7/6, 2015 at 18:37 Comment(4)
onMouseLeave is what I ended up using too as it does not bubble up.Totally
Saved me lots of time. thnxCochard
mouseleave can't be cancelable.Infallibilism
@grecdev, say more!Smoker
M
137

For a simpler pure CSS solution that works in most cases, one could remove children's pointer-events by setting them to none

.parent * {
     pointer-events: none;
}

Browser support: IE11+

Metasomatism answered 16/9, 2013 at 20:45 Comment(9)
Brilliant! Totally just fixed my issue!Dreiser
This should be the first or at least second answer, I was ready to go with the hassle of event listeners and this totally fixed my issue too. So simple !Brewster
This prevent mouseout from firing, but for me it also prevents the actual child from being clicked as a selection in the menu, which is the point of the menu.Gonzalez
@hellofunk That's why you'd apply the click event to the parent. The exact code needed varies depending on implementation, this answer just suggests using the pointer-events propertyMetasomatism
it works only if you do not have other controller elements (edit, delete) inside the area, because this solution blocks them too..Hospitality
Works like a charm :)Cummins
I have no words for this, it works perfectly and is so clean. Didn't know CSS would allow controlling eventsAssize
Super simple solution. Hats off to you.Thorbert
Best solution for Angular6+Nibelungenlied
W
102
function onMouseOut(event) {
        //this is the original element the event handler was assigned to
        var e = event.toElement || event.relatedTarget;
        if (e.parentNode == this || e == this) {
           return;
        }
    alert('MouseOut');
    // handle mouse event here!
}



document.getElementById('parent').addEventListener('mouseout',onMouseOut,true);

I made a quick JsFiddle demo, with all the CSS and HTML needed, check it out...

EDIT FIXED link for cross-browser support http://jsfiddle.net/RH3tA/9/

NOTE that this only checks the immediate parent, if the parent div had nested children then you have to somehow traverse through the elements parents looking for the "Orginal element"

EDIT example for nested children

EDIT Fixed for hopefully cross-browser

function makeMouseOutFn(elem){
    var list = traverseChildren(elem);
    return function onMouseOut(event) {
        var e = event.toElement || event.relatedTarget;
        if (!!~list.indexOf(e)) {
            return;
        }
        alert('MouseOut');
        // handle mouse event here!
    };
}

//using closure to cache all child elements
var parent = document.getElementById("parent");
parent.addEventListener('mouseout',makeMouseOutFn(parent),true);

//quick and dirty DFS children traversal, 
function traverseChildren(elem){
    var children = [];
    var q = [];
    q.push(elem);
    while (q.length > 0) {
      var elem = q.pop();
      children.push(elem);
      pushAll(elem.children);
    }
    function pushAll(elemArray){
      for(var i=0; i < elemArray.length; i++) {
        q.push(elemArray[i]);
      }
    }
    return children;
}

And a new JSFiddle, EDIT updated link

Wellwisher answered 15/1, 2011 at 5:47 Comment(11)
You should add a mouseout event to the fiddle so it can be tested. An alert or something should do.Menarche
Sorry looks like you have alert('MouseOut') , however it does not work for me? I have hit run with no JS library optionMenarche
Tested on safari and chrome, but should work on everything! what is your browser?Wellwisher
What if you have grand children? or great grand children? i.e. can you have a recursive solution instead of just immidiate children ?Marela
It works great. But please can you help me detatching it :-)? I've been trying for hours, but it keeps adding eventhandlers to my div.Eleanoreleanora
Here is an edited version for subchilds jsfiddle.net/RH3tA/622 you can add some conditions to add subchild levels (une condition per subchild level)Deduce
Some small change to avoid error when there is more than one cascade level of element. function OnMouseOut(event) { //this is the original element the event handler was assigned to var e = event.toElement || event.relatedTarget; while( e != null ) { if( e == this ) { return; } e = e.parentNode; } alert('MouseOut'); }Woolly
By the way if you were to create the child elements in Javascript by using innerHTML this wont work. They must be created using the createElement method - and before the event is added to the parent.Zina
This doesn't work. mouseleave is the correct answerShakeup
@itcouldevenbeaboat Both seem to work for me, though mouseleave only seems to work within the eventlistener (so html DOM or simply element.mouseleave = onMouseOut(); won't work)..Iconium
This is quite an old answer - nowadays you can use contains which makes it a much more elegant solution: function makeMouseOutFn(event) { e = event.toElement || event.relatedTarget; if (this.contains(e)) return; //handle mouse event here }Furthermost
M
35

instead of onmouseout use onmouseleave.

You haven't showed to us your specific code so I cannot show you on your specific example how to do it.

But it is very simple: just replace onmouseout with onmouseleave.

That's all :) So, simple :)

If not sure how to do it, see explanation on:

https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_onmousemove_leave_out

Peace of cake :) Enjoy it :)

Meteoroid answered 28/5, 2019 at 6:27 Comment(2)
This is a great shout, well worth checking out if you have a similar situationBangs
This worked for me perfectly! I have a div with two buttons, which will appear when hovering the parent. Thanks!Residentiary
I
29

Here's a more elegant solution based on what came below. it accounts for event bubbling up from more than one level of children. It also accounts for cross-browser issues.

function onMouseOut(this, event) {
//this is the original element the event handler was assigned to
   var e = event.toElement || event.relatedTarget;

//check for all children levels (checking from bottom up)
while(e && e.parentNode && e.parentNode != window) {
    if (e.parentNode == this||  e == this) {
        if(e.preventDefault) e.preventDefault();
        return false;
    }
    e = e.parentNode;
}

//Do something u need here
}

document.getElementById('parent').addEventListener('mouseout',onMouseOut,true);
Imhoff answered 30/10, 2012 at 14:24 Comment(4)
Sam Elie, this seems to not to be working on IE, Safari or Opera. Do you have a cross-browser version of this script? It works like a charm in Firefox and Chrome. Thanks.Faxon
When I paste the above function into my script, Dreamweaver and FF throw an error on the first line, "function onMouseOut(this, event) {". It looks like you're not allowed to put "this" as a parameter. I guess it kind of works when I leave out "this" from the input params, but I don't know for sure, because "I don't know what I don't know".Backsheesh
I also had the same issue pop up in Chrome on the same line, excluding this from the function definition line @GregoryLewis mentioned fixed the issue. Also for more cross browser support, try this: if (window.addEventListener){ document.getElementById('parent').addEventListener('mouseout',onMouseOut,true); } else if (window.attachEvent){ document.getElementById('parent').attachEvent("onmouseout",onMouseOut); }Higgs
Very handsome! Best answer if support for older browsers is required.Erdda
C
15

If you're using jQuery you can also use the "mouseleave" function, which deals with all of this for you.

$('#thetargetdiv').mouseenter(do_something);
$('#thetargetdiv').mouseleave(do_something_else);

do_something will fire when the mouse enters thetargetdiv or any of its children, do_something_else will only fire when the mouse leaves thetargetdiv and any of its children.

Cobos answered 6/5, 2014 at 23:33 Comment(0)
G
14

Thanks to Amjad Masad that inspired me.

I've the following solution which seems to work in IE9, FF and Chrome and the code is quite short (without the complex closure and transverse child things) :

    DIV.onmouseout=function(e){
        // check and loop relatedTarget.parentNode
        // ignore event triggered mouse overing any child element or leaving itself
        var obj=e.relatedTarget;
        while(obj!=null){
            if(obj==this){
                return;
            }
            obj=obj.parentNode;
        }
        // now perform the actual action you want to do only when mouse is leaving the DIV
    }
Golf answered 2/6, 2012 at 4:40 Comment(1)
This one's a winnerGasbag
B
7

I think Quirksmode has all the answers you need (different browsers bubbling behaviour and the mouseenter/mouseleave events), but I think the most common conclusion to that event bubbling mess is the use of a framework like JQuery or Mootools (which has the mouseenter and mouseleave events, which are exactly what you intuited would happen).

Have a look at how they do it, if you want, do it yourself
or you can create your custom "lean mean" version of Mootools with just the event part (and its dependencies).

Bumble answered 15/1, 2011 at 3:34 Comment(0)
V
7

Try mouseleave()

Example :

<div id="parent" mouseleave="function">
   <div id="child">

   </div>
</div>

;)

Validity answered 18/6, 2013 at 18:41 Comment(0)
C
5

I've found a very simple solution,

just use the onmouseleave="myfunc()" event than the onmousout="myfunc()" event

In my code it worked!!

Example:

<html>
<head>
<script type="text/javascript">
   function myFunc(){
      document.getElementById('hide_div').style.display = 'none';
   }
   function ShowFunc(){
      document.getElementById('hide_div').style.display = 'block';
   }
</script>
</head>
<body>
<div onmouseleave="myFunc()" style='border:double;width:50%;height:50%;position:absolute;top:25%;left:25%;'>
   Hover mouse here
   <div id='child_div' style='border:solid;width:25%;height:25%;position:absolute;top:10%;left:10%;'>
      CHILD <br/> It doesn't fires if you hover mouse over this child_div
   </div>
</div>
<div id="hide_div" >TEXT</div>
<a href='#' onclick="ShowFunc()">Show "TEXT"</a>
</body>
</html>

Same Example with mouseout function:

<html>
<head>
<script type="text/javascript">
   function myFunc(){
      document.getElementById('hide_div').style.display = 'none';
   }
   function ShowFunc(){
      document.getElementById('hide_div').style.display = 'block';
   }
</script>
</head>
<body>
<div onmouseout="myFunc()" style='border:double;width:50%;height:50%;position:absolute;top:25%;left:25%;'>
   Hover mouse here
   <div id='child_div' style='border:solid;width:25%;height:25%;position:absolute;top:10%;left:10%;'>
      CHILD <br/> It fires if you hover mouse over this child_div
   </div>
</div>
<div id="hide_div">TEXT</div>
<a href='#' onclick="ShowFunc()">Show "TEXT"</a>
</body>
</html>

Hope it helps :)

Cabe answered 26/12, 2012 at 13:3 Comment(0)
A
3

Although the solution you referred to uses jquery, mouseenter and mouseleave are native dom events, so you might use without jquery.

Attrahent answered 26/1, 2018 at 22:29 Comment(0)
V
2

There are two ways to handle this.

1) Check the event.target result in your callback to see if it matches your parent div

var g_ParentDiv;

function OnMouseOut(event) {
    if (event.target != g_ParentDiv) {
        return;
    }
    // handle mouse event here!
};


window.onload = function() {
    g_ParentDiv = document.getElementById("parentdiv");
    g_ParentDiv.onmouseout = OnMouseOut;
};

<div id="parentdiv">
    <img src="childimage.jpg" id="childimg" />
</div>

2) Or use event capturing and call event.stopPropagation in the callback function

var g_ParentDiv;

function OnMouseOut(event) {

    event.stopPropagation(); // don't let the event recurse into children

    // handle mouse event here!
};


window.onload = function() {
    g_ParentDiv = document.getElementById("parentdiv");
    g_ParentDiv.addEventListener("mouseout", OnMouseOut, true); // pass true to enable event capturing so parent gets event callback before children
};

<div id="parentdiv">
    <img src="childimage.jpg" id="childimg" />
</div>
Vaporetto answered 15/1, 2011 at 4:10 Comment(4)
How can I make this work for onmouseout instead of onmouseover?Menarche
Oops. My bad. I just change all the "mouseover" references to "mouseout" in the code above. That should do it for you.Vaporetto
For the first method, the event.target always matches the parent element when the mouse goes over the child element, so it does not workMenarche
Same thing occurs for the second method. When the mouse enters a child element it still triggers the eventMenarche
C
2

simply we can check e.relatedTarget has child class and if true return the function.

    if ($(e.relatedTarget).hasClass("ctrl-btn")){
        return;
    }

this is code worked for me, i used for html5 video play,pause button toggle hover video element

element.on("mouseover mouseout", function(e) {

    if(e.type === "mouseout"){

        if ($(e.relatedTarget).hasClass("child-class")){
            return;
        }

    }

});
Coheir answered 17/9, 2020 at 6:11 Comment(0)
B
1

I make it work like a charm with this:

function HideLayer(theEvent){
 var MyDiv=document.getElementById('MyDiv');
 if(MyDiv==(!theEvent?window.event:theEvent.target)){
  MyDiv.style.display='none';
 }
}

Ah, and MyDiv tag is like this:

<div id="MyDiv" onmouseout="JavaScript: HideLayer(event);">
 <!-- Here whatever divs, inputs, links, images, anything you want... -->
<div>

This way, when onmouseout goes to a child, grand-child, etc... the style.display='none' is not executed; but when onmouseout goes out of MyDiv it runs.

So no need to stop propagation, use timers, etc...

Thanks for examples, i could make this code from them.

Hope this helps someone.

Also can be improved like this:

function HideLayer(theLayer,theEvent){
 if(theLayer==(!theEvent?window.event:theEvent.target)){
  theLayer.style.display='none';
 }
}

And then the DIVs tags like this:

<div onmouseout="JavaScript: HideLayer(this,event);">
 <!-- Here whatever divs, inputs, links, images, anything you want... -->
<div>

So more general, not only for one div and no need to add id="..." on each layer.

Breakdown answered 28/3, 2012 at 11:17 Comment(0)
C
1

If you have access to the element which the event is attached to inside the mouseout method, you can use contains() to see if the event.relatedTarget is a child element or not.

As event.relatedTarget is the element to which the mouse has passed into, if it isn't a child element, you have moused out of the element.

div.onmouseout = function (event) {
    if (!div.contains(event.relatedTarget)) {
        // moused out of div
    }
}
Curch answered 14/5, 2017 at 14:52 Comment(0)
B
1

On Angular 5, 6 and 7

<div (mouseout)="onMouseOut($event)"
     (mouseenter)="onMouseEnter($event)"></div>

Then on

import {Component,Renderer2} from '@angular/core';
...
@Component({
 selector: 'app-test',
 templateUrl: './test.component.html',
 styleUrls: ['./test.component.scss']
})
export class TestComponent implements OnInit, OnDestroy {
...
 public targetElement: HTMLElement;

 constructor(private _renderer: Renderer2) {
 }

 ngOnInit(): void {
 }

 ngOnDestroy(): void {
  //Maybe reset the targetElement
 }

 public onMouseEnter(event): void {
  this.targetElement = event.target || event.srcElement;
  console.log('Mouse Enter', this.targetElement);
 }

 public onMouseOut(event): void {
  const elementRelated = event.toElement || event.relatedTarget;
  if (this.targetElement.contains(elementRelated)) {
    return;
  }
  console.log('Mouse Out');
 }
}
Babblement answered 12/12, 2018 at 16:15 Comment(0)
T
0

I check the original element's offset to get the page coordinates of the element's bounds, then make sure the mouseout action is only triggered when the mouseout is out of those bounds. Dirty but it works.

$(el).live('mouseout', function(event){
    while(checkPosition(this, event)){
        console.log("mouseovering including children")
    }
    console.log("moused out of the whole")
})

var checkPosition = function(el, event){
    var position = $(el).offset()
    var height = $(el).height()
    var width = $(el).width()
    if (event.pageY > position.top 
|| event.pageY < (position.top + height) 
|| event.pageX > position.left 
|| event.pageX < (position.left + width)){
    return true
}
}
Trilobite answered 25/1, 2012 at 15:8 Comment(0)
W
0
var elem = $('#some-id');
elem.mouseover(function () {
   // Some code here
}).mouseout(function (event) {
   var e = event.toElement || event.relatedTarget;
   if (elem.has(e).length > 0) return;

   // Some code here
});
Waterhouse answered 2/10, 2012 at 15:49 Comment(1)
Please give some explanation with your anwser.Whittaker
G
0

If you added (or have) a CSS class or id to the parent element, then you can do something like this:

<div id="parent">
  <div>
  </div>
</div>

JavaScript:
document.getElementById("parent").onmouseout = function(e) {
  e = e ? e : window.event //For IE
  if(e.target.id == "parent") {
    //Do your stuff
  }
}

So stuff only gets executed when the event is on the parent div.

Glossology answered 13/9, 2013 at 19:19 Comment(0)
D
0

I just wanted to share something with you.
I got some hard time with ng-mouseenter and ng-mouseleave events.

The case study:

I created a floating navigation menu which is toggle when the cursor is over an icon.
This menu was on top of each page.

  • To handle show/hide on the menu, I toggle a class.
    ng-class="{down: vm.isHover}"
  • To toggle vm.isHover, I use the ng mouse events.
    ng-mouseenter="vm.isHover = true"
    ng-mouseleave="vm.isHover = false"

For now, everything was fine and worked as expected.
The solution is clean and simple.

The incoming problem:

In a specific view, I have a list of elements.
I added an action panel when the cursor is over an element of the list.
I used the same code as above to handle the behavior.

The problem:

I figured out when my cursor is on the floating navigation menu and also on the top of an element, there is a conflict between each other.
The action panel showed up and the floating navigation was hide.

The thing is that even if the cursor is over the floating navigation menu, the list element ng-mouseenter is triggered.
It makes no sense to me, because I would expect an automatic break of the mouse propagation events.
I must say that I was disappointed and I spend some time to find out that problem.

First thoughts:

I tried to use these :

  • $event.stopPropagation()
  • $event.stopImmediatePropagation()

I combined a lot of ng pointer events (mousemove, mouveover, ...) but none help me.

CSS solution:

I found the solution with a simple css property that I use more and more:

pointer-events: none;

Basically, I use it like that (on my list elements):

ng-style="{'pointer-events': vm.isHover ? 'none' : ''}"

With this tricky one, the ng-mouse events will no longer be triggered and my floating navigation menu will no longer close himself when the cursor is over it and over an element from the list.

To go further:

As you may expect, this solution works but I don't like it.
We do not control our events and it is bad.
Plus, you must have an access to the vm.isHover scope to achieve that and it may not be possible or possible but dirty in some way or another.
I could make a fiddle if someone want to look.

Nevertheless, I don't have another solution...
It's a long story and I can't give you a potato so please forgive me my friend.
Anyway, pointer-events: none is life, so remember it.

Drier answered 1/5, 2017 at 21:48 Comment(0)
B
0

There are a simple way to make it work. The element and all childs you set a same class name, then:

element.onmouseover = function(event){
 if (event.target.className == "name"){
 /*code*/
 }
}
Bloodmobile answered 9/2, 2021 at 19:54 Comment(0)
A
0

Also for vanillajs you can use that way

document.querySelector('.product_items') && document.querySelector('.product_items').addEventListener('mouseleave', () => updateCart())


const updateCart = () => {
let total = 0;
document.querySelectorAll('input') && document.querySelectorAll('input').forEach(item => total += +item.value)
  document.getElementById('total').innerHTML = total
}
<div class="product_items">
  <div class="product_item">
    <div class="product_name">
    </div>
    <div class="multiply__btn">
      <button type="button">-</button>
      <input name="test" type="text">
      <button type="button">+</button>
    </div>
  </div>
  <div class="product_item">
    <div class="product_name">
    </div>
    <div class="multiply__btn">
      <button type="button">-</button>
      <input name="test" type="text">
      <button type="button">+</button>
    </div>
  </div>
  <div class="product_item">
    <div class="product_name">
    </div>
    <div class="multiply__btn">
      <button type="button">-</button>
      <input name="test" type="text">
      <button type="button">+</button>
    </div>
  </div>
</div>

<div id="total"></div>
Alcine answered 16/7, 2021 at 9:27 Comment(0)
R
0

If for some reason you don't want to use the mouseenter and mouseleave events, you can use mouseover/mouseout with a little "debouncing".

The idea relies on the fact that your event handler will receive out followed by a new over when crossing boundaries between various child elements....except when the mouse has really left (for longer than the debounce period). This seems simpler than crawling the dom nodes on every event.

If you "debounce" with a short delay before assuming you have a real out you can effectively ignore all these out/over events bubbling up from child elements.

Note! This will not work if a child element also has a listener for over and/or out events AND their handler calls event.stopPropogation() to stop the event from bubbling up to the parent element where we have attached our handler. If you control the code, this is not necessarily a problem, but you should be aware.

sample code

javascript



function mouseOverOutDebounce (element, debounceMs, mouseOverFn, mouseOutFn) {
    var over = false,
        debounceTimers = [];

    function mouseOver (evt) {
        if (over) {  // already OVER, existing interaction
            while (debounceTimers.length > 0) { // then we had a pending mouseout(s), cancel
                window.clearTimeout(debounceTimers.shift());
            }
        }
        else { // new OVER
            over = true;
            mouseOverFn(evt);
        }
    }
    function mouseOut (evt) {
        if (!over) return;  // already OUT, ignore.

        debounceTimers.push(window.setTimeout(function () {
            over = false;
            mouseOutFn(evt);
        }, debounceMs));
    }

    function removeEventListeners () {
        element.removeEventListener('mouseover', mouseOver);
        element.removeEventListener('mouseout', mouseOut);
    }
    
    element.addEventListener('mouseover', mouseOver);
    element.addEventListener('mouseout', mouseOut);

    return removeEventListeners;
}

var someEl = document.querySelector('.container'),
    textarea = document.querySelector('textarea'),
    mouseOver = function (evt) { report('mouseOVER', evt); },
    mouseOut = function (evt) { report('mouseOUT', evt); },
    removeEventListeners = mouseOverOutDebounce(someEl, 200, mouseOver, mouseOut);

function report(msg, data) {
    console.log(msg, data);
    textarea.value = textarea.value + msg + '\n';
}

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title></title>
    <style type="text/css">
        html, body {
            margin: 0;
            padding: 0;
        }
        body {
            margin: 5%;
        }
        .container {
            width: 300px;
            height: 600px;
            border: 10px solid red;
            background-color:  #dedede;
            float: left;
        }
        .container .square {
            width: 100px;
            height: 100px;
            background-color: #2086cf;
            margin: -10px 0 0 -10px; 
        }
        textarea {
            margin-left: 50px;
            width: 800px;
            height: 400px;
            background-color: #464646;
            font-family: monospace;
            color: white;
        }
        .bar {
            width: 2px;
            height: 30px;
            display: inline-block;
            margin-left: 2px;
            background-color: pink;
        }
    </style>
</head>
<body>

<div class="container">
    <div class="square"></div>

    <div class="bar"></div>
    <div class="bar"></div>
    <div class="bar"></div>
    <div class="bar"></div>
    <div class="bar"></div>
    <div class="bar"></div>
    <div class="bar"></div>
</div>

<textarea></textarea>


<script src="interactions.js"></script>
</body>
</html>

fiddle

https://jsfiddle.net/matp/9bhjkLct/5/

Regeneracy answered 11/7, 2022 at 10:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.