Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
482 views
in Technique[技术] by (71.8m points)

javascript - Can you specify a "data-target" for Bootstrap which refers to a sibling DOM element without using an ID?

I am dynamically adding Collapsable elements to a page. Bootstrap uses the "data-target" attribute to specify which element the collapse toggle applies to.

From the docs:

The data-target attribute accepts a css selector

Is there a way to write a selector which specifies the next sibling of the parent element? All of the examples from the docs seem to use selections by ID.

Specifically the HTML looks like:

<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>

I would like to write something like (pseudo code using jquery syntax illegally):

<a class="accordion-toggle" data-toggle="collapse" data-target="$(this).parent().next()">

But I am starting to suspect this may not be possible with CSS selectors.

Right now as a workaround I am generating a new ID (an incrementing number appended to a string) when I create the element.

Is there a nicer approach using a selector? Should I be using some post-creation javascript to set the data-target attribute? Is generating IDs for dynamic content the standard approach?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

While it is true that the selector in a data-target attribute is a jQuery selector, the data-api specification for this plugin provides no means of referencing back to this in the scope of execution (see lines 147-153 in bootstrap-collapse.js for its use).

However, I would like to offer another alternative approach, which is to extend the data-api with your own custom toggle specifier. Let's call it collapse-next.

JS (see update note)

$('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 (updated)

Downside here is that it's a rather tightly coupled approach, since the JS presumes a specific structure to the markup.


Note about IE issues

As @slhck pointed out in his answer, IE9 and under apparently fail on the first click when using an earlier revision of my answer. The cause is actually not an IE issue at all, but rather a Bootstrap one. If one invokes .collapse('toggle') on a target whose Carousel object is uninitialized, the toggle() method will be called twice - once during initialization and then again explicitly after initialization. This is definitely a Bootstrap bug and hopefully will get fixed. The only reason it doesn't appear as a problem in Chrome, FF, IE10, etc, is because they all support CSS transitions, and hence when the second call is made it short-circuits because the first one is still active. The updated workaround above merely avoids the double-call problem by checking for initialization first and handling it differently.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...