Apakah ada cara untuk memilih node saudara?

104

Untuk beberapa alasan kinerja, saya mencoba menemukan cara untuk memilih hanya simpul saudara dari simpul yang dipilih.

Sebagai contoh,

<div id="outer">
  <div id="inner1"></div>
  <div id="inner2"></div>
  <div id="inner3"></div>
  <div id="inner4"></div>
</div>

Jika saya memilih node inner1, apakah ada cara bagi saya untuk mengakses saudara kandungnya, inner2-4node?

codingbear
sumber

Jawaban:

141

Baiklah ... tentu ... akses saja orang tua dan kemudian anak-anak.

 node.parentNode.childNodes[]

atau ... menggunakan jQuery:

$('#innerId').siblings()

Sunting: Cletus seperti biasa menginspirasi. Saya menggali lebih jauh. Inilah cara jQuery mendapatkan saudara pada dasarnya:

function getChildren(n, skipMe){
    var r = [];
    for ( ; n; n = n.nextSibling ) 
       if ( n.nodeType == 1 && n != skipMe)
          r.push( n );        
    return r;
};

function getSiblings(n) {
    return getChildren(n.parentNode.firstChild, n);
}
cgp
sumber
23
Perhatikan bahwa jquery.siblings () mengecualikan node saat ini dari set hasil.
cletus
3
Yang merupakan fitur yang sangat bagus!
cgp
1
Sebenarnya padanan node.parentNode.childNodes [] di jquery sebenarnya $ (node) .parent (). Children () bukan $ (node) .siblings (). Ini bisa menjadi fitur yang bagus tetapi juga bisa mengganggu. Itu tergantung pada apa yang Anda inginkan.
cletus
1
Anda akan ingin memeriksa node ELEMENT_NODE dengan node.parentNode.childNodes, karena itu akan memberi Anda node teks ruang putih juga.
seanmonstar
Tidak ada, saya pikir itu adalah kesalahan - maaf tentang itu (dihapus)
cgp
100
var sibling = node.nextSibling;

Ini akan mengembalikan saudara segera setelahnya, atau null tidak ada saudara lagi yang tersedia. Demikian juga, Anda bisa menggunakan previousSibling.

[Sunting] Setelah dipikir-pikir, ini tidak akan memberikan divtag berikutnya , tetapi spasi setelah node. Sepertinya lebih baik

var sibling = node.nextElementSibling;

Ada juga ada previousElementSibling .

parvus.dll
sumber
1
next / beforeElementSibling tidak didukung di IE8
Vadim
1
Mulai dari IE9. Lihat juga stackoverflow.com/questions/5197825/…
parvus
14

Cepat:

var siblings = n => [...n.parentElement.children].filter(c=>c!=n)

https://codepen.io/anon/pen/LLoyrP?editors=1011

Dapatkan turunan orang tua sebagai array, filter elemen ini.

Edit:

Dan untuk menyaring node teks (Terima kasih pmrotule ):

var siblings = n => [...n.parentElement.children].filter(c=>c.nodeType == 1 && c!=n)
bundar
sumber
2
Solusi bagus. Meskipun, saya akan memeriksa nodeType untuk membuang node teks[ ...n.parentNode.children ].filter(c => c.nodeType == 1 && c != n)
pmrotule
Bagaimana Anda memodifikasi ini untuk skrip ketikan?
Nic Scozzaro
10

Dari 2017:
jawaban langsung: element.nextElementSiblinguntuk mendapatkan saudara elemen yang tepat. juga Anda miliki element.previousElementSiblinguntuk yang sebelumnya

dari sini cukup mudah untuk mendapatkan semua saudara kandung berikutnya

var n = element, ret = [];
while (n = n.nextElementSibling){
  ret.push(n)
}
return ret;
pery mimon
sumber
Ini harus mengembalikan semua saudara kandung, tidak hanya nextatau previous. Menentukan secara tepat mundur atau maju tidak banyak membantu dalam kasus ini.
dvlden
4
kenapa tidak. jika Anda mengambil gambar berikutnya dan sebelumnya, Anda bisa mendapatkan gambaran keseluruhan. jawaban itu datang untuk menunjukkan cara baru dalam melakukan sesuatu. dan menyumbangkan sesuatu untuk pembaca. hanya untuk menjadi orang tua dan pergi ke setiap elemen dan memfilter yang saat ini dapat dilakukan semua orang
pery mimon
6

sudahkah Anda memeriksa metode "Sibling" di jQuery?

    sibling: function( n, elem ) {
        var r = [];

        for ( ; n; n = n.nextSibling ) {
            if ( n.nodeType === 1 && n !== elem ) {
                r.push( n );
            }
        }

        return r;
    }

n.nodeType == 1 periksa apakah elemennya adalah node html dan n! == mengecualikan elemen saat ini.

