I'm in trouble with restoring DOM structure that has elements passed to Bootstrap's .fn.tooltip()
method.
To be specific: $('footer p')
is passed to tooltip on document ready event, like this:
$(function(){
$('footer p').tooltip();
$('footer p').on('click', function(){
console.log('Just to test events')
});
})
I check it out, tooltip works, on click console message appears. Now I take backup of what am I about to delete and delete it, from console, by calling function:
function experiment_destroy() {
window.backup = $('footer').clone(true, true);
$('footer p').remove();
}
as expected, footer's p
disappears.
Now I restore what is cloned and cached in window.backup variable with:
function experiment_restore(){
$('footer').empty();
$('footer').replaceWith(window.backup);
}
also called from console and here's what happens:
footer p
element is back as it should befooter p
on click produces console message 'Just to test events'
message, so this event is restored along with elementEven if I re-call tooltip method in function experiment_restore
I get nothing. Does anyone have some idea?
UPDATE:
I've made one more variation. Tried with different - totally minimal DOM environment with just p
for tooltip
and parent container element. Results are the same. Definitely there isn't just something in my complex DOM structure that was messing things up.
Here is very simple Fiddle.
You need to call the tooltip()
method again. Optionally you should destroy the tooltip before cloning / removing the item for cleaning up the data.
Working Fiddle
$('footer p').tooltip();
$('#destroy').click(function(){
// optionally remove bindings
$('footer p').tooltip('destroy');
window.backup = $('footer').clone();
$('footer p').remove();
})
$('#restore').click(function(){
$('footer').replaceWith(window.backup);
// apply tooltip again
//window.backup.find("p").tooltip();
$('footer p').tooltip();
});
For the scenario you've shown in your question, I would use $().detach()
to remove it from the DOM while at the same time keeping the event handlers and the data added to it with $().data()
intact. In terms of the fiddle you've put in the question:
$('#destroy').click(function(){
var $footer_p = $('footer p');
window.backup = $footer_p;
$footer_p.detach();
})
$('#restore').click(function(){
var $footer = $('footer');
$footer.append(window.backup);
});
Here's an updated fiddle
What happens behind the scenes is that Bootstrap uses $().data()
to add a JavaScript object of class Tooltip
to your DOM element, and adds a bunch of event handlers. You need to preserve these.
If for some reason, you cannot use $().detach()
, then you would have to recreate the tooltip by calling $().tooltip()
.
$().clone(true, true)
not working?You call $().clone()
with parameters to deep clone the DOM hierarchy and preserve the event handlers and the data set with $().data()
so why is it not working? Is it not the case that the clone should have a reference to the Tooltip
object created by Bootstrap?
Yes, the event handlers are preserved, and the clone does have a reference to the Tooltip
object. However, this object it itself not cloned. More importantly, it is not adapted to refer to the new DOM node created by $().clone()
. (So even if jQuery would clone it, it would still not work.) It does receive the event that would trigger the tooltip but Tooltip.prototype.show
performs this check:
var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
if (e.isDefaultPrevented() || !inDom) return
The inDom
variable will be true if this.$element
is in the DOM. However, this refers to the original element for which the tooltip was created, not the clone. Since that element is no longer in the DOM, then inDom
is false and the next line returns, so the tooltip is never shown.
For giggles, take a clone of a DOM element on which you created a Bootstrap tooltip, do not remove the original element but add the clone somewhere else on the page. Then trigger the tooltip on the clone. The tooltip will appear on the original element. :)
What I described above is the general way Bootstrap's jQuery plugins work: they use $().data()
to add JavaScript objects to the elements on which they operate. There's also a Dropdown
class for dropdowns, a Modal
class for modals, etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With