0

I have a bunch of tooltips on one page. The child div (tooltip) gets shown through css when hovering over the parent div. Now I try to get it running on click. The first tooltip works and gets shown through my code and also gets hidden when I click outside the child div. I know the issue is with the id (has to be unique). How can I achieve, that the function is directly at the div applied, that I click on. Like when I click on the third div (parent), that it also gets triggered there with its child div (tooltip)? For me it´s weird that Javascript can´t identify on which element I click and then apply my function to that element unless I want something else... Now the first works, the rest is ignored... Hope u can help.

Thanks

//Showing the tooltip on click

document.getElementById("website-tooltip-container-1").addEventListener("click", function() {
  var element = document.getElementById("test-1");
  element.classList.add("website-tooltiptext-visible");
});

//Removing tooltip when clicked outside tooltip container or outside tooltip itself

document.addEventListener('mouseup', function(e) {
  var container = document.getElementById('test-1');
  if (!container.contains(e.target)) {
    container.classList.remove("website-tooltiptext-visible");
  }
});
/* Tooltip Container */

.website-tooltip {
  position: relative;
  display: flex;
  justify-content: center;
  cursor: pointer;
  font-family: Roboto;
  font-size: 18px;
  font-weight: 400;
  color: #666;
}


/* Tooltip text */

.website-tooltip .website-tooltiptext {
  visibility: hidden;
  max-width: 350px;
  font-family: open sans;
  font-size: 13px;
  line-height: 22px;
  background-color: #FFFFFF;
  color: #666;
  text-align: left;
  padding: 11px 15px 11px 15px !important;
  border-radius: 3px;
  box-shadow: 0px 5px 10px -2px rgba(0, 0, 0, 0.5);
  /* Position the tooltip text */
  position: absolute;
  z-index: 1;
  top: 100%;
  margin: 0px 0px 0px 0px;
}


/* Show the tooltip text when you mouse over the tooltip container */

.website-tooltip:hover .website-tooltiptext {
  visibility: visible;
}


/* Hide when hovering over tooltip div */

div.website-tooltiptext:hover {
  display: none;
}


/* Toggle this class to show Tooltip on click via Javascript */

.website-tooltiptext-visible {
  visibility: visible !important;
  display: block !important;
}
<div id="website-tooltip-container-1" class="website-tooltip"><span class="dottedunderline">Tooltip 1</span>
  <div id="test-1" class="website-tooltiptext">Blabalabalbalablablabla.
  </div>
</div>

<div id="website-tooltip-container-2" class="website-tooltip"><span class="dottedunderline">Tooltip 2</span>
  <div id="test-2" class="website-tooltiptext">Blabalabalbalablablabla.
  </div>
</div>

<div id="website-tooltip-container-3" class="website-tooltip"><span class="dottedunderline">Tooltip 3</span>
  <div id="test-3" class="website-tooltiptext">Blabalabalbalablablabla.
  </div>
</div>

<div id="website-tooltip-container-4" class="website-tooltip"><span class="dottedunderline">Tooltip 4</span>
  <div id="test-4" class="website-tooltiptext">Blabalabalbalablablabla.
  </div>
</div>
Artan
  • 63
  • 13
  • "_it´s weird that Javascript can´t identify on which element I click_" That's an incorrect assumption, there's `target` property in the `event` object, that property contains a reference to the clicked element. – Teemu Jan 28 '21 at 16:15
  • Ok, and how can this help me? How can I implement that, so that the function gets triggered at the directly clicked div? – Artan Jan 28 '21 at 16:17
  • There's a lot of ways, the only limitation is your imagination. You can take a look at [a tooltip code](https://jsfiddle.net/1np2t75b/1/) I've created as an example how you can minimize DOM queries in events and utilize Map object when attaching data to the DOM. – Teemu Jan 28 '21 at 17:08
  • Ok thanks, but your code is too complex for me. I am not that pro. Such a hassle for just doing the same thing on same elements makes me wonder. In CSS you just put in a class put :hover behind it and all elements just work perfectly with minimal coding. Perhaps JavaScript is not the tool for my goal or at all. I asked this question in different ways here several times. Seems to be to difficult. Thought there would be something like 'document.getElementById[actual.clicked.id]("website-tooltip-container")' but writing a book just to show tooltips, nah! Guess I´ll copy the code and change ids... – Artan Jan 28 '21 at 17:30
  • You should stop thinking ids when you're working with a bulk of markup. The extra work with `getElementById` doesn't make much sense, as exactly the same result is already stored in `event.target`. My example code is actually quite simple, it just shows you how to bind data without ids and superfluous queries in the DOM. A big part of the code handles the tooltip placing on the page, it's not important in this context. – Teemu Jan 28 '21 at 17:35
  • 1
    Thank you for putting up your code, however it would be best to revisit it as it has some errors. In the HTML you use the same Id on several elements. This is not legal HTML. As @teemu suggests, stop thinking about ids for this problem. – A Haworth Jan 29 '21 at 15:00

2 Answers2

0

Let's take this step by step. First, wherever the user clicks you want to hide the existing tooltip, if there is one visible. One way to do that is to have this function:

function hideTooltip() {
  let el = document.querySelector(".website-tooltiptext-visible");
  if (el) { el.classList.remove("website-tooltiptext-visible");}
}

We want to hide the tooltip if the user clicks anywhere on the window so:

 window.addEventListener('click', hideTooltip);

