Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mouseenter and mouseleave event with window scroll event

I want to measure the time that a mouse cursor is in a specific area (div-container). See code below.

Until now, the leave and enter times (hover-times) are only measures when the mouse cursor enters and leaves the respective container (due to the mouseleave and mouseenter event) but not when the user uses mouse wheel or scrolls the window. My goal is to change the code in a way that the hover time is also measured when the window is scrolled (e.g. the user uses the mouse wheel).

I already tried to implement a .scroll() event with the selector 'document'.

Has anyone already encountered the same problem and has a solution for the problem?

var hover_events = {};
var enter_time;
var leave_time;


$(".element").on('mouseenter', function(d) {
  enter_time = Date.now();
  hover_events[d.target.id] = {
    element_id: d.target.id,
    enter_time: enter_time,
    leave_time: undefined,
  };

});

$(".element").on('mouseleave', function(d) {
  leave_time = Date.now();
  hover_events[d.target.id]["leave_time"] = leave_time;

  console.log(hover_events[d.target.id])
  delete(hover_events[d.target.id]);

});
.element {
  margin: 100px;
  width: 100px;
  height: 100px;
  background-color: lightblue;
}

#scroll {
  width: 1000px;
  height: 1000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="scroll">
  <div class="element" id="test">
  </div>
</div>
like image 780
Nicki Maier Avatar asked Jan 26 '26 03:01

Nicki Maier


1 Answers

I found that question fun to work on... And spend quite a time on it.

Here is how I thought it:

  • Use mouseenter to record a time_enter.
  • use the mouseleave to calculate a time_spent for the element and clear time_enter.
  • On mousemove, record the x/y mouse position.
  • On scroll for all elements, get the positions (relative to the view port) compare them with the recorded mouse position to trigger a mouseenter or a mouseleave on it.

Codepen

console.clear();

var elements = {};
let mouse_pos = {};

// Save all element position relative to the viewport
function positions() {
  $(".element").each(function () {
    let bounding_rect = this.getBoundingClientRect();
    elements[this.id] = elements[this.id] || {};

    elements[this.id].top = bounding_rect.top;
    elements[this.id].right = bounding_rect.right;
    elements[this.id].bottom = bounding_rect.bottom;
    elements[this.id].left = bounding_rect.left;
    elements[this.id].time_spent = elements[this.id].time_spent || 0;
  });
}

// Run once on load
positions();
let keys = Object.keys(elements);

$(window).on("scroll", function () {
  positions();

  // loop all elements
  keys.forEach(function (id) {
    let item = elements[id];

    if (
      mouse_pos.x > item.left &&
      mouse_pos.x < item.right &&
      mouse_pos.y > item.top &&
      mouse_pos.y < item.bottom
    ) {
      console.log("Hovering", id);
      $(`#${id}`).trigger("mouseenter");
    } else {
      $(`#${id}`).trigger("mouseleave");
    }
  });
});

$(document).on("mousemove", function (e) {
  mouse_pos.x = e.pageX;
  mouse_pos.y = e.pageY;
  //console.log(mouse_pos)
});

$(".element").on("mouseenter", function (e) {
  elements[e.target.id].time_enter = Date.now();
  //console.log(elements);
  $(`#${e.target.id}`).addClass("hovered");
});

$(".element").on("mouseleave", function (e) {
  if (elements[e.target.id].time_enter) {
    elements[e.target.id].time_spent +=
      Date.now() - elements[e.target.id].time_enter;
    delete elements[e.target.id].time_enter;
    //console.log(elements);

    $(`#${e.target.id}`)
      .text((elements[e.target.id].time_spent / 1000).toFixed(2) + " sec.")
      .removeClass("hovered");
  }
});
body {
  height: 1000px;
}

.row {
  display: flex;
  justify-content: space-between;
  margin-top: 100px;
}

.element {
  width: 100px;
  height: 100px;
  background-color: lightblue;
  display: flex;
  justify-content: center;
  align-items: center;
}

.hovered {
  border: 1px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="row">
  <div class="element" id="el_1"></div>
  <div class="element" id="el_2"></div>
  <div class="element" id="el_3"></div>
  <div class="element" id="el_4"></div>
</div>
<div class="row">
  <div class="element" id="el_5"></div>
  <div class="element" id="el_6"></div>
  <div class="element" id="el_7"></div>
  <div class="element" id="el_8"></div>
</div>
like image 184
Louys Patrice Bessette Avatar answered Jan 27 '26 19:01

Louys Patrice Bessette



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!