Debounce mouse over/out

by Matt Pr

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title></title>
    
</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>

</body>
</html>

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: 350px;
  height: 300px;
  background-color: #464646;
  font-family: monospace;
  color: white;
}
.bar {
  width: 2px;
  height: 30px;
  display: inline-block;
  margin-left: 2px;
  background-color: pink;
}

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';
}