克隆并恢复"工具"元素

Mil*_*vić 9 html javascript jquery twitter-bootstrap

我在恢复具有传递给Bootstrap .fn.tooltip()方法的元素的DOM结构时遇到了麻烦.

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

$(function(){

$('footer p').tooltip();
$('footer p').on('click', function(){
console.log('Just to test events')
});

})
Run Code Online (Sandbox Code Playgroud)

我检查出来,工具提示工作,出现点击控制台消息.现在我通过调用函数来备份我将要删除的内容并从控制台中删除它:

function experiment_destroy() {
window.backup = $('footer').clone(true, true);
$('footer p').remove();
}
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,页脚p消失了.

现在我恢复在window.backup变量中克隆和缓存的内容:

function experiment_restore(){
    $('footer').empty();
    $('footer').replaceWith(window.backup);
}
Run Code Online (Sandbox Code Playgroud)

也从控制台调用,这是发生的事情:

  • footer p 元素应该回来了
  • footer p单击时会生成控制台消息"Just to test events"消息,因此此事件将与元素一起恢复
  • 没有恢复工具提示.

即使我在函数中重新调用tooltip方法,experiment_restore我什么也得不到.有没有人有一些想法?

更新: 我又做了一个变种.尝试使用不同的 - 完全最小的DOM环境,只有pfor tooltip和parent容器元素.结果是一样的.当然,我的复杂DOM结构中不仅存在一些混乱的东西.

这是非常简单的小提琴.

Cat*_*lin 7

您需要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();
});
Run Code Online (Sandbox Code Playgroud)


Lou*_*uis 3

对于您在问题中显示的场景,我会用来$().detach()将其从 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);
});
Run Code Online (Sandbox Code Playgroud)

这是更新的小提琴

幕后发生的事情是 Bootstrap 使用$().data()类的 JavaScript 对象添加Tooltip到 DOM 元素,并添加一堆事件处理程序。你需要保存这些。

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

为什么$().clone(true, true)不工作?

您使用$().clone()参数调用来深度克隆 DOM 层次结构并保留事件处理程序和数据集,$().data()那么为什么它不起作用呢?难道克隆不应该有对TooltipBootstrap创建的对象的引用吗?

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

  var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
  if (e.isDefaultPrevented() || !inDom) return
Run Code Online (Sandbox Code Playgroud)

如果该变量位于 DOM 中,则该inDom变量将为 true 。this.$element但是,这指的是为其创建工具提示的原始元素,而不是克隆元素。由于该元素不再在 DOM 中,因此 theninDom为 false 并且下一行返回,因此工具提示永远不会显示。

为了搞笑,可以克隆一个您创建了 Bootstrap 工具提示的 DOM 元素,不要删除原始元素,而是将克隆添加到页面的其他位置。然后触发克隆上的工具提示。工具提示将出现在原始元素上。:)

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