Event Delegation
Magic!!!
The other day I was trying to show a tooltip for every time a user hovers over a link on my webpage (trynna be fancy y’know what I mean?). This could easily be done with CSS, but I decided to use Javascript because I wanted to group the tooltips into one div separate from the links (with CSS I would have to do some hacky selection to target the tooltip on a:hover).
I started with a single event listener on a single link (Github).
const githubLink = document.querySelector('section.connect .github'); // select the Github link
const githubTip = document.querySelector('section.connect .showGithub'); // select the Github tooltipconst showTip = (e) => {
githubTip.style.display = "block";
}const hideTip = (e) => {
githubTip.style.display = "none";
}githubLink.onmouseover = showTip;
githubLink.onmouseout = hideTip;

Okay, that works. Let’s try for all 5 links now.
const githubLink = document.querySelector('section.connect .github');
const githubTip = document.querySelector('section.connect .showGithub');
const dribbbleLink = document.querySelector('section.connect .dribbble');
const dribbbleTip = document.querySelector('section.connect .showDribbble');
const codepenLink = document.querySelector('section.connect .codepen');
const codepenTip = document.querySelector('section.connect .showCodepen');
const twitterLink = document.querySelector('section.connect .twitter');
const twitterTip = document.querySelector('section.connect .showTwitter');
const emailLink = document.querySelector('section.connect .email');
const emailTip = document.querySelector('section.connect .showEmail');const showTip = (e) => {
switch (e.target.classList.value) {
case "github":
githubTip.style.display = "block";
break;
case "dribbble":
dribbbleTip.style.display = "block";
break;
case "codepen":
codepenTip.style.display = "block";
break;
case "twitter":
twitterTip.style.display = "block";
break;
case "email":
emailTip.style.display = "block";
break;
default:
break;
}
}const hideTip = (e) => {
switch (e.target.classList.value) {
case "github":
githubTip.style.display = "none";
break;
case "dribbble":
dribbbleTip.style.display = "none";
break;
case "codepen":
codepenTip.style.display = "none";
break;
case "twitter":
twitterTip.style.display = "none";
break;
case "email":
emailTip.style.display = "none";
break;
default:
break;
}
}githubLink.onmouseover = showTip;
githubLink.onmouseout = hideTip;
dribbbleLink.onmouseover = showTip;
dribbbleLink.onmouseout = hideTip;
codepenLink.onmouseover = showTip;
codepenLink.onmouseout = hideTip;
twitterLink.onmouseover = showTip;
twitterLink.onmouseout = hideTip;
emailLink.onmouseover = showTip;
emailLink.onmouseout = hideTip;
???

You know that saying of progressive enhancement vs. graceful degradation? I figure I would just “progressively enhance” my code by duplicating the code five times to cover all the links. In the process, I was attaching five event listeners onto my links but most likely only about 1 of them would be fired.
Needless to say this needed some major refactoring.
First off, I was creating a different tooltip for each link — this is unnecessary because every tooltip shows up at the exact spot and look exactly the same, except for the innerText. So let’s create only one tooltip and by default let’s just have it show Github link (but CSS would show it hidden by default anyway).
// HTMLdiv.showURL https://github.com/annuhdo// Javascript
const urlTip = document.querySelector('section.connect .showURL');
Second, since all the elements are handled in the same way (mouse over to show tooltip and mouse out to hide), I can assign a single handler to their common ancestor and detect which tooltip to show instead. Basically a ‘catch-all’ handler on the idv outside link elements.
const connectSection = document.querySelector('section.connect');connectSection.onmouseover = showTip;
connectSection.onmouseout = hideTip;
Putting it all together, the general logic will be that we put a handler on the outside div, when a user mouse over the div, it checks if it actually mouses over link — if it is a link then the tooltip will pops up and the text inside the tooltip would be the link’s href.
const connectSection = document.querySelector('section.connect');
const urlTip = document.querySelector('section.connect .showURL');const showTip = (e) => {
const link = e.target;
if (link.tagName == 'A') {
// user hovered over a link
urlTip.innerText = link.href;
urlTip.style.display = "block";
}
}const hideTip = (e) => {
urlTip.style.display = "none";
}connectSection.onmouseover = showTip;
connectSection.onmouseout = hideTip;
62 lines of code to 17 lines, not bad.

I learned a lot about this from here, so thanks a lot for that.
Hope that helps! 🌚
