Pertanyaan Dapatkah Anda menetapkan "target data" untuk Bootstrap yang mengacu pada elemen DOM saudara tanpa menggunakan ID?


Saya menambahkan elemen Collapsable ke halaman secara dinamis. Bootstrap menggunakan atribut "target data" untuk menentukan elemen mana yang beralih toggle ke.

Dari dokumen:

The data-target attribute accepts a css selector

Apakah ada cara untuk menulis pemilih yang menentukan saudara kandung selanjutnya dari elemen induk? Semua contoh dari dokumen tampaknya menggunakan pilihan berdasarkan ID.

Khususnya HTML terlihat seperti:

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

Saya ingin menulis sesuatu seperti (pseudo code menggunakan sintaks jquery secara ilegal):

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

Tapi saya mulai mencurigai ini tidak mungkin dengan pemilih CSS.

Saat ini sebagai solusi saya menghasilkan ID baru (nomor tambahan yang ditambahkan ke string) ketika saya membuat elemen.

Apakah ada pendekatan yang lebih baik menggunakan pemilih? Haruskah saya menggunakan javascript pasca-pembuatan untuk menetapkan atribut target data? Apakah menghasilkan ID untuk konten dinamis merupakan pendekatan standar?


32
2017-10-09 18:05


asal


Jawaban:


Meskipun memang benar bahwa pemilih dalam data-target Atribut adalah pemilih jQuery, spesifikasi data-api untuk plugin ini tidak menyediakan sarana referensi kembali ke this dalam lingkup eksekusi (lihat baris 147-153 di bootstrap-collapse.js untuk penggunaannya).

Namun, saya ingin menawarkan pendekatan alternatif lain, yaitu untuk memperpanjang data-api dengan specifier beralih kustom Anda sendiri. Sebut saja runtuh berikutnya.

JS (lihat catatan pembaruan)

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

Kelemahan di sini adalah bahwa ini adalah pendekatan yang agak erat, karena JS mengandaikan struktur tertentu pada markup.


Catatan tentang masalah IE

Sebagai @slhck menunjukkan jawabannya, IE9 dan di bawah tampaknya gagal pada klik pertama ketika menggunakan revisi sebelumnya dari jawaban saya. Penyebabnya sebenarnya bukan masalah IE sama sekali, melainkan Bootstrap satu. Jika seseorang memanggil .collapse('toggle') pada target yang Carousel objek tidak diinisialisasi, yang toggle() metode akan dipanggil dua kali - sekali selama inisialisasi dan kemudian lagi secara eksplisit setelah inisialisasi. Ini jelas merupakan bug Bootstrap dan semoga akan diperbaiki. Satu-satunya alasan tidak muncul sebagai masalah di Chrome, FF, IE10, dll, adalah karena semuanya mendukung transisi CSS, dan karenanya ketika panggilan kedua dibuat menjadi sirkuit pendek karena yang pertama masih aktif. Solusi yang diperbarui di atas hanya menghindari masalah double-call dengan memeriksa inisialisasi terlebih dahulu dan menanganinya secara berbeda.


25
2017-10-09 23:18



Solusi @ merv tidak bekerja untuk saya di IE9 dan di bawah, karena negara yang dilipat tidak tersedia kecuali Anda mengklik setiap item sekali. Itu berfungsi baik di Firefox dan Chrome sekalipun. Jadi setelah dua klik, semuanya akan berfungsi.

Apa yang saya lakukan adalah mengatur .collapse-next kelas ke elemen pemicu, lalu paksakan ul saudara kandung untuk runtuh toggle mulai 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 });
  }
});

Ini untuk benar-benar mengubah status menu:

$('.collapse-next').click(function(e){
  e.preventDefault();
  $(this).parent().next().collapse('toggle');
});

Tampaknya menggunakan data- atribut adalah pendekatan yang agak lebih modern dan lebih bersih, tetapi untuk browser lama yang bekerja dengan kelas dan jQuery tampaknya melakukan pekerjaan itu juga.


4
2018-03-21 14:59



Saya pikir pendekatan terbaik adalah melakukan iterate semua ini accordion-toggle elemen dan mengatur mereka data-target atribut secara dinamis melalui jquery dan setelah itu letakkan kode akordeon yang disebutkan di bootstrap.

Contoh: 

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

    // accoridon code
});

Semoga ini bisa membantu


1
2017-10-09 18:22



Ya, Anda dapat melakukannya dengan mudah!

Cukup tambahkan kode berikut ke skrip Anda dan nikmati: 

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

Sekarang setiap tempat di kode Anda, Anda dapat mengatur target runtuhnya oleh perintah jQuery sepenuhnya dinamis dalam data-mytarget.

Sekarang gunakan seperti itu:

<a data-toggle="collapse" data-mytarget="$(this).parent().next()">Link</a>

atau

<a data-toggle="collapse" data-mytarget="$('#TopMenuBar').closest('ul')">Link</a>

atau

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

Saya menggunakan data-mytarget dari pada data-target. Jika Anda menggunakan data-target ia bekerja juga tetapi pustaka jQuery memunculkan kesalahan seperti ini: Uncaught Error: Syntax error, unrecognized expression: $(this).parent().next().

Jadi saya mendefinisikan properti saya yang berbeda dengan data-mytarget nama.


1
2018-06-30 11:58



Tidak ada javascript solusi atau tergantung pada js bootstrap yang sudah digunakan, hanya mengeksploitasi struktur DOM-

Lihat data-target=""...

Petunjuk untuk cara mudah mengurangi solusi besar-

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

Struktur pemilihan CSS ini akan memilih DOM yang diinginkan .dropdown-toggle:hover + .more-menu dan di sana kami dapat menerapkan CSS yang kami inginkan.


1
2017-07-09 10:59



TYPO3 FCE dan Accordion Bootstrap

Saya mengalami masalah dengan masalah ini juga saya menggunakannya dalam TYPO3 untuk pelanggan yang ingin dapat menambahkan jumlah elemen yang tak terbatas ke akordeon. Jadi saya membuat Elemen Konten Fleksibel dan memetakan elemen.

Ide dengan data-toggle = "collapse-next" tidak bekerja untuk saya seperti yang diharapkan karena tidak menutup elemen terbuka. Saya membuat fungsi javascript baru melakukan itu silakan temukan kode di sini. Semoga seseorang menemukan hal-hal yang bermanfaat.

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>

0
2017-08-06 10:50



Berikut ini adalah pendekatan yang tidak memerlukan ID unik dan menghindari struktur html tertentu.

Ini membungkus setiap instance dari pemicu penciutan dan target dalam "bagian" html. Saya suka menggunakan pemilih kelas, terutama untuk beberapa contoh. Dalam hal ini, ia menghindari harus membuat ID unik buatan.

Meminjam dari jawaban yang sangat baik dari @ merv, saya menamai tombol pengalih data collapse-section mirip dengannya collapse-next, dan menambahkan atribut bagian data. Daripada induk (). Berikutnya (), ini mencari nama bagian () terdekat, kemudian ke bawah untuk nama target yang diberikan. Mereka bisa saudara kandung atau tingkat lainnya.

(Saya memiliki konvensi penamaan menggunakan "id ..." sebagai awalan untuk nama kelas yang digunakan sebagai pemilih jquery, untuk menghindari pencampuran dengan styling.)

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();
});

0
2017-09-03 02:47