Как найти всех братьев и сестер выбранного в данный момент объекта - PullRequest
22 голосов
/ 07 декабря 2010

Каков идеальный способ найти всех следующих и предыдущих в Javascript.Я пробовал несколько способов, но не получил точного решения.если выбран какой-либо элемент, мне нужно получить длину всех следующих братьев и сестер, кроме пробелов, пробелов или разрывов строк

Также я не хочу использовать jquery для этого, я специально искал что-то из Javaскрипт

Пожалуйста, совет

Ответы [ 8 ]

22 голосов
/ 07 декабря 2010

Это немного более сложное решение, но оно позволяет вам создать фильтр того, как вы получаете братьев и сестер.

Есть три функции для получения only previous, only следующий или все .Это может быть улучшено, но достойная отправная точка, если вам нужно больше контролировать, какие типы братьев и сестер вы хотите собрать.Возможно, стоит добавить.

Рабочий пример

получить всех следующих братьев и сестер

//this will start from the current element and get all of the next siblings

function getNextSiblings(elem, filter) {
    var sibs = [];
    while (elem = elem.nextSibling) {
        if (elem.nodeType === 3) continue; // text node
        if (!filter || filter(elem)) sibs.push(elem);
    }
    return sibs;
}

получить всех предыдущих братьев и сестер

//this will start from the current element and get all the previous siblings

function getPreviousSiblings(elem, filter) {
    var sibs = [];
    while (elem = elem.previousSibling) {
        if (elem.nodeType === 3) continue; // text node
        if (!filter || filter(elem)) sibs.push(elem);
    }
    return sibs;
}

получить всех братьев и сестер

//this will start from the first child of the current element's parent and get all the siblings

function getAllSiblings(elem, filter) {
    var sibs = [];
    elem = elem.parentNode.firstChild;
    do {
        if (elem.nodeType === 3) continue; // text node
        if (!filter || filter(elem)) sibs.push(elem);
    } while (elem = elem.nextSibling)
    return sibs;
}

пример фильтра для применения к вышеуказанным функциям

// Example filter only counts divs and spans but could be made more complex
function exampleFilter(elem) {
    switch (elem.nodeName.toUpperCase()) {
        case 'DIV':
            return true;
        case 'SPAN':
            return true;
        default:
            return false;
    }
}

HTML и результаты тестирования

HTML

<div id='test'>
    <div id='test2'>asdf</div>
    <br /> sdf
    <div>asdfasdf<span>asdf</span></div>
    <div>a</div>
    <span>a</span>
    <br />
    <div>d</div>
    <hr/>
</div>

JavaScript

var elem;
elem = document.getElementById('test2');

//with filter alerts 4
alert( getNextSiblings( elem, exampleFilter ).length );

// no filter, alerts 7
elem = document.getElementById('test2');// put elem back to what it was
alert( getNextSiblings( elem ).length );

// alerts 0
elem = document.getElementById('test2');// put elem back to what it was
alert( getPreviousSiblings( elem, exampleFilter ).length );

// alerts 5
elem = document.getElementById('test2');// put elem back to what it was
alert( getAllSiblings( elem, exampleFilter ).length );
17 голосов
/ 07 декабря 2010

Я предполагаю, что это происходит внутри обработчика событий, где this является ссылкой на целевой элемент, чьи братья и сестры вы хотите повлиять

Если нет, понадобятся корректировки.

var result = [],
    node = this.parentNode.firstChild;

while ( node ) {
    if ( node !== this && node.nodeType === Node.ELEMENT_NODE ) 
      result.push( node );
    node = node.nextElementSibling || node.nextSibling;
}

// result will contain all type 1 siblings of "this"
5 голосов
/ 03 августа 2018

Вот очень короткий и простой способ сделать это с ES6:

function getAllSiblings(element, parent) {
        const children = [...parent.children];
        return children.filter(child => child !== element);
    }

Это вернет все дочерние элементы родительского узла, которые не являются элементом.

4 голосов
/ 07 декабря 2010

Вы можете получить все дочерние элементы родительского элемента и исключить сам элемент.

2 голосов
/ 31 июля 2017

назад в 2017:
Возможно, есть лучший ответ, но этот хороший и немного чище

function sibiling(dom, query) {
   var doms = dom.parentElement.querySelectorAll(query);
   return [].slice.call(doms).filter( d => d != dom);
}
2 голосов
/ 26 мая 2016

Это обновление ответа @ subhaze.

Этот код использует matches метод DOM , который поддерживается в современных браузерах :

Демо

function matches(elem, filter) {
  if (elem && elem.nodeType === 1) {
    if (filter) {
      return elem.matches(filter);
    }
    return true;
  }
  return false;
}

// this will start from the current element and get all of
// the next siblings
function getNextSiblings(elem, filter) {
  var sibs = [];
  while (elem = elem.nextSibling) {
    if (matches(elem, filter)) {
      sibs.push(elem);
    }
  }
  return sibs;
}

// this will start from the current element and get all the
// previous siblings
function getPreviousSiblings(elem, filter) {
  var sibs = [];
  while (elem = elem.previousSibling) {
    if (matches(elem, filter)) {
      sibs.push(elem);
    }
  }
  return sibs;
}

// this will start from the first child of the current element's
// parent and get all the siblings
function getAllSiblings(elem, filter) {
  var sibs = [];
  elem = elem.parentNode.firstChild;
  while (elem = elem.nextSibling) {
    if (matches(elem, filter)) {
      sibs.push(elem);
    }
  } 
  return sibs;
}

Используйте эти функции следующим образом:

var elem = document.querySelector('#test');

// find all the "div" and "span" siblings
var after = getNextSiblings(elem, 'div, span');

// find previous siblings with ".list-item" class
var index = getPreviousSiblings(elem, '.list-item');

// get all siblings with a title attribute
var allSibs = getAllSiblings(elem, '[title]');
1 голос
/ 02 апреля 2014

Этот ответ был ранее опубликован здесь в ответ на аналогичный вопрос.

Есть несколько способов сделать это.

Любое из следующих действий должно сработать.

// 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;
}

К вашему сведению: кодовая база jQuery - отличный ресурс для изучения Javascript класса А. Вот превосходный инструмент, который очень хорошо раскрывает кодовую базу jQuery. http://james.padolsey.com/jquery/

0 голосов
/ 02 мая 2018

Просто мои два цента здесь, я сделал пару функций, чтобы получить все предыдущие и последующие элементы любого элемента.

const getPreviousAll = element => {
  const previousAllFound = [];
  const getPrevious = element => {
    if (element !== null) {
      previousAllFound.push(element);
      const previousFound = element.previousElementSibling;
      if (previousFound !== null) {
        getPrevious(previousFound);
      }
    }
  };
  getPrevious(element.previousElementSibling);
  return previousAllFound;
};
const getNextAll = element => {
  const target = element;
  const nextAllFound = [];
  const getAll = element => {
    if (element !== null) {
      nextAllFound.push(element);
      const nextFound = element.nextElementSibling;
      if (nextFound !== null) {
        getAll(nextFound);
      }
    }
  };
  getAll(element.nextElementSibling);
  return nextAllFound;
};

Вам просто нужно вызвать эту функцию с помощью узла, который вы можетеget by getElementById.

...