0

I am trying to just do 2 things here: display this array of objects their own individual <div> when mouse enter- need to change border color to black. when clicked on need to alert each objects property "name" .

( getting error in console-- "Uncaught TypeError: hover.addEventListener is not a function" )

this is what I have so far...

var data = [ {'name':'user1', 'group':1 }, {'name':'user2', 'group':1 }, {'name':'user2', 'group':1 }, {'name':'user3', 'group':2 } ];

for(i = 0; i < data.length; i++) { document.write('<div class="hover">' + data[i].name + '</div>'); }

let hover = document.getElementsByClassName(".hover");

hover.addEventListener("click", function(e){ alert("object.name"); });

hover.addEventListener("onmouseenter", function(e){ hover.style.borderColor = "black"; });

2 Answers2

0

There is a basic issue here: hover, if it worked the way you're trying to make it work, represents a collection of elements, very similar to an array, and it does not have a method addEventListener. You would need to add an event listener to every element in that collection.

However, that still isn't going to work, because the elements don't exist at the point in time you're trying to attach event listeners to them. I would read up on event delegation, but in the meantime, here is one solution: I've attached the event listeners to the document itself, and if the target of the click/mouseenter is an element with the class hover, it Does The Thing. If your elements don't exist, then it's not an issue -- nothing happens. Once they exist, the functionality you want will work -- the event listener is listening to everything that happens below it in the tree.

var data = [{
    'name': 'user1',
    'group': 1
  },
  {
    'name': 'user2',
    'group': 1
  },
  {
    'name': 'user2',
    'group': 1
  },
  {
    'name': 'user3',
    'group': 2
  }
];

for (i = 0; i < data.length; i++) {
  document.write('<div class="hover">' + data[i].name + '</div>');
}



document.addEventListener("click", function(e) {
  if (e.target.classList.contains("hover")) {
    alert("object.name");
  }
});
// NOTE this will fire a very large number of times
document.addEventListener("mouseover", function(e) {
  if (e.target.classList.contains("hover")) {
    // NOTE just applying borderColor won't work if it there's no border to start with
    e.target.style.border = "1px solid black";
  }
});
DanCouper
  • 822
  • 6
  • 13
  • You *can* add `mouseenter` and `click` handlers just on the `div` elements and not have to use the expensive `mouseover` event. See my solution. And how would you handle removing the border when the mouse left the `div` if that were required? It can be done but it becomes rather messy. – Booboo Mar 12 '20 at 13:54
  • Oh, definitely, it was just a quick example – DanCouper Mar 12 '20 at 14:03
0

First, when you use document.getElementsByClassName, you don't use a period before the class name. Second, the event name for addEventListener is mouseenter, not onmouseenter. Third, you have to use Array.prototype.forEach.call so that you add a handler for each div element.

I have made a few changes to your code. I have initialized each div to have a red border so that you can better see the effect of setting the color to black (if there were no border to begin with, just setting a color attribute would have no effect on creating a border). And for good measure, I reset the border back to red when the mouse leaves the div. But you can remove the mouseleave handler if you wish. If you don't want any border initially then instead of setting the borderColor property, you must set the border property to something like 5px solid black.

var data = [
    {'name':'user1',
    'group':1
    },
    {'name':'user2',
    'group':1
    },
    {'name':'user2',
    'group':1
    },
    {'name':'user3',
    'group':2
    }
];

for(let i = 0; i < data.length; i++) {
   document.write('<div class="hover" style="border: 5px solid red; margin: 5px 0px;">' + data[i].name + '</div>');
}

// ensure div elements have been created:
document.addEventListener("DOMContentLoaded", function(event) { 
    let hovers = document.getElementsByClassName("hover"); // no '.'
    Array.prototype.forEach.call(hovers, function(hover) {
        hover.addEventListener("click", function(e) {
            let hover = e.target;
            alert(hover.innerHTML);
        });
        hover.addEventListener("mouseenter", function(e) {
            let hover = e.target;
            hover.style.borderColor = "black";
        });
        hover.addEventListener("mouseleave", function(e) {
            let hover = e.target;
            hover.style.borderColor = "red";
        });
    });
});

Variation Where the Border is Added and Removed

var data = [
    {'name':'user1',
    'group':1
    },
    {'name':'user2',
    'group':1
    },
    {'name':'user2',
    'group':1
    },
    {'name':'user3',
    'group':2
    }
];

for(let i = 0; i < data.length; i++) {
   document.write('<div class="hover">' + data[i].name + '</div>');
}

// ensure div elements have been created:
document.addEventListener("DOMContentLoaded", function(event) { 
    let hovers = document.getElementsByClassName("hover"); // no '.'
    Array.prototype.forEach.call(hovers, function(hover) {
        hover.addEventListener("click", function(e) {
            let hover = e.target;
            alert(hover.innerHTML);
        });
        hover.addEventListener("mouseenter", function(e) {
            let hover = e.target;
            hover.style.border = "1px solid black";
        });
        hover.addEventListener("mouseleave", function(e) {
            let hover = e.target;
            hover.style.borderWidth = "0px";
        });
    });
});
Booboo
  • 18,421
  • 2
  • 23
  • 40
  • See [What should I do when someone answers my question?](https://stackoverflow.com/help/someone-answers). – Booboo Mar 12 '20 at 13:36