Javascript 你能在不使用 ID 的情况下为 Bootstrap 指定一个引用同级 DOM 元素的“数据目标”吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12805825/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can you specify a "data-target" for Bootstrap which refers to a sibling DOM element without using an ID?
提问by Soverman
I am dynamically adding Collapsable elements to a page. Bootstrap uses the "data-target" attribute to specify which element the collapse toggle applies to.
我正在向页面动态添加可折叠元素。Bootstrap 使用“data-target”属性来指定折叠切换应用于哪个元素。
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.
有没有办法编写一个选择器来指定父元素的下一个兄弟元素?文档中的所有示例似乎都使用 ID 选择。
Specifically the HTML looks like:
具体来说,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>
I would like to write something like (pseudo code using jquery syntax illegally):
我想写一些类似的东西(非法使用 jquery 语法的伪代码):
<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.
但我开始怀疑 CSS 选择器可能无法做到这一点。
Right now as a workaround I am generating a new ID (an incrementing number appended to a string) when I create the element.
现在,作为一种解决方法,我在创建元素时生成一个新 ID(附加到字符串的递增数字)。
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?
使用选择器有更好的方法吗?我应该使用一些创建后的 javascript 来设置 data-target 属性吗?为动态内容生成 ID 是标准方法吗?
采纳答案by merv
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.jsfor its use).
虽然data-target
属性中的选择器确实是一个 jQuery 选择器,但该插件的 data-api 规范没有提供返回this
执行范围的方法(请参阅bootstrap-collapse.js中的第147-153 行以了解其用法)。
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.
但是,我想提供另一种替代方法,即使用您自己的自定义切换说明符扩展 data-api。我们称它为collapse-next。
JS (see update note)
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
HTML
<a class="accordion-toggle" data-toggle="collapse-next">
JSFiddle (updated)
JSFiddle(更新)
Downside here is that it's a rather tightly coupled approach, since the JS presumes a specific structure to the markup.
这里的缺点是它是一种相当紧密耦合的方法,因为 JS 假定标记具有特定的结构。
Note about IE issues
关于 IE 问题的注意事项
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 appearas 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.
正如@slhck 在他的回答中指出的那样,使用我的回答的早期修订版时,IE9 及以下显然在第一次点击时失败。原因实际上根本不是 IE 问题,而是 Bootstrap 问题。如果调用对象未初始化.collapse('toggle')
的目标,Carousel
则该toggle()
方法将被调用两次 - 一次在初始化期间,然后在初始化之后显式地再次调用。这绝对是一个 Bootstrap 错误,希望能得到修复。它没有出现的唯一原因Chrome、FF、IE10 等中的一个问题是因为它们都支持 CSS 转换,因此当第二次调用时它会短路,因为第一个调用仍然处于活动状态。上面更新的解决方法只是通过首先检查初始化并以不同方式处理它来避免双重调用问题。
回答by slhck
@merv's solution didn't work for me in IE9 and below, since the collapsible state wasn't available unless you clicked at each item once. It did work fine in Firefox and Chrome though. So after two clicks, everything would work.
@merv 的解决方案在 IE9 及更低版本中对我不起作用,因为除非您单击每个项目一次,否则可折叠状态不可用。不过它在 Firefox 和 Chrome 中运行良好。因此,单击两次后,一切都会正常进行。
What I did was set a .collapse-next
class to the triggering elements, then force their ul
siblings to collapse with toggle
set to false
:
我所做的是.collapse-next
为触发元素设置一个类,然后ul
使用toggle
set to强制他们的兄弟姐妹崩溃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 });
}
});
This is for actually toggling the menu state:
这是用于实际切换菜单状态:
$('.collapse-next').click(function(e){
e.preventDefault();
$(this).parent().next().collapse('toggle');
});
It seems that using data-
attributes is a somewhat more modern and cleaner approach, but for old browsers working with classes and jQuery seems to do the job as well.
似乎使用data-
属性是一种更现代和更简洁的方法,但对于使用类和 jQuery 的旧浏览器似乎也能完成这项工作。
回答by RAM
Yes, you can do it easily!
是的,您可以轻松做到!
Just add the following code to your scripts and enjoy:
只需将以下代码添加到您的脚本中即可享受:
$('body').on('click','[data-toggle="collapse"][data-mytarget^="$("]',function(){
eval($(this).data('mytarget')).collapse('toggle');
});
Now every where in your code you can set the target of collapse by a fully dynamic jQuery commandinside data-mytarget
.
现在,每一个地方在你的代码,你可以通过设置崩溃的目标完全动态的jQuery命令中data-mytarget
。
Now use it like it:
现在像这样使用它:
<a data-toggle="collapse" data-mytarget="$(this).parent().next()">Link</a>
or
或者
<a data-toggle="collapse" data-mytarget="$('#TopMenuBar').closest('ul')">Link</a>
or
或者
<a data-toggle="collapse" data-mytarget="[ EACH IDEAl JQUERY CODE OF YOU STARTED WITH $( ]">Link</a>
Demo:
演示:
$('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>
I used
data-mytarget
instead ofdata-target
. If you usedata-target
it works too but the jQuery library raise an error like this:Uncaught Error: Syntax error, unrecognized expression: $(this).parent().next()
.So I defined my different property with
data-mytarget
name.
我用
data-mytarget
而不是data-target
. 如果你使用data-target
它的作品太多,但jQuery库养这样的错误:Uncaught Error: Syntax error, unrecognized expression: $(this).parent().next()
。所以我用
data-mytarget
名字定义了我的不同属性。
回答by Vishal Kumar Sahu
No javascriptsolution or it depends on bootstrap's js already in use, just exploiting the DOM structure-
没有 javascript解决方案,或者它依赖于已经在使用的 bootstrap js,只是利用了 DOM 结构-
See the data-target=""
...
看到data-target=""
...
A hint for easy way to reduce the bulky solutions-
减少笨重解决方案的简单方法的提示-
<button
data-toggle="collapse"
data-target=".dropdown-toggle:hover + .more-menu"
type="button"
class="btn btn-primary dropdown-toggle"
>
Toggle Bagal Wala
</button>
<div class="collapse more-menu">I will be toggled</div>
This CSS selection structure will select the desired DOM .dropdown-toggle:hover + .more-menu
and there we can apply our desired CSS.
There are more ways to exploit what we have. :hover
or :active
or so many other ways.
这个 CSS 选择结构将选择所需的 DOM,.dropdown-toggle:hover + .more-menu
然后我们可以应用所需的 CSS。有更多的方法可以利用我们拥有的东西。:hover
或:active
或许多其他方式。
回答by Kundan Singh Chouhan
I think the best approach would be to do this iterate all accordion-toggle
elements and set their data-target
attribute dynamically via jquery and after that place the code of accordion mentioned in bootstrap.
我认为最好的方法是迭代所有accordion-toggle
元素并data-target
通过 jquery 动态设置它们的属性,然后放置 bootstrap 中提到的手风琴代码。
Example :
例子 :
$(function(){
$("a.accordion-toggle").each(function(index) {
$(this).attr("data-target", "#" + $(this).parent().next().attr("id"));
});
// accoridon code
});
Hope this will help
希望这会有所帮助
回答by Thomas
TYPO3 FCE and Bootstrap Accordion
TYPO3 FCE 和 Bootstrap 手风琴
I am having some trouble with this issue too i am using it in TYPO3 for a customer who wants to be able to add an infinite number of elements to the accordion. So I created a Flexible Content Element and mapped the elements.
我在这个问题上也遇到了一些麻烦,我在 TYPO3 中为希望能够向手风琴添加无限数量元素的客户使用它。所以我创建了一个灵活的内容元素并映射了这些元素。
The idea with that data-toggle="collapse-next" did not work for me as expected as it did not close the open elements. I created a new javascript-function doing that please find the code here. Hopefully someone finds the stuff useful.
使用 data-toggle="collapse-next" 的想法对我没有预期的效果,因为它没有关闭打开的元素。我创建了一个新的 javascript 函数,请在此处找到代码。希望有人发现这些东西有用。
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
<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>
回答by goodeye
Here is an approach that avoids needing unique IDs and avoids a specific html structure.
这是一种避免需要唯一 ID 并避免特定 html 结构的方法。
This encloses each instance of the collapse trigger and target in a "section" of html. I like to use class selectors, especially for multiple instances. In this case, it avoids having to create artificial unique IDs.
这将折叠触发器和目标的每个实例包含在 html 的“部分”中。我喜欢使用类选择器,尤其是对于多个实例。在这种情况下,它避免了必须创建人工唯一 ID。
Borrowing from @merv's excellent answer, I named the data-toggle collapse-section
similar to his collapse-next
, and added a data-section attribute.
Instead of parent().next(), this looks up for a closest() section name, then down for the given target name. They can be siblings or any other level.
借用@merv 的出色回答,我将 data-toggle 命名为collapse-section
类似于他的collapse-next
,并添加了一个 data-section 属性。它不是 parent().next(),而是查找最接近的 () 部分名称,然后向下查找给定的目标名称。他们可以是兄弟姐妹或任何其他级别。
(I have a naming convention using "id..." as a prefix for class names that are used as jquery selectors, to avoid mixing with styling.)
(我有一个命名约定,使用“id ...”作为用作 jquery 选择器的类名的前缀,以避免与样式混合。)
HTML
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
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();
});