在javascript中查找所有nextSiblings和previousSiblings的完美方式是什么。我尝试了几种方法但没有得到准确的解决方案如果选择了任何元素,我需要得到所有下一个兄弟的长度,不包括空格,任何空格或换行符
此外,我不想为此使用jquery,我特意从java脚本中查找内容
请咨询
答案 0 :(得分:22)
这对解决方案来说有点啰嗦,但允许您创建一个关于如何获得兄弟姐妹的过滤器。
有三个功能可以仅上一个,仅下一个,或全部。如果您需要更多地控制您想要收集的兄弟姐妹类型,这可以改善但是起点不错。认为可能值得补充。
<强> Working Example 强>
获取所有下一个兄弟姐妹
//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 );
答案 1 :(得分:17)
我假设这发生在一个事件处理程序中,其中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"
答案 2 :(得分:5)
这是使用ES6的一种非常简短的方法:
function getAllSiblings(element, parent) {
const children = [...parent.children];
return children.filter(child => child !== element);
}
这将返回不是该元素的父节点的所有子节点。
答案 3 :(得分:4)
您可以获取元素父级的所有子级,并排除元素本身。
答案 4 :(得分:2)
这是@ subhaze答案的更新。
此代码使用matches
DOM method supported in modern browsers:
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]');
答案 5 :(得分:2)
回到2017年:
也许有更好的答案,但那又好又干净
function sibiling(dom, query) {
var doms = dom.parentElement.querySelectorAll(query);
return [].slice.call(doms).filter( d => d != dom);
}
答案 6 :(得分:1)
此答案之前已发布here以回应类似问题。
有几种方法可以做到。
以下任一项都可以解决问题。
// 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代码库是观察A级Javascript的绝佳资源。
这是一个优秀的工具,以非常简化的方式显示jQuery代码库。 http://james.padolsey.com/jquery/
答案 7 :(得分:0)
这里只有我的两分钱,我做了几个函数来获得任何元素的所有主流和下一个兄弟。
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;
};
您只需使用getElementById可以获取的节点调用此函数。
答案 8 :(得分:0)
以前的所有兄弟姐妹
// jQuery (optional filter selector)
$el.prevAll($filter);
// Native (optional filter function)
function getPreviousSiblings(elem, filter) {
var sibs = [];
while (elem = elem.previousSibling) {
if (elem.nodeType === 3) continue; // ignore text nodes
if (!filter || filter(elem)) sibs.push(elem);
}
return sibs;
}
所有下一个兄弟姐妹
// jQuery (optional selector filter)
$el.nextAll($filter);
// Native (optional filter function)
function getNextSiblings(elem, filter) {
var sibs = [];
var nextElem = elem.parentNode.firstChild;
do {
if (nextElem.nodeType === 3) continue; // ignore text nodes
if (nextElem === elem) continue; // ignore elem of target
if (nextElem === elem.nextElementSibling) {
if (!filter || filter(elem)) {
sibs.push(nextElem);
elem = nextElem;
}
}
} while(nextElem = nextElem.nextSibling)
return sibs;
}
过滤器功能示例:
function exampleFilter(elem) {
switch (elem.nodeName.toUpperCase()) {
case 'DIV':
return true;
case 'SPAN':
return true;
default:
return false;
}
}
答案 9 :(得分:0)
下面的这个实际上帮助我通过PARENT(唯一知道您兄弟姐妹的人不知道您父母身份的人)选择了所有SIBLINGS(最初不包括所选项目本身)。您唯一知道的是您的直子长兄,即 previousElementSibling 和直子的直子,即 nextElementSibling 。大声笑!
const allSiblings = Array.from(YOUR_SELECTION.parentElement.children)
.filter(sibling => sibling.UNIQUE_PropertyName !== (YOUR_SELECTION.COMPARABLE/UNIQUE_PropertyName));
// You don't have to save in a variable if you don't want to
HTML
<div id="mummy">
<div id="baby_1">Samuel</div>
<div id="baby_2">Dave</div>
<div id="baby_3">Shaun</div>
<div id="baby_4">Michael</div>
<div id="baby_5" class="selected">Fazlullah</div>
<div id="baby_6">Samson</div>
<div id="baby_7">Bais</div>
<div>
JavaScript
// I have decide to use the Names of the children as my UNIQUE_Property, So i can get that with the .textContent propertyName
const selected = document.querySelector('.selected'); // So with "Fazlullah" selected
const allSiblings = Array.from(selected.parentElement.children) // I got to know his mum (.parentElement), then the mum's children(.children)
.filter(sibling => sibling.textContent !== selected.textContent); // And this now get's me a list (actually an Array) of his siblings that he doesn't even know.
allSiblings.forEach(sibling => {
console.log(sibling.textContent);
});
如果我决定使用子代“ id”,则我的链式过滤器方法应为:.filter(sibling => sibling.id !== selected.id);
请参见Demo
答案 10 :(得分:0)
const getSiblings = (elm, withTextNodes) => {
if( !elm || !elm.parentNode ) return
let siblings = [...elm.parentNode[withTextNodes ? 'childNodes' : 'children']],
idx = siblings.indexOf(elm);
siblings.previous = siblings.slice(0, idx)
siblings.next = siblings.slice(idx + 1)
return siblings
}
// Usage example:
const testElm = document.querySelector('em');
const testElmSiblings = getSiblings(testElm);
console.log(
testElmSiblings.previous,
testElmSiblings.next,
testElmSiblings
)
<div></div>
text node 1
<a></a>
<p></p>
<em></em>
<main></main>
text node 2
<hr/>
<b></b>