Iterating Through N Level Children
This seems like something neat that might be "built into" jQuery but I think it's still worth asking.
I have a problem where that can easily be solved开发者_Go百科 by iterating through all the children of a element. I've recently discovered I need to account for the cases where I would need to do a level or two deeper than the "1 level" (just calling .children() once) I am currently doing.
jQuery.each(divToLookAt.children(), function(index, element)
{
//do stuff
}
);
This is what I'm current doing. To go a second layer deep, I run another loop after doing stuff code for each element.
jQuery.each(divToLookAt.children(), function(index, element)
{
//do stuff
jQuery.each(jQuery(element).children(), function(indexLevelTwo, elementLevelTwo)
{
//do stuff
}
);
}
);
If I want to go yet another level deep, I have to do this all over again.
This is clearly not good. I'd love to declare a "level" variable and then have it all take care of. Anyone have any ideas for a clean efficient jQueryish solution?
Thanks!
This is an awesome question because of the levels deep catch. Check out the fiddle.
Converted this to a plugin.
Activate
$('#div').goDeep(3, function(deep){ // $.fn.goDeep(levels, callback)
// do stuff on `this`
});
Plugin
$.fn.goDeep = function(levels, func){
var iterateChildren = function(current, levelsDeep){
func.call(current, levelsDeep);
if(levelsDeep > 0)
$.each(current.children(), function(index, element){
iterateChildren($(element), levelsDeep-1);
});
};
return this.each(function(){
iterateChildren($(this), levels);
});
};
This question is awesome :-)
If you know your DOM is not too gigantic, you could just find all the descendants and filter out the ones that don't qualify:
var $parent = $('#parent');
var $childrenWithinRange = $parent.find('*').filter(function() {
return $(this).parents('#parent').length < yourMaxDepth;
});
After that, the jQuery instance "$childrenWithinRange" would be all the child nodes of that parent <div>
that are within some maximum depth. If you wanted exactly that depth, you'd switch "<" to "===". I may be off by one somewhere.
You should be able to just do it with the all-selector
(docs), the child-selector
(docs) and multiple-selector
(docs) like this:
Example: http://jsfiddle.net/mDu9q/1/
$('#start > *,#start > * > *,#start > * > * > *').doSomething();
...or if you only wanted to target the children 3 levels deep, you could do this:
Example: http://jsfiddle.net/mDu9q/2/
$('#start > * > * > *').doSomething();
Both of these selectors are valid for querySelectorAll
, which means big performance boost in supported browsers.
The question sounds like the answer could be XPATH. I'm not well informed about the browser-support, but in XPATH you only need to create a path like
/*/*/*/*
- https://developer.mozilla.org/en/introduction_to_using_xpath_in_javascript (works in FF,Chrome,Safari,Opera)
- http://msdn.microsoft.com/en-us/library/aa335968%28v=vs.71%29.aspx (didn't try it yet)
var lvlFunc = function(elmt, depth) {
if(depth > 0) {
elmt.children().each(function(i, e){
// do stuff on the way down
lvlFunc($(this), --depth);
// do stuff on the way out
});
// do stuff
}
};
lvlFunc(divToLookAt, 3);
Make sure that you put your "do stuff" code in the right location if matters which order the "stuff" is performed in.
精彩评论