How to find all Siblings of the currently selected DOM object

前端 未结 11 1166
轻奢々
轻奢々 2020-12-08 04:25

What is the perfect way to find all nextSiblings and previousSiblings in JavaScript. I tried few ways but not getting accurate solution. If any element is selected, I need t

相关标签:
11条回答
  • 2020-12-08 05:19

    back to 2017:
    Maybe there is a better answer but that good and a little bit cleaner

    function sibiling(dom, query) {
       var doms = dom.parentElement.querySelectorAll(query);
       return [].slice.call(doms).filter( d => d != dom);
    }
    
    0 讨论(0)
  • 2020-12-08 05:21

    This is an update to @subhaze's answer.

    This code uses the matches DOM method which is supported in modern browsers:

    Demo

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

    Use these functions as follows:

    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]');
    
    0 讨论(0)
  • 2020-12-08 05:21

    Just my two cents here, I made a couple of functions to get all the previos and the next siblings of any element.

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

    You just have to call this functions with a node that you can get by getElementById.

    0 讨论(0)
  • 2020-12-08 05:22

    This is a bit more winded of a solution but allows you to create a filter on how you get siblings.

    There are three functions to get only previous, only next, or all. This could be improved but decent starting point if you need more control on what types of siblings you want to collect. Thought it might be worth adding.

    Working Example

    get all next siblings

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

    get all previous siblings

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

    get all siblings

    //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 to apply to above functions

    // 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 and testing output

    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 );
    
    0 讨论(0)
  • 2020-12-08 05:23

    Here is a very short and simple way to do it with ES6:

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

    This will return all children of the parent node that are not the element.

    0 讨论(0)
提交回复
热议问题