使用事件侦听器克隆引导程序元素
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
更改为指向新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是对象容器I正在克隆的子级。
有时这是可行的,但有时我会得到一个仍然可以扩展和收缩原始div的按钮,即使当我检查HTML时,ID看起来是正确的。
我怀疑复制的事件处理程序可能对要扩展和收缩的div的id的引用进行了硬编码,这就是为什么仅仅修复DOM元素中的id是不起作用的。然而,这并不能解释为什么有些克隆有效,而另一些则无效。
克隆带有引导行为的东西的正确方法是什么?
因此,有几个答案指出,仅从clone()
调用中删除true
就可以避免复制事件侦听器。所以我现在意识到我的问题比我在这里过于简单化的问题要复杂一些。我将单独提问。(克隆一个Bootstrap元素,但不是所有的事件侦听器)
到目前为止,您的代码还可以,只需从clone()
中删除true
即可,这是不需要的。
更新
此布尔值指示是否应将事件处理程序与元素一起复制。默认值为false。因此,当我们在不传递任何布尔值的情况下调用
.clone()
方法时,它只是复制元素,而不是附加到它的事件处理程序。但是,当我们传递值true时,它会复制元素和附加到它上的任何event处理程序。
但是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.
但是
您需要使用事件委派技术为动态对象处理事件。
$(document).on("click",".btn",function(){ .... });
这将起作用,因为事件处理程序绑定到DOM
树(在本例中为文档)的更高的元素,并且将在事件到达该元素时执行,该元素源自与选择器匹配的元素,这就是Bootstrap为动态对象所做的,如果需要,也可以为动态对象做同样的操作。她是JSFiddle。
此外,您还需要将整个collapsible
部分封装在div
中进行克隆。
注意:使用
.clone()
会产生具有重复id
属性的元素,这些属性本应是唯一的。在可能的情况下,建议避免克隆具有此属性的元素或使用类属性作为标识符。
因此,您需要在克隆后更新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
那是什么?
克隆时不要复制事件,请删除true
标志。
var header = objectContainer.clone();
我的猜测是Bootstrap正在处理动态对象的事件绑定,也用于数据切换,它只需要有不同的id;目标
这是一把小提琴。
PS:在OP的问题中,不知道这个或objectContainer是什么,所以在新的包装器中创建了一个闭包并粘贴结果。
问题不是由事件侦听器本身引起的。问题是Bootstrap是如何工作的。对于大多数Bootstrap组件,Bootstrap创建一个与DOM元素相关联的JavaScript对象在克隆引导程序组件时,需要注意这个对象对于collapse
元素,Bootstrap会创建一个Collapse
对象。
JavaScript对象通过jQuery的$.data
与DOM元素相关联这就是问题所在。如果您使用jQuery的clone
并请求将事件处理程序复制到克隆,那么您还可以使用$.data
获得数据集的副本。但是,如果数据是对JavaScript对象的引用,则复制到克隆的是引用。因此,原始和克隆引用了同一个JavaScript对象,这就是一切出错的地方。顺便说一句,这对Bootstrap来说并不特殊:任何引用都会受到这个问题的影响。
您可以对作为引导组件的克隆元素执行$.removeData
。这将强制Bootstrap重新创建JavaScript对象。对于自动注册到数据API中的组件,这应该是所有需要的。(collapse
自动注册。)对于不自动注册的组件(例如工具提示),您需要调用$.[component]
手动重新创建组件。
我从一个ManHasNoName的小提琴上拨出了一把小提琴来说明这一点。唯一的修改是:
-
将参数
true, true
添加到var header = objectContainer.clone();
-
修改
header.find(".collapse").attr("id", collapseId)
,在末尾添加.removeData()
。
我已经为您的代码创建了一个JSFiddle。在您看来,最可能的错误是使用0
的this.collapsibleObjCounter++
值可能会产生问题。
这是一个正在工作的JSFiddle。如果你想这么做,请告诉我。谢谢。
https://jsfiddle.net/2fgoywzy/1/
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
。不执行增量后执行
- Html引导程序警报自动关闭困难
- 引导程序:在导航栏中,显示悬停在单个位置的基于Li Link的不同内容
- 如何在引导程序元素的顶部添加掩码
- 一个轮播页面引导程序中的多个元素
- 转换元素在引导程序中不起作用
- 如何确保元素的位置在引导程序2中是固定的
- Twitter 引导程序提前类型无法添加到动态创建的元素
- 引导程序使用 js 检查/取消选中多个元素
- 引导程序折叠,仅显示一个元素
- 向引导程序标记输入元素添加标记时发生类型错误:f[c]
- 如何将JavaScript应用于引导程序btn组以选择/取消选择子按钮元素
- 将引导程序下拉列表附加到不同的元素
- 在屏幕调整大小时为引导程序元素分配新类不起作用
- 如何在引导程序下拉列表中获取Selected元素,其中下拉列表是动态填充的
- 引导程序scrollspy跳过第一个元素
- 为引导程序元素加载cookie的更好方法
- 使用事件侦听器克隆引导程序元素
- 引导程序中的导航元素居中
- AngularJS不"引导程序”;新的DOM元素
- 在注入的元素上激活引导程序日期选择器