Saya pikir Anda dapat menggunakan fungsi yang sama, semua kode itu tampaknya javascript vanilla.

Nicolas Rojo
sumber
6

Ada beberapa cara untuk melakukannya.

Salah satu dari yang berikut ini seharusnya berhasil.

// METHOD A (ARRAY.FILTER, STRING.INDEXOF)
var siblings = function(node, children) {
    siblingList = children.filter(function(val) {
        return [node].indexOf(val) != -1;
    });
    return siblingList;
}

// METHOD B (FOR LOOP, IF STATEMENT, ARRAY.PUSH)
var siblings = function(node, children) {
    var siblingList = [];
    for (var n = children.length - 1; n >= 0; n--) {
        if (children[n] != node) {
            siblingList.push(children[n]);
        }  
    }
    return siblingList;
}

// METHOD C (STRING.INDEXOF, ARRAY.SPLICE)
var siblings = function(node, children) {
   siblingList = children;
   index = siblingList.indexOf(node);
   if(index != -1) {
       siblingList.splice(index, 1);
   }
   return siblingList;
}

FYI: Basis kode jQuery adalah sumber daya yang bagus untuk mengamati JavaScript Tingkat A.

Berikut adalah alat luar biasa yang mengungkapkan basis kode jQuery dengan cara yang sangat efisien. http://james.padolsey.com/jquery/

kepala biara
sumber
3

Inilah cara Anda mendapatkan saudara sebelumnya, berikutnya, dan semua (kedua sisi):

function prevSiblings(target) {
   var siblings = [], n = target;
   while(n = n.previousElementSibling) siblings.push(n);
   return siblings;
}

function nextSiblings(target) {
   var siblings = [], n = target;
   while(n = n.nextElementSibling) siblings.push(n);
   return siblings;
}

function siblings(target) {
    var prev = prevSiblings(target) || [],
        next = nexSiblings(target) || [];
    return prev.concat(next);
}
Maciej Sitko
sumber
2

Gunakan document.querySelectorAll () dan Loop dan iterasi

function sibblingOf(children,targetChild){
  var children = document.querySelectorAll(children);
  for(var i=0; i< children.length; i++){
    children[i].addEventListener("click", function(){
      for(var y=0; y<children.length;y++){children[y].classList.remove("target")}
      this.classList.add("target")
    }, false)
  }
}

sibblingOf("#outer >div","#inner2");
#outer >div:not(.target){color:red}
<div id="outer">
      <div id="inner1">Div 1 </div>
      <div id="inner2">Div 2 </div>
      <div id="inner3">Div 3 </div>
      <div id="inner4">Div 4 </div>
 </div>

Gildas.Tambo
sumber
1

jQuery

$el.siblings();

Asli - terbaru, Edge13 +

[...el.parentNode.children].filter((child) =>
  child !== el
);

Asli (alternatif) - terbaru, Edge13 +

Array.from(el.parentNode.children).filter((child) =>
  child !== el
);

Asli - IE10 +

Array.prototype.filter.call(el.parentNode.children, (child) =>
  child !== el
);
Humoyun Ahmad
sumber
0
var childNodeArray = document.getElementById('somethingOtherThanid').childNodes;
Thunderboltz
sumber
window.document.documentElement.childNodes [1] .childNodes [4] diambil dari howtocreate.co.uk/tutorials/javascript/dombasics
Thunderboltz
apakah ini merupakan solusi dari pertanyaan sama sekali?
zahid9i
Ini tidak menyelesaikan masalah yang dihadapi, atau setidaknya tidak cukup jelas untuk berguna.
cdeszaq
0

1) Tambahkan kelas yang dipilih ke elemen target
2) Temukan semua turunan dari elemen induk tidak termasuk elemen target
3) Hapus kelas dari elemen target

 <div id = "outer">
            <div class="item" id="inner1">Div 1 </div>
            <div class="item" id="inner2">Div 2 </div>
            <div class="item" id="inner3">Div 3 </div>
            <div class="item" id="inner4">Div 4 </div>
           </div>



function getSiblings(target) {
    target.classList.add('selected');
    let siblings = document.querySelecttorAll('#outer .item:not(.currentlySelected)')
    target.classList.remove('selected'); 
return siblings
    }
Manoj Yadav
sumber
-1

Fungsi berikut akan mengembalikan larik yang berisi semua saudara kandung dari elemen yang diberikan.

function getSiblings(elem) {
    return [...elem.parentNode.children].filter(item => item !== elem);
}

Cukup berikan elemen yang dipilih ke dalam getSiblings()fungsi sebagai satu-satunya parameter.

Saabbir
sumber
-2
x1 = document.getElementById('outer')[0]
      .getElementsByTagName('ul')[1]
      .getElementsByTagName('li')[2];
x1.setAttribute("id", "buyOnlineLocationFix");
andre paradise
sumber