Now for each of the elements where we want to show a tooltip (and I cannot tell from the question how to select these so you'll have to add a loop to do this)

el.addEventListener('click', showTooltip);

where

  function showTooltip(e) {
     e.stopPropagation(); // we don't want the window to see the click as well
     hideTooltip();
     this.classList.add("website-tooltiptext-visible");
}

UPDATE We now have the code in the question so it's possible to ascertain which elements are to be clickable. Here's a snippet with the above code added in (and references to hover and the original JS removed).

function showTooltip(event) {
  event.stopPropagation(); // we don't want the window to see the click as well
  hideTooltip();
  this.classList.add("website-tooltiptext-visible");
}
function hideTooltip() {
  let el = document.querySelector(".website-tooltiptext-visible");
  if (el) { el.classList.remove("website-tooltiptext-visible"); }
}

window.addEventListener('click', hideTooltip);//hide the tooltip if the user clicks anywhere on the window

//For each of the elements where we want to show a tooltip add an eventlistener to pick up clicks
const els = document.querySelectorAll(".website-tooltip");
for (let i = 0; i < els.length; i++) {
  els[i].addEventListener('click', showTooltip);
}
/* Tooltip Container */

.website-tooltip {
  position: relative;
  display: flex;
  justify-content: center;
  cursor: pointer;
  font-family: Roboto;
  font-size: 18px;
  font-weight: 400;
  color: #666;
  background-color: #eee; /* added just to show where the clickable areas are */
}

/* Tooltip text */

.website-tooltip .website-tooltiptext {
  visibility: hidden;
  max-width: 350px;
  font-family: open sans;
  font-size: 13px;
  line-height: 22px;
  background-color: #FFFFFF;
  color: #666;
  text-align: left;
  padding: 11px 15px 11px 15px !important;
  border-radius: 3px;
  box-shadow: 0px 5px 10px -2px rgba(0, 0, 0, 0.5);
  /* Position the tooltip text */
  position: absolute;
  z-index: 1;
  top: 100%;
  margin: 0px 0px 0px 0px;
}

/* Toggle this class to show Tooltip on click via Javascript */

.website-tooltiptext-visible .website-tooltiptext {
  visibility: visible;
  display: block;
}
<div id="website-tooltip-container-1" class="website-tooltip"><span class="dottedunderline">Tooltip 1</span>
  <div id="test-1" class="website-tooltiptext">Test-1 text Blabalabalbalablablabla.
  </div>
</div>

<div id="website-tooltip-container-2" class="website-tooltip"><span class="dottedunderline">Tooltip 2</span>
  <div id="test-2" class="website-tooltiptext">Test-2 text Blabalabalbalablablabla.
  </div>
</div>

<div id="website-tooltip-container-3" class="website-tooltip"><span class="dottedunderline">Tooltip 3</span>
  <div id="test-3" class="website-tooltiptext">Test-3 text Blabalabalbalablablabla.
  </div>
</div>

<div id="website-tooltip-container-4" class="website-tooltip"><span class="dottedunderline">Tooltip 4</span>
  <div id="test-4" class="website-tooltiptext">Test-4 text Blabalabalbalablablabla.
  </div>
</div>
A Haworth
  • 30,908
  • 4
  • 11
  • 14
  • Hi @A Haworth, thanks for your reply. I added the code in my question so u can see what I achieved and for a better understanding. You can see that the first tooltip ("Tooltip 1") works as it should. When I click on it, it appears, when i click outside the parent div or the tooltip text itself it stays... Everything fine so far. Now I´m trying that this works with every single tooltip without having to copy the Javascript for every tooltip and change the id. I tried your code but couldnt´t get it running. Any solution for my goal. Or am I on a totally wrong road to solve it like this? Thanks! – Artan Jan 29 '21 at 14:54
  • You need to make your code into legal HTML first, then we can have another look. – A Haworth Jan 29 '21 at 15:01
  • Hi, the html code should be "legal" now. No same ids anymore. How can I go on? – Artan Jan 29 '21 at 15:06
  • Cool! Thanks very much! I appreciate your help. I think I never could have done it myself. Regarding to my own answer. This is perhaps useful that no matte what device, the tooltips should function the same way. As :hover pseudo class could get handled differently on various touch devices (See my own answer in this question regarding to :hover on touch devices). Thanks and great work! :) – Artan Feb 01 '21 at 12:35
0

Well after some research I found my "problem":

I was always checking in Firefox "Mobile / Touch Mode" if my styles are also shown correctly on touch devices and on different screen sizes. When I checked my tooltips which have all a :hover pseudo class, the Firefox browser (in desktop use but changed to "Mobile Mode") did just nothing on click on the tooltips.

I tried and tried and decided to go with JavaScript to open the tooltips via a click function. After getting no help and solutions to achieve that (JavaScript is new to me), I had the idea just to try it once if it works on my phone... Tadaaa, my eyes grew big as the tooltips just worked as they should.

I did a bit of research and found out that different devices with touch abilities change the :hover pseudo class to a click function, so that it works on the devices. The big question that stays is: Why is Firefox not "emulating" the behavior of a real touch device? I think this is very misleading when you think you are actually testing in a touch environment... but kind of not really...

Person with similar problem to emulate a "real" touch device

Here´s a possible solution for emulating a touch device with Firefox

Yeah, I could have tested it earlier on my phone, but I trusted Firefox. So for everyone with the same issue: Better test it first on a "real" mobile device when "Mobile Mode" in Firefox doesn´t work out before trying to add more code.

Here´s for example a link that helps how to deal with :hover on touch screen devices

Thanks for reading.

Regards

Artan
  • 63
  • 13