我在恢复DOM结构时遇到了麻烦,DOM结构中的元素被传递给Bootstrap的.fn.tooltip()
方法。
具体而言:$('footer p')
被传递给document的工具提示,如下所示:
$(function(){
$('footer p').tooltip();
$('footer p').on('click', function(){
console.log('Just to test events')
});
})
我检查它,工具提示工作,点击控制台消息出现。现在,通过调用函数,从控制台备份将要删除和删除的内容:
function experiment_destroy() {
window.backup = $('footer').clone(true, true);
$('footer p').remove();
}
正如所料,页脚的p
消失了。
现在,我使用以下方法还原在window.backup变量中克隆和缓存的内容:
function experiment_restore(){
$('footer').empty();
$('footer').replaceWith(window.backup);
}
也是从控制台调用的,下面是发生的情况:
footer p
元素以应有的方式返回。footer p
生成控制台消息“只用于测试事件”消息,因此该事件与元素一起还原。即使我在函数experiment_restore
中重新调用工具提示方法,我也什么也得不到。有人有什么想法吗?
更新:,我又做了一个变体。尝试使用不同的-完全最小的DOM环境,只对p
进行tooltip
和父容器元素。结果是相同的。当然,在我复杂的DOM结构中,不只是一些东西把事情搞砸了。
这是非常简单的Fiddle。
发布于 2015-04-10 11:48:59
对于您在问题中显示的场景,我将使用$().detach()
从DOM中删除它,同时保持事件处理程序和添加到DOM的数据与$().data()
保持完整。关于你所提出的问题:
$('#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);
});
这里有一个更新的小提琴
幕后发生的事情是,Bootstrap使用$().data()
将类Tooltip
的JavaScript对象添加到DOM元素中,并添加了一组事件处理程序。你需要保存这些。
如果由于某种原因不能使用$().detach()
,则必须通过调用$().tooltip()
重新创建工具提示。
为什么$().clone(true, true)
不能工作?
您使用参数调用$().clone()
来深入克隆DOM层次结构,并使用$().data()
保留事件处理程序和数据集,那么为什么它不能工作呢?克隆不是应该有一个引用的Tooltip
对象创建的引导吗?
是的,事件处理程序被保留下来,并且克隆确实有一个对Tooltip
对象的引用。但是,这个对象本身并不是克隆出来的。更重要的是,它不适合引用$().clone()
创建的新DOM节点。(因此,即使jQuery克隆了它,它仍然不能工作。)它确实收到了触发工具提示的事件,但是Tooltip.prototype.show
执行以下检查:
var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
if (e.isDefaultPrevented() || !inDom) return
如果inDom
在DOM中,则this.$element
变量将为真。但是,这是指为其创建工具提示的原始元素,而不是克隆。由于该元素已不在DOM中,所以inDom
为false,下一行将返回,因此工具提示永远不会显示。
对于咯咯笑,使用创建引导工具提示的DOM元素的克隆,不要删除原始元素,而是将克隆添加到页面的其他地方。然后触发克隆上的工具提示。工具提示将出现在原始元素上。:)
我上面描述的是Bootstrap的jQuery插件的一般工作方式:他们使用$().data()
将JavaScript对象添加到它们操作的元素中。还有一个用于下拉的Dropdown
类,一个用于modals的Modal
类,等等。
发布于 2015-04-09 12:55:50
您需要再次调用tooltip()
方法。或者,在克隆/删除用于清理数据的项之前,应该销毁工具提示。
$('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();
});
发布于 2020-12-06 20:52:56
作为一个补充答案,我使用了JQuery的克隆方法,但是我复制了所有的事件侦听器,比如.clone(true, true)
。我的问题是,工具提示与旧元素和克隆元素完全相同,但它们位于不同的位置(因此,在新元素上盘旋会在浏览器的左上角显示工具提示)。
我能想到的最简单的修复方法应该适用于所有Javascript,Bootstrap,JQuery,永远是:
const target = document.getElementById("random-div-you-want-to-clone-to")
$("selecting").clone(true, true).appendTo(target);
// if you only want .innerHTML of $("selecting")
// you can do $("selecting").children()
const _tooltips = target.querySelectorAll("[data-toggle='tooltip']");
for (const x of _tooltips) {
const build = x.cloneNode(true);
$(build).tooltip();
x.parentNode.replaceNode(build, x);
}
因此,.clone(true, true)
将抓取所有事件侦听器,包括"mousedown“,即工具提示的侦听器。当您使用本机ECMAScript的cloneNode
方法时,您不会获得事件侦听器,因此需要重置工具提示。
这不是最有效率的,但我花了一个小时努力想些什么.作为我的客人,在寻找一个更有效的方法,因为这个方法不是,但它的工作。(例如使用forEach,直接使用JQuery等等)。
编辑:您还可以在克隆时使用.children()
获取$("selecting")
的内部(即其子),而不是获取它和其子节点。
https://stackoverflow.com/questions/29491673
复制相似问题