Javascript “克隆和恢复”;“工具提示”;元素

Javascript “克隆和恢复”;“工具提示”;元素,javascript,jquery,html,twitter-bootstrap,Javascript,Jquery,Html,Twitter Bootstrap,我在恢复DOM结构时遇到了麻烦,因为它的元素被传递到了Bootstrap的.fn.tooltip()方法 具体来说:$('footer p')被传递到文档就绪事件的工具提示,如下所示: $(function(){ $('footer p').tooltip(); $('footer p').on('click', function(){ console.log('Just to test events') }); }) 我检查它,工具提示工作,点击控制台消息出现。现在,我将备份我要删除的内

我在恢复DOM结构时遇到了麻烦,因为它的元素被传递到了Bootstrap的
.fn.tooltip()
方法

具体来说:
$('footer p')
被传递到文档就绪事件的工具提示,如下所示:

$(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
    on click生成控制台消息“Just to test events” 消息,因此此事件将与元素一起还原
  • 不恢复任何工具提示
即使我在函数
experiment\u restore
中重新调用工具提示方法,我也一无所获。有人知道吗

更新: 我又做了一个变化。尝试使用不同的-完全最小的DOM环境,只使用
p
工具提示和父容器元素结果相同。当然,在我复杂的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);
});
这里有一个更新的

幕后发生的事情是引导使用
$().data()
将类
工具提示
的JavaScript对象添加到DOM元素中,并添加一组事件处理程序。你需要保存这些

如果由于某种原因,无法使用
$().detach()
,则必须通过调用
$().tooltip()
来重新创建工具提示

为什么
$().clone(true,true)
不工作? 使用参数调用
$().clone()
,以深度克隆DOM层次结构,并使用
$().data()
保留事件处理程序和数据集,那么为什么它不起作用呢?克隆不是应该引用引导创建的
工具提示
对象吗

是的,事件处理程序被保留,克隆确实有对
工具提示
对象的引用。但是,这个对象本身并没有被克隆。更重要的是,它不适合引用由
$().clone()
创建的新DOM节点。(因此,即使jQuery将克隆它,它仍然无法工作。)它确实会收到触发工具提示的事件,但
tooltip.prototype.show
执行此检查:

  var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
  if (e.isDefaultPrevented() || !inDom) return
如果
this.$element
在DOM中,则
inDom
变量将为true。但是,这是指为其创建工具提示的原始元素,而不是克隆元素。由于该元素不再在DOM中,因此
inDom
为false,下一行返回,因此工具提示永远不会显示

对于giggles,请获取您在其上创建引导工具提示的DOM元素的克隆,不要删除原始元素,而是将克隆添加到页面上的其他位置。然后触发克隆上的工具提示。工具提示将显示在原始图元上。:)


我上面描述的是Bootstrap的jQuery插件的一般工作方式:它们使用
$().data()
将JavaScript对象添加到它们操作的元素中。还有一个
下拉列表
类用于下拉列表,一个
模态
类用于模态,等等。

作为补充答案,我使用了JQuery的克隆方法,但复制了所有事件侦听器,如
.clone(true,true)
。我的问题是,工具提示与旧元素和克隆元素完全相同,但它们位于不同的位置(因此将鼠标悬停在新元素上会在浏览器的左上角显示工具提示)

我能想到的最简单的解决方案是:永远适用于所有Javascript、Bootstrap和JQuery:

const target=document.getElementById(“要克隆到的随机div”)
$(“正在选择”).clone(true,true).appendTo(目标);
//如果您只需要.innerHTML的$(“正在选择”)
//您可以执行$(“选择”).children()
const_tooltips=target.queryselectoral(“[data toggle='tooltip']”);
用于(常量x,共个工具提示){
const build=x.cloneNode(真);
$(build.tooltip();
x、 replaceNode(build,x);
}
因此,
.clone(true,true)
将捕获所有事件侦听器,包括工具提示的侦听器“mousedown”。当您使用本机ECMAScript的
cloneNode
方法时,您无法获得事件侦听器,因此需要重置工具提示

这不是最有效的,但我已经为此工作了一个小时,试图想出一些东西。。。请随便找一个更有效的方法,因为这个方法不是,但它是有效的。(例如,使用forEach,直接使用JQuery等)


编辑:您也可以在克隆时使用
.children()
获取
$(“选择”)
(即它的子对象)的内部信息,而不是获取它和它的子对象。

为什么不在还原功能中再次初始化工具提示?是的(最后一句话的第二句)-我已经尝试过了。但这不是重点。哦,是的,对不起。有任何控制台错误或什么吗?这很奇怪。它应该会起作用。可能当您尝试重新调用工具提示时,页脚尚未加载。试着设定一个时间,看看是否有问题。我希望这一切都不是真的。我甚至尝试过调用
工具提示
中的
实验还原方法
,超时100毫秒。
  var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
  if (e.isDefaultPrevented() || !inDom) return