brickleberry
brickleberry

Reputation: 522

mouseover event bubbling issue

I am writing some pure Javascript that requires me to add elements to a flex container dynamically row by row. To my surprise, My mouseover event propagate across the row and trigger the other children even though it shouldn't. Below is my code:

function drawChildren() {
    var size = Math.floor(containerSize / childSize);
    var counter = 1;
    var parent = document.getElementById(parentId);
    for(var rowCount = 1; rowCount <= size ; rowCount ++) {
      var row = document.createElement('div');
      row.id = `${parentId}-rowDiv-${rowCount} `;
      row.setAttribute('style', `
        height: ${childSize}px;
        width: ${containerSize}px;
        display: flex; 
        flex-direction:row; `);
      for(var child = 1; child <= size ; child ++) {
        var childDiv = document.createElement('div');
        childDiv.id = `${parentId}-childDiv-${counter}`;
        childDiv.setAttribute('style',`
            height: ${childSize}px;
          width: ${childSize}px; 
          background-color: ${getRandomColor()};`);
          
        childDiv.addEventListener("mouseover", onMouseOver);  
        childDiv.addEventListener("mouseleave", onMouseLeave);
        row.appendChild(childDiv);
        counter ++;
      }
      parent.appendChild(row);
    }

onmouseover , I called the function below:

function onMouseOver(e) {
    e.stopPropagation();
    document.getElementById(e.target.id).style.display = 'none';
    console.log(e.target.id);
  }

The problem is, whenever I mouseover on an object, it propagates across the row and fires the mouseover event for all the other items on the same row. It does fire one at a time also. I tried to stop propagation by adding the js stopPropagation() prop yet nothing change. Please what is causing this and how do I address it? Any help would be appreciated.

Upvotes: 1

Views: 1231

Answers (1)

n4m31ess_c0d3r
n4m31ess_c0d3r

Reputation: 3148

The JS logic works just fine after removing the syntax used for getting the variables for size and parentId (which I'm guessing is from JSP). May be the backtick (`) used is the issue.

OR

You are referring to the problem where hovering on first child of the row hides the entire row.

Here, display:none; will be the culprit and you can use visibility: hidden; instead.

display: none; will remove the element from the layout, freeing its space taken from the layout and thus, allowing the next element to take up its space. In the question, hovering on 1st child frees the space which is now taken by the 2nd element. Since your mouse is still at the same position, it will now remove the 2nd element and the cycle goes so on.

visibility: hidden; only hides the element while retaining its space in the layout of the page.

Here's a working snippet of your code (with display: none; and visibility : hidden;):

var containerSize = 200,
  childSize = 50;

function onMouseOverDisplay(e) {
  e.stopPropagation();
  document.getElementById(e.target.id).style.display = 'none';
  console.log(e.target.id);
}

function onMouseOverVisibility(e) {
  e.stopPropagation();
  document.getElementById(e.target.id).style.visibility = 'hidden';
  console.log(e.target.id);
}

function setAttr(elem, attrs) {
  for (var attr in attrs) {
    if (attrs.hasOwnProperty(attr)) {
      elem.setAttribute(attr, attrs[attr]);
    }
  }
}

function drawChildren(parentId) {
  var size = Math.floor(containerSize / childSize),
    parent = document.getElementById(parentId),
    counter = 1,
    rowCount, childCount, row, childDiv;

  for (rowCount = 1; rowCount <= size; rowCount++) {
    row = document.createElement('div');
    row.id = parentId + "-rowDiv-" + rowCount;
    row.setAttribute('style', "height: " + childSize + "px; width: " + containerSize + "px; display: flex; flex-direction: row;");
    for (childCount = 1; childCount <= size; childCount++) {
      childDiv = document.createElement('div');
      childDiv.id = parentId + "-childDiv-" + rowCount + "-" + childCount;
      childDiv.setAttribute('style', "height: " + childSize + "px; width: " + childSize + "px; background-color: cyan; border: 1px solid red;");

      if (parentId === 'tab-display') {
        childDiv.addEventListener("mouseover", onMouseOverDisplay);
      } else if (parentId === 'tab-visibility') {
        childDiv.addEventListener("mouseover", onMouseOverVisibility);
      }

      // childDiv.addEventListener("mouseleave", onMouseLeave);
      row.appendChild(childDiv);
      counter++;
    }
    parent.appendChild(row);
  }
}

drawChildren('tab-display');
drawChildren('tab-visibility');
<h2>Using Display None</h2>
<div id="tab-display"></div>

<h2>Using Visibilty Hidden</h2>
<div id="tab-visibility"></div>

Upvotes: 1

Related Questions