问题
I have an HTML list (<ul>
, <li>
, etc.) of pages, with multiple items at various depths. I am trying to write some code to traverse this list one element at a time. So a "next " button would return the ID of the following <li>
element, which could be a direct sibling of the current element, or it would be in a child <ul>
element, or it could be in a parent <ul>
element. Likewise, a "prev" button would do the same, but in reverse.
Here is some example html:
<ul>
<li id="post_item_1"><a href="#post1">Vestibulum ultrices, ante non tincidunt molestie, purus enim varius urna, nec bibendum...</a>
<ul>
<li id="post_item_26"><a href="#post26">This planet has — or rather had — a problem, which was this: most of...</a>
<ul>
<li id="post_item_27"><a href="#post27">A towel, it says, is about the most massively useful thing an interstellar hitch...</a>
</li>
</ul>
</li>
</ul>
</li>
<li id="post_item_2"><a href="#post2">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin nec velit augue,...</a>
<ul>
<li id="post_item_58"><a href="#post58">Reply to first post, with an edit</a>
</li>
<li id="post_item_59"><a href="#post59">Another reply to first post, made after the first reply</a>
</li>
</ul>
</li>
<li id="post_item_4"><a href="#post4">Phasellus vitae est tellus, vel aliquam lectus. Cras augue tellus, pulvinar a blandit...</a>
<ul>
<li id="post_item_60"><a href="#post60">Reply to second post</a>
</li>
</ul>
</li>
<li id="post_item_3"><a href="#post3">Pellentesque consequat urna mauris, luctus adipiscing enim. Sed quis lectus vel...</a>
</li>
<li id="post_item_28"><a href="#post28">"The Babel fish" said The Hitchhiker's Guide to the Galaxy quietly, "is small, yellow...</a>
</li>
<li id="post_item_61"><a href="#post61">Hello there, it is very worrying</a>
<ul>
<li id="post_item_62"><a href="#post62">Don't be scared, or scarred, or sacred, or Skesis!</a>
</li>
</ul>
</li>
<li id="post_item_67"><a href="#post67">Well, to be fair, at the end of the day, when all is said and done, I'd like to...</a>
</li>
</ul>
I've played around with jquery for some hours, and this is as far as I have got:
if (!node) {
// start with the selected node
node = $('#content #postNavigator ul li.selected')
}
if ( $(node).has('ul').length ) {
// has child <ul>
nextNode = $($(node).children()[1]).children()[0];
}
else {
// has a sibling
if ($(node).next('li').length) {
nextNode = $(node).next('li');
}
else {
// recursion needed here - this code will return parent, but only when 1 level deep.
if ($(node).parent().parent().next('li').length) {
nextNode = $(node).parent().parent().next('li');
}
else {
return false;
}
}
}
The above will return the next node, or a child node if there is one, and will return the parent node if there are no more siblings or children, but only one level deep. The HTML list can be of an unlimited depth, so some kind of recursion may be needed? This is as far my skills can take me. I haven't even begun to think about the "prev" link, to work on this list in the same way but in reverse order.
I asked the same on devshed (a few weeks ago) but have had no replies.
Thank you all for your answers.
Ninja, I have implemented yours with some success. I can now navigate up and down my nested list very nicely.
A further question, if you would be so kind: I need the ability to start the "position" at a point within the tree. Users can select a node within the tree by way of a hash (e.g. #post9) - they can click a node anywhere in the list to select it, or they can bookmark the url, which would include that node's own hash.
So my further question is: how would I locate a node within the tree and get it's position, using the hash in the URL? The hash in the URL correlates with the id of the li node .
回答1:
Since you're already using jQuery, you might as well take advantage of its built-in DOM traversal mechanisms. In this case you're going to care mostly about $().find
and $().eq
.
$().find
jQuery can actually find every matching element that exists below the level of any other selector. This single method is going to do the vast majority of your work for you.
// Returns a jQuery object containing every 'li' on the page
var items = $('body').find('li');
$().eq
Really you've got a couple of options for accessing those individual li
elements now. jQuery is an Array-like structure, which means you could access each element by its index. But jQuery also has a built-in method for getting individual elements out of a collection, and they'll be returned as jQuery objects as well.
// Good: Returns the first element from the jQuery collection as a JS DOMElement
items[0];
// Better: Returns the first element from the jQuery collection as a jQuery collection
items.eq(0);
Putting it together
Now that you've got the tools, you just need to apply a bit of logic to move from one element to the next on the list. Here's all you really need; I also copied your markup into a jsFiddle project and added a little bit of functionality to show you how it works: http://jsfiddle.net/ninjascript/Kt8f8/.
var items = $('body').find('li');
var length = items.length;
var position = -1;
function next() {
position = (position + 1 < length) ? position + 1 : 0;
return items.eq(position);
}
Good luck!
回答2:
I believe this will work:
function nextNode(selectedNode) {
var nextNode = selectedNode.next("li");
if (nextNode.length) {
return nextNode;
}
return nextNode.closest("li").next();
}
What this does is take the selected node and return the next node if it has one. If not, it searches for the closest parent li tag and gets the next node from him.
回答3:
if you dnt want to use external libraries then you need to use a combination of javascript document methods
and
dom element methods
Good luck!
来源:https://stackoverflow.com/questions/7052414/traversing-an-html-nested-list-using-javascript