Dapatkan indeks elemen sebagai anak relatif terhadap orangtua

160

Katakanlah saya memiliki markup ini:

<ul id="wizard">
    <li>Step 1</li>
    <li>Step 2</li>
</ul>

Dan saya punya jQuery ini:

$("#wizard li").click(function () {
    // alert index of li relative to ul parent
});

Bagaimana saya bisa mendapatkan indeks anak lirelatif terhadap orang tuanya, ketika mengklik itu li?

Misalnya, ketika Anda mengklik "Langkah 1", tanda alert"0" akan muncul.

AgileMeansDoAsLittleAsPossible
sumber

Jawaban:

247
$("#wizard li").click(function () {
    console.log( $(this).index() );
});

Namun daripada melampirkan satu penangan klik untuk setiap item daftar lebih baik (kinerja bijaksana) untuk menggunakan delegateyang akan terlihat seperti ini:

$("#wizard").delegate('li', 'click', function () {
    console.log( $(this).index() );
});

Di jQuery 1.7+, Anda harus menggunakan on. Contoh di bawah ini mengikat acara ke #wizardelemen, bekerja seperti acara delegasi:

$("#wizard").on("click", "li", function() {
    console.log( $(this).index() );
});
kotak merah
sumber
3
hi redsquare .. Saya berlatih dengan jQuery, saya agak n00b tentang delegasi: D .. mengapa mendelegasikan lebih baik daripada melampirkan acara langsung pada elemen?
stecb
1
@steweb - Hei - karena satu pengendali acara jauh lebih disukai daripada banyak yang berpotensi. Melampirkan acara ke dom bisa mahal jika Anda memiliki daftar besar sehingga sebagai aturan saya mencoba menggunakan di atas jika memungkinkan daripada penangan individu pada setiap elemen. Satu artikel yang masuk lebih dalam adalah briancrescimanno.com/2008/05/19/… - juga google 'delegasi acara javascript'
redsquare
ok, jadi, mengelola acara dengan cara ini adalah sesuatu yang lebih ringan daripada 'dom attachment' klasik :) ..terima kasih!
stecb
@Steweb - Ini juga lebih ringan karena jquery tidak perlu melakukan pencarian awal dari semua elemen li. Itu hanya mencari wadah dan mendengarkan pada tingkat itu untuk melihat apakah objek yang diklik adalah li.
redsquare
Metode .index ini sangat membantu saya. Saya menggunakan jQuery Sortable untuk melakukan pengurutan, tetapi menyimpan info peringkat semantik di DOM. Dengan .index (), saya dapat menarik peringkat keluar dari dom dengan sangat bersih. Terima kasih!
SimplGy
41

sesuatu seperti:

$("ul#wizard li").click(function () {
  var index = $("ul#wizard li").index(this);
  alert("index is: " + index)
});
Hancurkan
sumber
9
Tambahan yang bagus - kita dapat menemukan indeks relatif ke pemilih induk. +1
BasTaller
1
lebih suka jawaban ini karena sebenarnya menjawab pertanyaan daripada solusi yang mungkin untuk contoh
DarkMukke
8

Lihatlah contoh ini .

$("#wizard li").click(function () {
    alert($(this).index()); // alert index of li relative to ul parent
});
Kimtho6
sumber
4

Tidak perlu memerlukan perpustakaan besar seperti jQuery untuk mencapai ini, jika Anda tidak mau. Untuk mencapai hal ini dengan manipulasi DOM bawaan, dapatkan koleksi lisaudara kandung dalam array, dan saat klik, periksa indexOfelemen yang diklik di dalam array itu.

const lis = [...document.querySelectorAll('#wizard > li')];
lis.forEach((li) => {
  li.addEventListener('click', () => {
    const index = lis.indexOf(li);
    console.log(index);
  });
});
<ul id="wizard">
    <li>Step 1</li>
    <li>Step 2</li>
</ul>

Atau, dengan delegasi acara:

const lis = [...document.querySelectorAll('#wizard li')];
document.querySelector('#wizard').addEventListener('click', ({ target }) => {
  // Make sure the clicked element is a <li> which is a child of wizard:
  if (!target.matches('#wizard > li')) return;
  
  const index = lis.indexOf(target);
  console.log(index);
});
<ul id="wizard">
    <li>Step 1</li>
    <li>Step 2</li>
</ul>

Atau, jika elemen anak dapat berubah secara dinamis (seperti dengan daftar todo), maka Anda harus membuat array lis pada setiap klik, daripada sebelumnya:

const wizard = document.querySelector('#wizard');
wizard.addEventListener('click', ({ target }) => {
  // Make sure the clicked element is a <li>
  if (!target.matches('li')) return;
  
  const lis = [...wizard.children];
  const index = lis.indexOf(target);
  console.log(index);
});
<ul id="wizard">
    <li>Step 1</li>
    <li>Step 2</li>
</ul>

Performa Tertentu
sumber
$ (...). indexOf bukan sebuah fungsi
Kareem
2
Tidak ada cuplikan kode pada jawaban saya yang menghasilkan kesalahan itu - Anda dapat menekan "Run snippet code" untuk melihatnya berfungsi. Jika Anda mendapatkan kesalahan itu, Anda menggunakan kode yang berbeda - kedengarannya seperti Anda menggunakan jQuery, tetapi jawaban saya menunjukkan bagaimana menyelesaikan hal semacam ini tanpa jQuery
SpecificPerformance
Cukup adil. Ya, saya menggunakan JQuery. Terima kasih
Kareem
3

Delegasi dan Langsung mudah digunakan tetapi jika Anda tidak akan memiliki li: ditambahkan secara dinamis, Anda dapat menggunakan delagasi acara dengan bind / klik normal juga. Seharusnya ada beberapa peningkatan kinerja menggunakan metode ini karena DOM tidak harus dimonitor untuk elemen pencocokan baru. Belum punya angka sebenarnya tetapi masuk akal :)

$("#wizard").click(function (e) {
    var source = $(e.target);
    if(source.is("li")){
        // alert index of li relative to ul parent
        alert(source.index());
    }
});

Anda dapat mengujinya di jsFiddle: http://jsfiddle.net/jimmysv/4Sfdh/1/

jimmystormig
sumber
1
Apa yang Anda maksud ketika Anda mengatakan 'DOM ini tidak harus dimonitor'? delegasi jq tidak memantau dom.
redsquare
@redsquare Saya mendapat kesan bahwa Delegate hanyalah varian Live yang lebih efisien. Ini dari api.jquery.com/delegate : "Lampirkan handler ke satu atau lebih peristiwa untuk semua elemen yang cocok dengan pemilih, sekarang atau di masa depan, berdasarkan pada set elemen root tertentu." Itu harus pemantauan untuk mengikat di masa depan?
jimmystormig
tidak hanya menggunakan delegasi pada wadah seperti kode Anda di atas. Jika Anda memasukkan elemen li baru ke wadah acara klik wadah masih diaktifkan dan semuanya masih berfungsi. Tidak diperlukan pemantauan.
redsquare
@redsquare Ya, Anda benar. Solusi saya berfungsi bahkan jika ada elemen baru yang ditambahkan setelah DOM dimuat. Karena Delegasi menggunakan Live secara internal (lihat stackoverflow.com/questions/2954932/... ) masih terasa seperti ini lebih dioptimalkan tetapi kurang nyaman. Tapi seperti yang saya katakan, saya tidak punya nomor.
jimmystormig
2

Namun cara lain

$("#wizard li").click(function () 
{
    $($(this),'#wizard"').index();
});

Demo https://jsfiddle.net/m9xge3f5/

h0mayun
sumber