37

我正在向页面动态添加可折叠元素。Bootstrap 使用“data-target”属性来指定折叠切换适用于哪个元素。

从文档:

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 来设置 data-target 属性吗?为动态内容生成 ID 是标准方法吗?

4

7 回答 7

30

虽然data-target属性中的选择器确实是一个 jQuery 选择器,但该插件的 data-api 规范没有提供this在执行范围内引用的方法(参见bootstrap-collapse.js 中的第 147-153 行以了解其使用)。

但是,我想提供另一种替代方法,即使用您自己的自定义切换说明符扩展 data-api。我们称它为collapse-next

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 问题,而是 Bootstrap 问题。如果调用.collapse('toggle')一个Carousel对象未​​初始化的目标,该toggle()方法将被调用两次——一次在初始化期间,然后在初始化后再次显式调用。这绝对是一个 Bootstrap 错误,希望能得到修复。没有出现的唯一原因作为 Chrome、FF、IE10 等中的一个问题,是因为它们都支持 CSS 转换,因此当第二次调用时它会短路,因为第一个调用仍然处于活动状态。上面更新的解决方法只是通过首先检查初始化并以不同方式处理它来避免双重调用问题。

于 2012-10-09T23:18:55.713 回答
5

@merv 的解决方案在 IE9 及更低版本中对我不起作用,因为除非您单击每个项目一次,否则可折叠状态不可用。不过,它在 Firefox 和 Chrome 中运行良好。因此,单击两次后,一切正常。

我所做的是为触发元素设置一个类,然后使用set to.collapse-next强制它们的ul兄弟姐妹折叠:togglefalse

$(".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 的旧浏览器来说似乎也能胜任。

于 2013-03-21T14:59:58.493 回答
4

没有 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许多其他方式。

于 2017-07-09T10:59:23.997 回答
3

是的,你可以轻松做到!

只需将以下代码添加到您的脚本中即可享受:

$('body').on('click','[data-toggle="collapse"][data-mytarget^="$("]',function(){
     eval($(this).data('mytarget')).collapse('toggle');
});

现在,您可以在代码中的每个位置通过内部的完全动态 jQuery 命令data-mytarget设置折叠目标。

现在像这样使用它:

<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名字定义了我的不同属性。

于 2017-06-30T11:58:35.380 回答
1

我认为最好的方法是迭代所有accordion-toggle元素并data-target通过 jquery 动态设置它们的属性,然后放置 bootstrap 中提到的手风琴代码。

例子 :

$(function(){
    $("a.accordion-toggle").each(function(index) {
        $(this).attr("data-target", "#" + $(this).parent().next().attr("id"));
    });

    // accoridon code
});

希望这会有所帮助

于 2012-10-09T18:22:45.343 回答
0

TYPO3 FCE 和 Bootstrap 手风琴

我在这个问题上也遇到了一些麻烦,我在 TYPO3 中将它用于希望能够向手风琴添加无限数量的元素的客户。所以我创建了一个灵活的内容元素并映射了这些元素。

那个 data-toggle="collapse-next" 的想法并没有像预期的那样对我有用,因为它没有关闭打开的元素。我创建了一个新的 javascript 函数,请在此处找到代码。希望有人发现这些东西有用。

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>
于 2013-08-06T10:50:24.593 回答
0

这是一种避免需要唯一 ID 并避免特定 html 结构的方法。

这将折叠触发器和目标的每个实例包含在 html 的“部分”中。我喜欢使用类选择器,尤其是对于多个实例。在这种情况下,它避免了创建人为的唯一 ID。

借用@merv 的出色答案,我将 data-toggle 命名为collapse-section类似于他的collapse-next,并添加了一个 data-section 属性。这不是 parent().next(),而是查找最接近的 () 部分名称,然后查找给定的目标名称。他们可以是兄弟姐妹或任何其他级别。

(我有一个命名约定,使用“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();
});
于 2017-09-03T02:47:06.920 回答