0

I'm trying to highlight all elements of the same class (person1, person2, etc.) that are created dynamically with JavaScript from an array, when hovering over one element from this class. F.e. if I hover over an element with class: person1 I would like all elements with class: person1 to be highlighted. The main problem is that when I add a parameter to the highlightGen function that's added onmouseover (which would be highlightGen(j) ) to then work on each person1, person2, person3 depending on the situation through this variable, the function stops working all together. This is what I've come up with so far.

[update]: I've tried Your example, but the same effect occurs when I added parameters to the highlightGen function - not responding. I attach the codepen, so maybe someone will be able to figure why it's not responding to mouseenter.

https://codepen.io/mmsmsy/pen/zZddZz

jQuery UI function:

function highlightGen() {
    $(this).addClass('hovered', 300);
}

function highlightGenNot() {
    $(this).removeClass('hovered', 300);
}

And part of the code in a JavaScript loop creating elements from an array:

        var div = document.createElement('div');
        var divIdInitial = tree[j].name.toLowerCase();
        var find = ["ą","ć","ę","ł","ń","ó","ś","ź","ż"," "];
        var replace = ["a","c","e","l","n","o","s","z","z",""];
        var divId = divIdInitial.replaceArray(find,replace) + tree[j].genNum;
        div.setAttribute('id',divId);
        var divClass = 'person person' + tree[j].genNum;
        div.setAttribute('class',divClass);
        div.onmouseover = highlightGen;
        div.onmouseout = highlightGenNot;
Mateusz Mysiak
  • 548
  • 6
  • 19
  • Why not just change the class when you hover... so on hovering over any `person1` do e.g. `$('.person1').css('background', 'red');` then remove it on mouseout – StudioTime Mar 15 '17 at 14:34
  • That indeed works, however how do I make the function work for the other classes separately at the same time like person2, person3, etc. – Mateusz Mysiak Mar 15 '17 at 14:38
  • when hovering on `person1` if you want to affect more classes then simply: `$('.person1, .person2, .person2').css('background', 'red');` – StudioTime Mar 15 '17 at 14:48
  • No. I'd like to hover over any .person1 element and affect all and only .person1 elements. When hoovering over any .person2 element to affect all and only .person2 elements, and so on. – Mateusz Mysiak Mar 15 '17 at 15:48
  • so on hovering over any `person2` do e.g. `$('.person2').css('background', 'red');` – StudioTime Mar 15 '17 at 15:55
  • Since you mentioned that you are trying to avoid jQuery, I thought I would mention that you could use [`classList`](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList) to easily add/remove classes instead of using jQuery for that. – Useless Code Mar 15 '17 at 17:14

1 Answers1

0

You can make use of closures to pass another argument to highlight like this:

function highlightGen(className, addOrRemove) {
    $('.' + className).toggleClass('hovered', addOrRemove); // if addOrRemove is true then add the class, else remove it (http://api.jquery.com/toggleClass/)
}

And then set the event listeners like this:

// ...
var theClass = 'person' + tree[j].genNum;
div.className = 'person ' + theClass;      // className is better
div.onmouseenter = function() {            // onmouseenter is better
    highlightGen(theClass, true);          // add the class
}
div.onmouseleave = function() {            // onmouseleave is better
    highlightGen(theClass, false);         // remove it
}

Note 1: then you could remove the function highlightGen as it is now useless, just put its code inside the event listeners directly (it's up to you).

Note 2: If you are already using jQuery, then why not use it to create elements and setting their properties instead of using plain vanilla js (createElement, onmouseenter, ...)?

Example:

function highlightGen(className, addOrRemove) {
  $('.' + className).toggleClass('hovered', addOrRemove);
}

function generate() {
  var div = document.createElement("div");
  var theClass = 'person' + Math.floor(Math.random() * 3 + 1);
  div.className = 'person ' + theClass;
  div.textContent = "DIV." + theClass;
  div.onmouseenter = function() {
    highlightGen(theClass, true);
  }
  div.onmouseleave = function() {
    highlightGen(theClass, false);
  }
  return div;
}

// generate some testing divs
for(var i = 0; i < 20; i++)
  $("#container").append(generate());
.hovered {
  background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container"></div>
ibrahim mahrir
  • 31,174
  • 5
  • 48
  • 73
  • Looks like an elegant solution Your code, Thx. I'm trying to do everything in vanilla JS to learn what I can, so far except for this part the only jQuery I've used is to animate it to look a little bit nicer. However I still have problems using Your solution the same way I had a problem when I added a parameter. It just stops doing anything at all. I added codepen with the whole webpage to maybe give you some more to work it out. Thank You. – Mateusz Mysiak Mar 15 '17 at 15:14
  • @MateuszMysiak Man it took me a year to find it! You didn't copy the code the right way. You put the code of `highlightGen` inside `highlightGen` (a function inside a function => wrong). Fix it and it will add the class `.hovered` correctly. And add some style to the class `.hovered` too! – ibrahim mahrir Mar 15 '17 at 16:02
  • Corrected. It's doing something now, however now it's affecting always and only the last generation. It would seem like it should add all the separate classes, yet the function highlights always the last person class elements (in this case person6) whenever any person is highlighted. I've updated the CodePen. – Mateusz Mysiak Mar 15 '17 at 16:14
  • Shuuut! Yeah I forgot about that, I was going to mention that in the first comment. Here is your [**problem**](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example). **Hint:** The `while` loop with the index `j` surrounding the code that generates the divs!. – ibrahim mahrir Mar 15 '17 at 16:31
  • @MateuszMysiak I reccomend this [**answer**](http://stackoverflow.com/a/750495/6647153)! Change the code `while(j < tree.length) { /*code*/ j++;}` to `while(j < tree.length) { (function(j) { /*code*/ })(j); j++}` or use `forEach` like: `tree.forEach(function(t, j) { /*code*/ })` and get rid of the `while`! – ibrahim mahrir Mar 15 '17 at 16:40