0

I am trying to have an icon that switches class when the parent div is hovered. So far, here is my code:

var actionIcon = document.querySelector(".task > svg")
var taskContainer = document.querySelector(".task")

function iconScale() {
  actionIcon.classList.toggle('big');
}

taskContainer.onmouseenter = iconScale
taskContainer.onmouseleave = iconScale

And the HTML:

<div class="task">
  <h3>Title</h3>
  <svg viewBox="0 0 24 24">
    <path d="..." />
  </svg>
</div>

My issue is that the effect I am trying to achieve is only happening on the very first parent element and none of the other ones. I'm pretty sure I am not specifying something but I don't know what. Anyone could give me a hint?

j08691
  • 204,283
  • 31
  • 260
  • 272
Moromain
  • 77
  • 6

2 Answers2

2

Fixed code to map to ALL divs that are tasks. Cannot use querySelector as it only returns first instance.

const actionIcon = (parent) => {
  return parent.querySelector('svg');
};

document.addEventListener('DOMContentLoaded', function() {

  // Add events to ALL divs that conform
  let tasks = document.getElementsByClassName('task');
  
  for(let t of tasks) {
    t.onmouseenter = iconScale;
    t.onmouseleave = iconScale;
  }

  function iconScale(event) {
    let icon = actionIcon(event.target);
    icon.classList.toggle('big');
  }
});
svg {
  height: 50px;
  width: 50px;
  background-color: red;
} 

.big {
  background-color: blue;
}
<div class="task">
  <h3>Title</h3>
  <svg viewBox="0 0 24 24">
    
  </svg>
</div>
<div class="task">
  <h3>Title</h3>
  <svg viewBox="0 0 24 24">
    
  </svg>
</div>
<div class="task">
  <h3>Title</h3>
  <svg viewBox="0 0 24 24">
    
  </svg>
</div>
<div class="task">
  <h3>Title</h3>
  <svg viewBox="0 0 24 24">
    
  </svg>
</div>
Bibberty
  • 4,670
  • 2
  • 8
  • 23
  • My CSS is as simple as in your example (.big{transform: scale(1.2);}). I tried to modify my code as you suggested but nothing changes... It just works for the first element and not the other ones. Am I not missing something like specifying the div when it's hovered?? – Moromain Jan 02 '19 at 00:55
  • Works perfectly! Thanks a lot for your help :) – Moromain Jan 02 '19 at 01:04
  • 1
    Most welcome. Ensure you include the `DOMContentLoaded` call as this ensures your DOM content is loaded and ready to bind events. – Bibberty Jan 02 '19 at 01:05
  • is yours DIV.task have the same parent ? – Mister Jojo Jan 02 '19 at 01:08
  • Note that you can also use `querySelectorAll` to get all matches instead of just the first one. – Herohtar Jan 02 '19 at 01:08
  • Also, there is a difference between [`for...in`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in) and [`for...of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of). You should be using `for...of` here, because `for...in` also returns some additional properties that you should not be adding `.onmouseenter/.onmouseleave` to. – Herohtar Jan 02 '19 at 01:10
  • 1
    @Herohtar thanks for tip have edited code to reflect you for .. of comment. My bad – Bibberty Jan 02 '19 at 01:14
2

You asked for JavaScript, but as an alternative and simpler example, you don't even need to use JavaScript; what you want can be done entirely in CSS:

svg {
  height: 50px;
  width: 50px;
  background-color: red;
}

.task:hover svg {
  background-color: blue;
}
<div class="task">
  <h3>Title</h3>
  <svg viewBox="0 0 24 24">
    
  </svg>
</div>
<div class="task">
  <h3>Title</h3>
  <svg viewBox="0 0 24 24">
    
  </svg>
</div>
<div class="task">
  <h3>Title</h3>
  <svg viewBox="0 0 24 24">
    
  </svg>
</div>
<div class="task">
  <h3>Title</h3>
  <svg viewBox="0 0 24 24">
    
  </svg>
</div>
Herohtar
  • 5,347
  • 4
  • 31
  • 41