Подтвердить что ты не робот

Можете ли вы указать "цель данных" для Bootstrap, которая ссылается на элемент DOM sibling без использования идентификатора?

Я динамически добавляю Collapsable элементы на страницу. Bootstrap использует атрибут "data-target", чтобы указать, к какому элементу применяется коллапс.

Из документов:

The data-target attribute accepts a css selector

Есть ли способ написать селектор, который задает следующий родственный элемент родительского элемента? Все примеры из документов, похоже, используют выбор по идентификатору.

В частности, 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.

В качестве обходного пути я создаю новый идентификатор (добавочное число, добавленное к строке), когда я создаю элемент.

Есть ли более удобный подход с помощью селектора? Должен ли я использовать какой-либо пост-созданный javascript для установки атрибута data-target? Является ли генерация идентификаторов для динамического контента стандартным подходом?

4b9b3361

Ответ 1

Хотя верно, что селектор в атрибуте data-target является селектором jQuery, спецификация data-api для этого плагина не позволяет ссылаться на this в области выполнения (см. строки 147-153 в bootstrap-collapse.js для его использования).

Однако я хотел бы предложить еще один альтернативный подход, который заключается в расширении data-api с помощью вашего собственного спецификатора toggle. Позвольте называть его 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, и, следовательно, когда второй вызов выполняется, он замыкается, потому что первый из них все еще активен. Обновленное обходное решение выше просто устраняет проблему двойного вызова, сначала проверяя инициализацию и обрабатывая ее по-разному.

Ответ 2

Решение @merv не работало для меня в IE9 и ниже, так как сбрасываемое состояние недоступно, если вы не щелкнули по каждому элементу один раз. Однако он отлично работал в Firefox и Chrome. Поэтому после двух кликов все будет работать.

То, что я сделал, было установлено классом .collapse-next для элементов запуска, а затем принудительно свернуть их ul siblings с 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, похоже, тоже выполняет эту работу.

Ответ 3

Я думаю, что лучший подход состоит в том, чтобы сделать это, перебирать все элементы accordion-toggle и динамически устанавливать атрибут data-target через jquery и после этого поместить код аккордеона, упомянутый в bootstrap.

Пример:

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

    // accoridon code
});

Надеюсь, это поможет

Ответ 4

Да, вы можете сделать это легко! 😎

Просто добавьте следующий код в свои скрипты и наслаждайтесь: 😃

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

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>

Ответ 5

TYPO3 FCE и бутстрап-аккордеон

У меня возникают некоторые проблемы с этой проблемой, поэтому я использую ее в 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>

Ответ 6

См. data-target=""...

Подсказка для простого способа уменьшить объемные решения -

....
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="collapse" data-target=".dropdown-toggle:hover + .more-menu">
    Toggle Bagal Wala
  </button>
  <div class="collapse more-menu">
....

Ответ 7

Вот подход, который позволяет избежать необходимости в уникальных идентификаторах и избегать конкретной структуры html.

В этом случае каждый экземпляр триггера и цели слияния включается в "раздел" html. Мне нравится использовать селектор классов, особенно для нескольких экземпляров. В этом случае он избегает создания искусственных уникальных идентификаторов.

Заимствование из превосходного ответа @merv, я назвал data-toggle collapse-section похожим на его collapse-next и добавил атрибут раздела данных. Вместо 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();
});