Hello,
I have an issue, where I'm unable to use the same HTML template for multiple tooltips.
Here's my init code:
var poppers = Array.from(document.querySelectorAll('[data-toggle="popper"]'));
tippy(poppers, {
position: 'bottom',
trigger: 'click',
duration: 100,
interactive: true,
arrow: true,
performance: true,
html: document.querySelector('.popper')
});
Only the last [data-toggle="popper"] is able to toggle the tooltip, the first ones just display an empty box.
Any ideas how to fix this? :) Popper.js and tippy.js are looking very awesome!
I kind of stumbled upon this and debugged this the hard way just a few weeks ago (new to using tippy.js by maybe about a month now). I was going to suggest a fix for it but there's a workaround: use Node.cloneNode(true).
It's not written in the docs, but the template you're referring to ('.popper') is being taken away from the DOM. Check it out in your project.
@atomiks the long term fix is to either handle the cloning of the node internally or update the docs to describe this behavior.
Hope this helps @raineluntta.
Templates are cloned when you use a selector ID string like '#template' instead of using the Element directly. Otherwise the workaround is cloneNode as @padi said
@atomiks Ah yes, using the id does clone the element, but I was kind of expecting a document.querySelector('...') to do the same for consistency (one html option does destructive behavior while the other doesn't).
The Element option was added because cloning doesn't keep event listeners attached which someone needed. So you've got the option of using the Element directly or cloning it. String = clone, Element = direct append.
I mentioned that in the docs but maybe it wasn't explained too well... probably need to overhaul the wording on everything for v2
@atomiks I see. One of the reasons why I didn't say this before was because I wanted (2) others on my team to use tippy and see how they would use it. The behavior I described is one of the few common stumbling blocks we had (i.e. they also didn't expect the template to be gone).
A cleaner workaround to keeping the event listeners attached is to use event delegation. For example, if you have appendTo: document.body, you could do something like
<body>
<!-- other content -->
<!-- content below is not immediately here until `.show(popper)` is used -->
<span class='.btn-inside-tippy'>I'm inside Tippy!</span>
</body>
// You can also do something similar in pure javascript
jQuery("body").on("click", ".btn-inside-tippy", function() {
var targetElement = $(this);
targetElement.doSomething();
});
Or if you're concerned about performance of attaching listeners to the body, have something else for appendTo:
<body>
<!-- other content -->
<div id=tippytemplates-container>
<!-- content below is not immediately here until `.show(popper)` is used -->
<span class='.btn-inside-tippy'>I'm inside Tippy!</span>
</div>
</body>
jQuery("#tippytemplates-container").on("click", ".btn-inside-tippy", function() {
var targetElement = $(this);
targetElement.doSomething();
});
This is how turbolinks gets around replacing the
tag in betweenturbolinks:page_loads. There's a few other known techniques such as making use of MutationObserver, but for me event delegation is good enough to pick up by everyone without much effort.
I guess that depends on how the developer is using it and can't be controlled by the library... so I guess the solution is a better explanation in the docs?
@atomiks This is mostly up to you. You have 2 options:
cloneNode(true) inside the library when an Element/Node is passed and make an explicit advice about using event delegation. This is to be added in v2 of tippy.js anyway, so you can introduce breaking changes (developers will have to alter their event bindings). Pros:
html tippy setting does the same behavior for the 2 kinds of parameters/options. The html template is copied over they are templates, and switching your tippy options between id and Element should require no further changes in other parts of your js code, since...id or the Element option if you use event delegation.Cons:
Pros:
Cons:
Personally, I'm slightly leaning towards 1.
Off topic:
Related comment about the docs: As it currently stands, it has a very great "above the fold" content, but the dense text below is just difficult to skim for the behavior a user wants. This is probably part of why every tippy user I've seen so far has missed this quirk. A quick solution would be to have a sidebar that links to each section of the static website.
You can email me at [email protected] to continue the discussion so that we can avoid littering this issue with unrelated content.
Alright, I've simplified the hell out of the Creating HTML Templates section. That was really wordy and hard to read before. Now I've simplified it and explicitly noted the two options.
https://atomiks.github.io/tippyjs/#creating-html-templates
Great discussion here! Thank you for the solution, I honestly read the documentation multiple times but couldn't see that I could use the ID selector for my purpose. Glad the documentation is clearer now! :)
Most helpful comment
Alright, I've simplified the hell out of the
Creating HTML Templatessection. That was really wordy and hard to read before. Now I've simplified it and explicitly noted the two options.https://atomiks.github.io/tippyjs/#creating-html-templates