问题
I'd like to take the code found here: http://www.jslab.dk/articles/non.recursive.preorder.traversal.part2
// HTML element
var root = document.documentElement;
recursivePreorder(root);
// Recusively find and handle all text nodes
function recursivePreorder(node) {
// If node is a text node
if (node.type == 3) {
// Do something with node
}
// else recurse for each child node
else {
for(var i=0; i<node.childNodes.length; i++)
recursivePreorder(node.childNodes[i]);
}
}
and convert it into clean jQuery.
Any idea? I know recursion requires argument.callee since the callbacks in jQuery are anonymous, but I'm too new to JQuery to take it any further.
Thanks!
回答1:
As Code Duck pointed out, jQuery traverses nodes in source-order, depth-first - or, as you call it, pre-order. However, contents
only gets immediate children nodes, not descendants. Try this:
$(document).contents ().each (function processNodes ()
{
if (this.nodeType == 3)
doSomething (this); // do something with text node
else
$(this).contents ().each (processNodes);
});
As an aside, arguments.callee
is marked for deprecation, hence the named (as opposed to anonymous) function
回答2:
Unless this is a homework assignment and you're forced to go through all the loopy madness, there's surely an easier way with jQuery to accomplish whatever you're trying to do...
jQuery has a pretty robust set of selectors that will allow you to just select and return a collection of all of a specified type of element within a page or element (ex. all of the paragraph tags in a given div tag). They'll be returned to you in the order they appear in the DOM (which is pretty much what you get with the above). Alternatively, you can use a filter like suggested above.
If you need to do this in some specific order, then I would suggest using selectors or filters to grab the element you want to start at and then loop through its children recursively. jQuery has a built in function to return the children of a given element.
- http://docs.jquery.com/Selectors
- http://docs.jquery.com/Traversing/filter#expr
- http://docs.jquery.com/Traversing/children#expr
回答3:
As a jQuery plugin: (also adds a break feature (like jQuery.each
), and an option for pre or post-order; YMMV with post-order)
$.fn.walk = function(visit, post_order) {
if(this.length === 0) { return; }
this.each(function(i) {
if (!post_order) {
if (visit.call(this, i, this) === false) { return false; }
}
$j(this).children().walk(visit, post_order);
if (post_order) { return visit.call(this, i, this); }
});
}
回答4:
I think it's as simple as
var collection=$(document).contents().filter(function() { return this.nodeType == 3; });
Then, you're could either run your commands on the collection
set using $.each
, or if you want to run a jQuery method on the set, you could not assign it to a variable and chain the method onto the end.
来源:https://stackoverflow.com/questions/2082550/how-to-write-a-simple-preorder-dom-tree-traversal-algorithm-in-jquery