我正在动态地将可折叠元素添加到页面。 Bootstrap 使用"数据目标"属性来指定折叠切换应用于哪个元素。
从文档中:
The data-target attribute accepts a css selector
有没有办法编写一个选择器来指定父元素的下一个同级? 文档中的所有示例似乎都使用按 ID 选择的内容。
具体来说,HTML 看起来像:
<div class="accordion-group">
<div class="accordion-heading">
<a class="accordion-toggle" data-toggle="collapse" data-target="#collapseOne">
Generated Title
</a>
</div>
<div id="collapseOne" class="accordion-body collapse in">
<div class="accordion-inner">
Generated Content... this is big and sometimes needs collapsing
</div>
</div>
</div>
我想写一些类似的东西(非法使用 jquery 语法的伪代码):
<a class="accordion-toggle" data-toggle="collapse" data-target="$(this).parent().next()">
但我开始怀疑CSS选择器可能无法做到这一点。
现在作为一种解决方法,我在创建元素时正在生成一个新 ID(附加到字符串的递增数字)。
使用选择器有更好的方法吗? 我应该使用一些创建后的 javascript 来设置数据目标属性吗?为动态内容生成 ID 是标准方法吗?
虽然data-target
属性中的选择器确实是 jQuery 选择器,但此插件的数据 api 规范不提供在执行范围内引用回this
的方法(参见 bootstrap-collapse.js 中的第 147-153 行)。
但是,我想提供另一种替代方法,即使用您自己的自定义切换说明符扩展数据 API。 我们称之为崩溃-下一个。
JS(请参阅更新说明)
$('body').on('click.collapse-next.data-api', '[data-toggle=collapse-next]', function (e) {
var $target = $(this).parent().next()
$target.data('collapse') ? $target.collapse('toggle') : $target.collapse()
})
.HTML
<a class="accordion-toggle" data-toggle="collapse-next">
JSFiddle (更新)
这里的缺点是它是一种相当紧密耦合的方法,因为 JS 假定标记的特定结构。
有关 IE 问题的注意事项
正如@slhck在他的回答中指出的那样,IE9及以下版本在使用我的答案的早期版本时第一次点击显然失败。 原因实际上根本不是IE问题,而是引导问题。 如果在Carousel
对象未初始化的目标上调用.collapse('toggle')
,则将调用toggle()
方法两次 - 一次在初始化期间,然后在初始化后再次显式调用。 这绝对是一个引导错误,希望能得到修复。 它在Chrome,FF,IE10等中不会出现问题的唯一原因是因为它们都支持CSS转换,因此当进行第二次调用时,它会短路,因为第一次调用仍然处于活动状态。 上面更新的解决方法只是通过首先检查初始化并以不同的方式处理它来避免双重调用问题。
没有javascript解决方案或解决方案依赖于已经在使用的bootstrap的JS,只是利用DOM结构
请参阅data-target=""
...
避免笨重的解决方案并且不需要ID或额外的JS的提示,使用标记放置的技巧-
<button data-toggle="collapse" data-target=".dropdown-toggle:hover + .more-menu" type="button" class="btn btn-primary dropdown-toggle" >
Show More Menu +
</button>
<div class="collapse more-menu">More menu here...</div>
这个CSS选择结构将选择所需的DOM.dropdown-toggle:hover + .more-menu
在那里我们可以应用我们想要的CSS。 还有更多方法可以利用我们所拥有的。:hover
或:active
或许多其他方式。
@merv的解决方案在IE9及更低版本中对我不起作用,因为除非您单击每个项目一次,否则可折叠状态不可用。不过,它在Firefox和Chrome中确实工作正常。因此,单击两次后,一切都会正常工作。
我所做的是为触发元素设置一个.collapse-next
类,然后强制他们的ul
兄弟姐妹折叠,toggle
设置为false
:
$(".collapse-next").closest('li').each(function(){
if ($(this).hasClass('active')) {
// pop up active menu items
$(this).children("ul").collapse('show');
} else {
// just make it collapsible but don't expand
$(this).children("ul").collapse({ toggle: false });
}
});
这是为了实际切换菜单状态:
$('.collapse-next').click(function(e){
e.preventDefault();
$(this).parent().next().collapse('toggle');
});
似乎使用data-
属性是一种更现代、更干净的方法,但对于使用类和 jQuery 的旧浏览器来说,似乎也可以完成这项工作。
是的,你可以很容易地做到! 😎
只需将以下代码添加到您的脚本中即可享受:😃
$('body').on('click','[data-toggle="collapse"][data-mytarget^="$("]',function(){
eval($(this).data('mytarget')).collapse('toggle');
});
现在,在代码中的每个位置,您都可以通过data-mytarget
中的完全动态的jQuery命令来设置折叠目标。
现在像这样使用它:
<a data-toggle="collapse" data-mytarget="$(this).parent().next()">Link</a>
或
<a data-toggle="collapse" data-mytarget="$('#TopMenuBar').closest('ul')">Link</a>
或
<a data-toggle="collapse" data-mytarget="[ EACH IDEAl JQUERY CODE OF YOU STARTED WITH $( ]">Link</a>
演示:
$('body').on('click','[data-toggle="collapse"][data-mytarget^="$("]',function(){
eval($(this).data('mytarget')).collapse('toggle');
});
a{
padding:10px;
cursor:pointer;
margin:20px;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div class="accordion-group">
<div class="accordion-heading">
<a class="accordion-toggle btn btn-info" data-toggle="collapse" data-mytarget="$(this).parent().next()">Collapse It</a>
</div>
<div id="collapseOne" class="accordion-body collapse ">
<div class="accordion-inner">
Generated Content... this is big and sometimes needs collapsing
</div>
</div>
</div>
我用
data-mytarget
代替data-target
.如果你使用data-target
它也可以工作,但jQuery库会引发如下错误:Uncaught Error: Syntax error, unrecognized expression: $(this).parent().next()
。所以我用
data-mytarget
的名字定义了我的不同属性。
我认为最好的方法是迭代所有accordion-toggle
元素并通过jquery动态设置它们的data-target
属性,然后放置引导中提到的手风琴代码。
例:
$(function(){
$("a.accordion-toggle").each(function(index) {
$(this).attr("data-target", "#" + $(this).parent().next().attr("id"));
});
// accoridon code
});
希望这会有所帮助
TYPO3 FCE 和 Bootstrap Accordion
我也遇到了这个问题,我在 TYPO3 中为希望能够向手风琴添加无限数量元素的客户使用它.因此,我创建了一个灵活的内容元素并映射了这些元素。
data-toggle="collapse-next"的想法并没有像预期的那样对我有用,因为它没有关闭打开的元素。我创建了一个新的javascript函数,请在此处找到代码。希望有人发现这些东西有用。
爪哇语
$(document).on('click.collapse-next.data-api', '[data-toggle=collapse-next]', function (e) {
var $container = $(this).parents(".accordion");
var $opencontainers = $container.find(".in");
var $target = $(this).parent().next();
$target.data('collapse') ? $target.collapse('toggle') : $target.collapse();
$opencontainers.each(function() {$(this).collapse('toggle')});
})
.HTML
<html>
<div class="accordion">
<div class="accordion-section">
<div class="accordion-group">
<div class="accordion-heading">
<a class="accordion-toggle" data-toggle="collapse-next">
Collapsible Group Item #1
</a>
</div>
<div class="accordion-body collapse">
<div class="accordion-inner">
Anim pariatur cliche...
</div>
</div>
</div>
</div>
</div>
</html>
这是一种避免需要唯一 ID 并避免特定 html 结构的方法。
这会将折叠触发器和目标的每个实例包含在 html 的"部分"中。我喜欢使用类选择器,尤其是对于多个实例。在这种情况下,它避免了创建人工唯一 ID。
借用@merv的出色答案,我将数据切换collapse-section
命名为类似于他的collapse-next
,并添加了一个数据部分属性。 而不是 parent().next(),它会查找 closest() 节名称,然后查找给定的目标名称。他们可以是兄弟姐妹或任何其他级别。
(我有一个命名约定,使用"id..."作为用作jquery选择器的类名的前缀,以避免与样式混合。
.HTML
<div class="accordion-group idCollapseSection">
<div class="accordion-heading">
<a class="accordion-toggle" data-toggle="collapse-section"
data-section=".idCollapseSection" data-target=".idCollapseTarget">
Generated Title
</a>
</div>
<div>Any other html, at various depths.
<div class="accordion-body collapse in idCollapseTarget">
<div class="accordion-inner">
Generated Content... this is big and sometimes needs collapsing
</div>
</div>
</div>
</div>
.JS
//------------------------------
// Bootstrap Collapse.
//------------------------------
// Extend collapse to contain trigger and target within an enclosing section.
$('body').on('click.collapse-section.data-api', '[data-toggle=collapse-section]', function (e) {
var thisTrigger = $(this);
var sectionSelector = thisTrigger.data("section");
var targetSelector = thisTrigger.data("target");
var target = thisTrigger.closest(sectionSelector).find(targetSelector);
target.data('bs.collapse') ? target.collapse('toggle') : target.collapse();
});