使用事件侦听器克隆 bootstrap 元素
Cloning a bootstrap element with an event listener
我正在尝试克隆 bootstrap 元素,该元素具有 bootstrap 提供的数据切换行为:
HTML
<div class="container">
<button aria-expanded="false" data-target="#collapsible_obj_0" data-toggle="collapse" class="btn btn-link collapsed">click here</button>
<div style="height: 0px;" aria-expanded="false" id="collapsible_obj_0" class="collapse">
<span>foo</span>
</div>
</div>
克隆后,我正在将 div 的 ID
更改为新的唯一 ID,以及按钮的 data-target
指向 new div。
JS
var header = objectContainer.clone(true);
var counter = this.collapsibleObjCounter++;
var collapseId = "collapsible_obj_" + counter;
header.find(".collapse").attr("id", collapseId);
header.find("button[data-toggle='collapse']").attr("data-target", "#"+collapseId);
按钮和 div 是我正在克隆 的对象容器的子对象。
有时这可行,但有时我最终会得到一个按钮,它仍然扩展和收缩原始 div,即使当我检查 HTML 时,ID 看起来是正确的。
我怀疑复制的事件处理程序可能正在硬编码对要扩展和收缩的 div 的 ID 的引用,这就是为什么只修复 DOM 中的 ID元素不起作用。然而,这并不能解释为什么一些克隆有效而另一些无效。
克隆具有 bootstrap 行为的东西的正确方法是什么?
因此,有几个答案指出,只需从我的 clone()
调用中删除 true
即可避免复制事件侦听器。所以我现在意识到我的问题比我在这里过度简化的问题要复杂一些。我会把它作为一个单独的问题来问。 (Cloning a Bootstrap element but not all of the event listeners)
到目前为止你的代码没问题,只需从 clone()
中删除 true
就不需要了。
已更新
This Boolean value indicates whether event handlers should be copied along with the elements. The default value is to the false . So, when we were calling the .clone()
method without passing any Boolean value, it was just copying the elements but not the event handlers attached to it. But, when we pass the value true , it copies both the elements and any event handlers attached to it.
但是 Bootstrap 正在处理动态对象的 事件处理程序 ,因此您不需要 true
在克隆中。
喜欢
如果您使用这种方式处理 events
动态对象
$(".btn").click(.....);
// This button was dynamically created and you want a click event for it,
// but it wont work because at the time of event binding this button wasn't exist at all.
但是
您需要使用 event delegation 技术处理动态对象的 事件。
$(document).on("click",".btn",function(){ .... });
这将起作用,因为事件处理程序绑定到 DOM
树(在本例中为文档)更高层的元素,并且当事件到达该元素时将被执行匹配选择器,
这就是 Bootstrap 对动态对象所做的,如果需要,您也可以对动态对象执行相同的操作。为此,她的 JSFiddle。
您还需要将整个 collapsible
部分包装在 div
中以便克隆。
Note: Using .clone()
has the side-effect of producing elements with duplicate id
attributes, which are supposed to be unique. Where possible, it is recommended to avoid cloning elements with this attribute or using class attributes as identifiers instead.
所以,克隆后需要更新data-target
和div
id属性,这样新创建的按钮targets
就是新创建的折叠面板
我正在使用jQuery。
这是代码片段
$(function(){
var target = "collapsible_obj_";
var i = 1;
$("#button").click(function(){
$(".parent_colapse:last").clone().insertAfter(".parent_colapse:last");
$(".parent_colapse:last > button").attr("data-target", "#"+target+i);
$(".parent_colapse:last .collapse").attr("id", target+i);
i++;
});
$(document).on("click",".button",function(){
alert();
});
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div class="parent_colapse">
<button aria-expanded="false" data-target="#collapsible_obj_0" data-toggle="collapse" class="btn btn-link collapsed">click here</button>
<div style="height: 0px;" aria-expanded="false" id="collapsible_obj_0" class="collapse">
<span>foo</span>
<button type="button" class="button">click</button>
</div>
</div>
<button type="button" id="button">Clone</button>
关于你的问题你没有显示完整的script
这就是我们无法找到错误的原因。 LIKE 我们不知道 objectContainer
也 collapsibleObjCounter
那是什么?
我已经为您的代码创建了一个 JSFiddle。最可能的错误似乎是您使用 0
的 this.collapsibleObjCounter++
值可能会造成问题。
这是一个有效的 JSFiddle。请让我知道这是否是您想要做的。谢谢。
JS
$( document ).ready(function() {
for (i = 1; i < 5; i++) {
var objectContainer = $("#main");
var header = objectContainer.clone(true);
var counter = i; // replace this with this.collapsibleObjCounter++
var collapseId = "collapsible_obj_" + counter;
header.find(".collapse").attr("id", collapseId);
header.find("button[data-toggle='collapse']").attr("data-target", "#"+collapseId);
$(header).appendTo('body');
}
});
HTML
<div id="main">
<button aria-expanded="false" data-target="#collapsible_obj_0" data-toggle="collapse" class="btn btn-link collapsed">click here</button>
<div style="height: 0px;" aria-expanded="false" id="collapsible_obj_0" class="collapse">
<span>foo</span>
</div>
</div>
如果您在 this.collapsibleObjCounter++
中的值为 0
,那么我建议您做 ++this.collapsibleObjCounter
。而不是 post increment do pre increment
克隆时不要复制事件,删除 true
标志。
var header = objectContainer.clone();
我的猜测是 Bootstrap 正在为数据切换处理动态对象的事件绑定,它只需要有不同的 id 和目标。
这是一个 fiddle。
PS: 不知道 OP 问题中的 this 或 objectContainer 是什么,因此创建了一个闭包并在新包装器中粘贴结果。
问题不是由事件侦听器本身引起的。问题是 Bootstrap 是如何工作的。对于大多数 Bootstrap 组件,Bootstrap 创建一个与 DOM 元素关联的 JavaScript 对象。 克隆 Bootstrap 组件时需要注意此对象。 对于 collapse
元素,Bootstrap 创建一个 Collapse
object.
JavaScript 对象通过 jQuery 的 $.data
与 DOM 元素相关联。 这就是问题所在。如果您使用 jQuery 的 clone
并请求将事件处理程序复制到克隆,那么您还可以使用 $.data
获得数据集的副本。但是,当数据是对 JavaScript 对象的引用时,则它是被复制到克隆的 reference。所以原始对象和克隆对象指的是同一个 JavaScript 对象,这就是一切都误入歧途的地方。这对 Bootstrap 来说并不特别,顺便说一下:任何引用都会遇到这个问题。
您可以对 Bootstrap 组件的克隆元素执行 $.removeData
。这将强制 Bootstrap 重新创建 JavaScript 对象。对于自动注册数据 API 的组件,这应该是所有需要的。 (collapse
自动注册。)对于 不 自动注册的组件(例如工具提示),您需要调用 $.[component]
手动重新创建组件。
我 forked a fiddle from 的 fiddle 说明了这一点。唯一的修改是:
将参数true, true
添加到var header = objectContainer.clone();
修改header.find(".collapse").attr("id", collapseId)
,在末尾添加.removeData()
。
我正在尝试克隆 bootstrap 元素,该元素具有 bootstrap 提供的数据切换行为:
HTML
<div class="container">
<button aria-expanded="false" data-target="#collapsible_obj_0" data-toggle="collapse" class="btn btn-link collapsed">click here</button>
<div style="height: 0px;" aria-expanded="false" id="collapsible_obj_0" class="collapse">
<span>foo</span>
</div>
</div>
克隆后,我正在将 div 的 ID
更改为新的唯一 ID,以及按钮的 data-target
指向 new div。
JS
var header = objectContainer.clone(true);
var counter = this.collapsibleObjCounter++;
var collapseId = "collapsible_obj_" + counter;
header.find(".collapse").attr("id", collapseId);
header.find("button[data-toggle='collapse']").attr("data-target", "#"+collapseId);
按钮和 div 是我正在克隆 的对象容器的子对象。
有时这可行,但有时我最终会得到一个按钮,它仍然扩展和收缩原始 div,即使当我检查 HTML 时,ID 看起来是正确的。
我怀疑复制的事件处理程序可能正在硬编码对要扩展和收缩的 div 的 ID 的引用,这就是为什么只修复 DOM 中的 ID元素不起作用。然而,这并不能解释为什么一些克隆有效而另一些无效。
克隆具有 bootstrap 行为的东西的正确方法是什么?
因此,有几个答案指出,只需从我的 clone()
调用中删除 true
即可避免复制事件侦听器。所以我现在意识到我的问题比我在这里过度简化的问题要复杂一些。我会把它作为一个单独的问题来问。 (Cloning a Bootstrap element but not all of the event listeners)
到目前为止你的代码没问题,只需从 clone()
中删除 true
就不需要了。
已更新
This Boolean value indicates whether event handlers should be copied along with the elements. The default value is to the false . So, when we were calling the
.clone()
method without passing any Boolean value, it was just copying the elements but not the event handlers attached to it. But, when we pass the value true , it copies both the elements and any event handlers attached to it.
但是 Bootstrap 正在处理动态对象的 事件处理程序 ,因此您不需要 true
在克隆中。
喜欢
如果您使用这种方式处理 events
动态对象
$(".btn").click(.....);
// This button was dynamically created and you want a click event for it,
// but it wont work because at the time of event binding this button wasn't exist at all.
但是
您需要使用 event delegation 技术处理动态对象的 事件。
$(document).on("click",".btn",function(){ .... });
这将起作用,因为事件处理程序绑定到 DOM
树(在本例中为文档)更高层的元素,并且当事件到达该元素时将被执行匹配选择器,
这就是 Bootstrap 对动态对象所做的,如果需要,您也可以对动态对象执行相同的操作。为此,她的 JSFiddle。
您还需要将整个 collapsible
部分包装在 div
中以便克隆。
Note: Using
.clone()
has the side-effect of producing elements with duplicateid
attributes, which are supposed to be unique. Where possible, it is recommended to avoid cloning elements with this attribute or using class attributes as identifiers instead.
所以,克隆后需要更新data-target
和div
id属性,这样新创建的按钮targets
就是新创建的折叠面板
我正在使用jQuery。
这是代码片段
$(function(){
var target = "collapsible_obj_";
var i = 1;
$("#button").click(function(){
$(".parent_colapse:last").clone().insertAfter(".parent_colapse:last");
$(".parent_colapse:last > button").attr("data-target", "#"+target+i);
$(".parent_colapse:last .collapse").attr("id", target+i);
i++;
});
$(document).on("click",".button",function(){
alert();
});
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div class="parent_colapse">
<button aria-expanded="false" data-target="#collapsible_obj_0" data-toggle="collapse" class="btn btn-link collapsed">click here</button>
<div style="height: 0px;" aria-expanded="false" id="collapsible_obj_0" class="collapse">
<span>foo</span>
<button type="button" class="button">click</button>
</div>
</div>
<button type="button" id="button">Clone</button>
关于你的问题你没有显示完整的script
这就是我们无法找到错误的原因。 LIKE 我们不知道 objectContainer
也 collapsibleObjCounter
那是什么?
我已经为您的代码创建了一个 JSFiddle。最可能的错误似乎是您使用 0
的 this.collapsibleObjCounter++
值可能会造成问题。
这是一个有效的 JSFiddle。请让我知道这是否是您想要做的。谢谢。
JS
$( document ).ready(function() {
for (i = 1; i < 5; i++) {
var objectContainer = $("#main");
var header = objectContainer.clone(true);
var counter = i; // replace this with this.collapsibleObjCounter++
var collapseId = "collapsible_obj_" + counter;
header.find(".collapse").attr("id", collapseId);
header.find("button[data-toggle='collapse']").attr("data-target", "#"+collapseId);
$(header).appendTo('body');
}
});
HTML
<div id="main">
<button aria-expanded="false" data-target="#collapsible_obj_0" data-toggle="collapse" class="btn btn-link collapsed">click here</button>
<div style="height: 0px;" aria-expanded="false" id="collapsible_obj_0" class="collapse">
<span>foo</span>
</div>
</div>
如果您在 this.collapsibleObjCounter++
中的值为 0
,那么我建议您做 ++this.collapsibleObjCounter
。而不是 post increment do pre increment
克隆时不要复制事件,删除 true
标志。
var header = objectContainer.clone();
我的猜测是 Bootstrap 正在为数据切换处理动态对象的事件绑定,它只需要有不同的 id 和目标。
这是一个 fiddle。
PS: 不知道 OP 问题中的 this 或 objectContainer 是什么,因此创建了一个闭包并在新包装器中粘贴结果。
问题不是由事件侦听器本身引起的。问题是 Bootstrap 是如何工作的。对于大多数 Bootstrap 组件,Bootstrap 创建一个与 DOM 元素关联的 JavaScript 对象。 克隆 Bootstrap 组件时需要注意此对象。 对于 collapse
元素,Bootstrap 创建一个 Collapse
object.
JavaScript 对象通过 jQuery 的 $.data
与 DOM 元素相关联。 这就是问题所在。如果您使用 jQuery 的 clone
并请求将事件处理程序复制到克隆,那么您还可以使用 $.data
获得数据集的副本。但是,当数据是对 JavaScript 对象的引用时,则它是被复制到克隆的 reference。所以原始对象和克隆对象指的是同一个 JavaScript 对象,这就是一切都误入歧途的地方。这对 Bootstrap 来说并不特别,顺便说一下:任何引用都会遇到这个问题。
您可以对 Bootstrap 组件的克隆元素执行 $.removeData
。这将强制 Bootstrap 重新创建 JavaScript 对象。对于自动注册数据 API 的组件,这应该是所有需要的。 (collapse
自动注册。)对于 不 自动注册的组件(例如工具提示),您需要调用 $.[component]
手动重新创建组件。
我 forked a fiddle from
将参数
true, true
添加到var header = objectContainer.clone();
修改
header.find(".collapse").attr("id", collapseId)
,在末尾添加.removeData()
。