我尝试选择一系列dom元素,从element
到element
。这在JQuery中可以实现:(Source)
$('#id').nextUntil('#id2').andSelf().add('#id2')
我试图仅使用JavaScript实现这一目标。
这是我尝试过的,但我得到了一个无限循环:
function prevRange(element, prevTill) {
var result = [];
while (element !== prevTill)
result.push(element);
return result;
}
var wrapper = document.getElementById('wrapper'),
wrapperChildren = wrapper.children;
console.log(prevRange(wrapperChildren[2], wrapperChildren[0]));
function prevRange(element, prevTill) {
var result = [];
/*while (element !== prevTill)
result.push(element);*/
return result;
}

<ul id="wrapper">
<li class="inner">I'm #01</li>
<li class="inner">I'm #02</li>
<li class="inner">I'm #03</li>
<li class="inner">I'm #04</li>
</ul>
&#13;
答案 0 :(得分:1)
使用Element.previousElementSibling
:
var wrapper = document.getElementById('wrapper'),
wrapperChildren = wrapper.children;
console.log(prevRange(wrapperChildren[2], wrapperChildren[0]));
function prevRange(element, prevTill) {
var result = [element];
while (element && element !== prevTill) {
element = element.previousElementSibling;
result.push(element);
}
return result;
}
<ul id="wrapper">
<li class="inner">I'm #01</li>
<li class="inner">I'm #02</li>
<li class="inner">I'm #03</li>
<li class="inner">I'm #04</li>
</ul>
答案 1 :(得分:1)
您的变量element
和prevTill
永远不会在while
循环中更改。因此,当您第一次进入element
循环时,如果prevTill
和while
不相等,那么它们将永远不会出现,并且您的while
循环将永远不会执行。
另外,你没有传入你试图迭代的元素数组并得到一个子集。
我会修改你的函数来接受你想要获得子集的元素数组,以及你想要的子集的起始和结束索引,然后你可以遍历{{1}中的数组。 }循环。
while
var wrapper = document.getElementById('wrapper'),
wrapperChildren = wrapper.children;
console.log(prevRange(wrapperChildren, 0, 2));
function prevRange(array, start, end) {
var result = [];
var curr = start;
while (curr <= end) {
result.push(array[curr]);
curr++;
}
return result;
}
答案 2 :(得分:0)
您不会迭代这些元素。 element
永远不会等于prevTill
因为你永远不会改变元素。如果您传递了元素子元素的数组,并使用for
循环遍历它所需的范围,该怎么办?所以你要传递元素数组,你想要的第一个孩子的最小索引,以及你想要的最后一个孩子的最大索引。
答案 3 :(得分:0)
你不想这样做:
while (element !== null && element !== prevTill)
{
result.push(element);
element = element.previousElementSibling;
}
更新了fiddle。
答案 4 :(得分:0)
已经有很多答案,但我已经为我认为你想要实现的目标实施了一个全面的解决方案。
#!/usr/bin/python
print "Content-type: text/plain\r\n\r\n",
print "Hello world"
答案 5 :(得分:0)
您必须迭代元素以避免无限循环。工作代码可能如下所示:
function prevRange(element, prevTill) {
var result = [];
if(element === prevTill){
result.push(element);
return result;
}
var siblings = element.parentNode.children;//prevTill is expected among siblings
var startSelection = false;
for(var i=0,ch;ch=siblings[i];++i){//iterate siblings
if(ch === element || ch === prevTill){//no matter which go first
result.push(ch);
startSelection = !startSelection;//start/stop
}
else if(startSelection)
result.push(ch);
}
/*while (element !== prevTill) this is your code
result.push(element);*/
return result;
}
答案 6 :(得分:0)
有几种方法可以做到这一点......我喜欢Nikhil的倒退回答,你可以用nextSibling属性做同样的事情。
我个人曾经遇到过下一次和之前的问题(特别是IE和Edge,YAY MS !!)
这是另一个非常简单的替代方案,但不依赖于DOM next / prev。
var wrapper = document.getElementById('wrapper'),
wrapperChildren = wrapper.children;
console.log(stopWhen(wrapperChildren[0],wrapperChildren[2]));
function stopWhen(start,end){
var results = new Array()
,parent = start.parentElement
,startPos = Array.prototype.indexOf.call(parent.childNodes, start)-2
,endPos = Array.prototype.indexOf.call(parent.childNodes, end)-2;
for(var i=startPos; i < endPos; i++){
if(parent.children[i] != null){
results.push(parent.children[i]);
}
}
return results;
}
分叉fiddle
答案 7 :(得分:0)
合并数组原型slice
和indexOf
方法。
getRangeElements(
document.getElementById('wrapper'), // parent
document.getElementById('li1'), // start
document.getElementById('li3') // end
)
function getRangeElements (parent, start, end) {
var children = parent.children
return [].slice.call(
children,
[].indexOf.call(children, start),
[].indexOf.call(children, end) + 1
)
}
ChildNodes本身并不具有数组方法,因此使用call
方法来应用该功能。一旦childNodes可以被视为数组元素,那么首先得到indexOf
子元素,然后slice
你正在寻找的范围。
假设:
<ul id="wrapper">
<li class="inner" id="li1">I'm #01</li>
<li class="inner" id="li2">I'm #02</li>
<li class="inner" id="li3">I'm #03</li>
<li class="inner" id="li4">I'm #04</li>
</ul>
...返回:
[li#li1.inner, li#li2.inner, li#li3.inner]
答案 8 :(得分:0)
您可以创建一个 TreeWalker 来为您执行此操作:
var wrapper = document.getElementById('wrapper');
var wrapperChildren = wrapper.children;
function getElementRange(rangeRoot, elementStart, elementEnd) {
var result = [];
var itr = document.createTreeWalker(
rangeRoot,
NodeFilter.SHOW_ELEMENT,
null, // no filter
false);
itr.currentNode = elementStart;
do {
result.push(itr.currentNode);
} while(itr.currentNode !== elementEnd && itr.nextSibling());
return result;
}
console.log(getElementRange(wrapper, wrapperChildren[0], wrapperChildren[2]));
&#13;
<ul id="wrapper">
<li class="inner">I'm #01</li>
<li class="inner">I'm #02</li>
<li class="inner">I'm #03</li>
<li class="inner">I'm #04</li>
</ul>
&#13;
结帐This link to MDN 有关创建TreeWalkers的更多信息
我还建议您了解TreeWalker interface object
希望这有帮助。
*编辑 - 以下是支持双向范围的示例:
var wrapper = document.getElementById('wrapper');
var wrapperChildren = wrapper.children;
function getElementRange(elementStart, elementEnd) {
var result = [];
var rootNode;
var indexStart;
var indexEnd;
rootNode = elementStart.parentNode;
if(rootNode !== elementEnd.parentNode){
return console.log("Cannot getElementRange, elements are not siblings");
}
//Get direction to traverse nodes
indexStart = Array.prototype.indexOf.call(rootNode.childNodes, elementStart);
indexEnd = Array.prototype.indexOf.call(rootNode.childNodes, elementEnd);
var itr = document.createTreeWalker(
rootNode,
NodeFilter.SHOW_ELEMENT,
null, // no filter
false);
itr.currentNode = elementStart;
var iterateMethod = indexStart < indexEnd ? 'nextSibling' : 'previousSibling';
do {
result.push(itr.currentNode);
} while(itr.currentNode !== elementEnd && itr[iterateMethod]());
return result;
}
console.log(getElementRange(wrapperChildren[1], wrapperChildren[3]));
console.log(getElementRange(wrapperChildren[3], wrapperChildren[1]));
&#13;
<ul id="wrapper">
<li class="inner">I'm #01</li>
<li class="inner">I'm #02</li>
<li class="inner">I'm #03</li>
<li class="inner">I'm #04</li>
</ul>
&#13;