0

I’ve been through a LOT of stackoverflows but haven’t figured out how to accomplish this. What I’m looking to do is pretty simple, but I’m not good with plain ole Javascript.

Desire:

  • Mousing over #element1 adds .specialClass to #element2
  • Mousing out #element1 removes .specialClass from #element2

If I was able to use jQuery this is exactly what I’m looking to accomplish:

$(document).ready(function() {     
    $('#element1').hover(function(){     
        $('#element2').addClass('specialClass');    
    },     
    function(){    
        $('#element2').removeClass('specialClass');     
    });
});

I need this same functionality in a plain Javascript function. I know it seems like a job for CSS, but in my very particular instance, I need this to be JS.

** THIS QUESTION IS NOT A DUPLICATE of Change an element's class with JavaScript as that one uses onClick and I'm looking for mouse over/out. **

FSSuperhero
  • 19
  • 1
  • 2
  • 1
    So what problem are you asking us for help with? Or are you asking us to translate this logic for you? http://api.jquery.com/hover/ explains which events it binds to to perform it's logic. And there should be many existing questions about javascript changing classes. – Taplar Aug 23 '18 at 18:36
  • Check [this](https://stackoverflow.com/a/262752/2767755) answer. – Arup Rakshit Aug 23 '18 at 18:37
  • 2
    [Change an element's class with JavaScript](https://stackoverflow.com/questions/195951/change-an-elements-class-with-javascript) – t.niese Aug 23 '18 at 18:37
  • [Use jQuery hover without jquery library?](https://stackoverflow.com/questions/17602317/use-jquery-hover-without-jquery-library) – t.niese Aug 23 '18 at 18:38
  • [$(document).ready equivalent without jQuery](https://stackoverflow.com/questions/799981/document-ready-equivalent-without-jquery) – t.niese Aug 23 '18 at 18:38

2 Answers2

1

document.getElementById('element1').addEventListener('mouseover', function(){
  var el = document.getElementById('element2')
  el.classList.add("specialClass");
});

document.getElementById('element1').addEventListener('mouseout', function(){
  var el = document.getElementById('element2')
  el.classList.remove("specialClass");
});
.specialClass {
  color: blue;
}
<div id="element1"> Element 1 </div>

<div id="element2">Element 2</div>
Zaren Wienclaw
  • 163
  • 3
  • 13
McRist
  • 1,455
  • 8
  • 14
0

While you have two answers already, I thought I'd post an alternative to those; using one named function instead of two anonymous functions:

// defining a named function, using arrow syntax:
let toggleClassOnHover = (e) => {

    // here we retrieve the element with the id of 'elementTwo':
    document.getElementById('elementTwo')

      // we use the classList API to work with the classes
      // of that element:
      .classList
      // using the toggle method to add, or remove, the
      // 'hoverClass' class-name to the element, depending
      // on the switch:
      .toggle('hoverClass',
        // if the 'type' property of the Event object ('e')
        // is of the same type and value as 'mouseenter'
        // the switch is (Boolean) true and the class-name is added
        // (if it is not already present); if it is not exactly
        // equal to 'mouseenter' then the switch is false and so the
        // class is removed (if it is already present):
        e.type === 'mouseenter');
  },

  // we're adding two event-listeners to this element so we cache
  // a reference to the element:
  elementOne = document.getElementById('elementOne');

// here we add an event-listener for the 'mouseenter' event,
// binding the named function as the event-handler:
elementOne.addEventListener('mouseenter', toggleClassOnHover);

// here we add an event-listener for the 'mouseleave' event,
// binding the named function as the event-handler:
elementOne.addEventListener('mouseleave', toggleClassOnHover);

let toggleClassOnHover = (e) => {
    document.getElementById('elementTwo').classList.toggle('hoverClass', e.type === 'mouseenter');
  },
  elementOne = document.getElementById('elementOne');

elementOne.addEventListener('mouseenter', toggleClassOnHover);
elementOne.addEventListener('mouseleave', toggleClassOnHover);
div {
  width: 80vw;
  margin: 0.5em auto;
  border: 2px solid currentColor;
  transition: color 0.4s linear;
}

.hoverClass {
  color: limegreen;
}
<div id="elementOne">Element one</div>
<div id="elementTwo">Element two</div>

Why did I use the mouseenter and mouseleave events, instead of mouseover and mouseout? That's illustrated in the following demo:

function incrementCounts(e) {
  if (event.type === 'mouseover') {
    +this.dataset.mouseovercount++;
  } else if (event.type === 'mouseenter') {
    +this.dataset.mouseentercount++;
  }
}

let elementOne = document.getElementById('elementOne');

elementOne.addEventListener('mouseover', incrementCounts);
elementOne.addEventListener('mouseenter', incrementCounts);
div {
  width: 80vw;
  margin: 0.5em auto;
  border: 2px solid currentColor;
  transition: color 0.4s linear;
}

div p {
  width: 50vw;
  margin: 0.5em auto;
  border: 2px solid #000;
}

#elementOne::before,
#elementOne::after {
  display: inline-block;
  width: 100%;
  border: 1px solid transparent;
  height: 1em;
}

#elementOne::before {
  content: 'Mouseover count: ' attr(data-mouseovercount);
  border-bottom-color: #000;
}

#elementOne::after {
  content: 'Mouseenter count: ' attr(data-mouseentercount);
  border-top-color: #000;
}

.hoverClass {
  color: limegreen;
}
<div id="elementOne" data-mouseovercount="" data-mouseentercount="">
  <p>Element one's content wrapped in a strangely sized &lt;p&gt; element, itself with a <span>&lt;span&gt; descendent.</p></div>
<div id="elementTwo">Element two</div>

At its most basic the mouseover event fires when the cursor enters the bounds of the element itself and when entering the bounds of the descendent elements; whereas mouseenter fires only when the cursor crosses into the element itself.

In this particular case it makes little difference but, in other situations, mouseover can lead to unexpected outcomes, whereas mouseenter is somewhat more predictable.

As you posted no HTML of your own we're unable to offer specifics as to your particular problem, but if the second element appears in the DOM as a later sibling, or descendent of a later sibling, of the first element then CSS is quite able to offer this functionality if styling is your only requirement:

div {
  width: 80vw;
  margin: 0.5em auto;
  border: 2px solid currentColor;
  transition: color 0.4s linear;
}

#elementOne:hover+#elementTwo {
  color: limegreen;
}
<div id="elementOne">Element one</div>
<div id="elementTwo">Element two</div>

References:

David says reinstate Monica
  • 230,743
  • 47
  • 350
  • 385