We’re using a framework which creates arbitrarily nested HTML data elements identified by the attribute data-type=[some data type]. Each of these can contain direct input fields as well as other data-type, either as singletons or arrays. The only saving grace of the nesting structure is a data-type will never contain data-types of the same type at any depth.
The HTML I have to work with
<div data-type='project' id='example1'>
<input name='start-date'/>
<div data-type='project-lead' id='example2'>
<input name='department'/>
<input name='email'/>
<div data-type='analyst'>
<input name='department'/>
<input name='email'/>
</div>
<div data-type='analyst'>
<input name='department'/>
<input name='email'/>
</div>
<div data-type='analyst'>
<input name='department'/>
<input name='email'/>
</div>
</div>
<div class="JustToMakeMyLifeMoreDifficult">
<div data-type='sponsor'>
<input name='department'/>
<input name='email'/>
</div>
<div data-type='sponsor'>
<input name='department'/>
<input name='email'/>
</div>
</div>
</div>
The Selector Problem
I need a JQuery find selector which gets me the set of data-type elements one data-type level beneath the given object:
myData($obj){
return $obj.find('[data-type]').not([data-type elements further down]);
}
Such that:
myData($('#example1'))
myData($('#example2'))
respectively yields jquery results:
[project-lead,sponsor,sponsor]
[analyst, analyst, analyst]
JQuery wizards, please help me. You’re the only the ones that can.
Answered
This isn’t possible with JQuery selectors. I wrapped Patrick’s very elegant solution below into a generalized JQuery function-
(function( $ ){
$.fn.dataChildren = function(_selector) {
var iter = this;
var res = this.children(_selector);
while ( ( iter = iter.children(':not(' + _selector +')') ).length ) {
res = res.add(iter.children(_selector));
}
return res;
};
})( jQuery );
So that:
$('#example1').dataChildren('[data-type]')
Works as described above. I <3 SO.
EDIT 2: I think this is what you’re looking for:
This one goes recursively deep, but the recursion on any child branch stops when an element is found with
data-type, so it only continues as long as there’s a child that does not havedata-type.It may be easier to follow if I use a
do-whileloop, and unwind some of the code:EDIT: I may have misunderstood one part.It looks like an element with
data-typemay have children that also havedata-type. If that’s the case, change the selector to this:So to sum this one up, it says get all children and grandchildren that have a
data-typeattribute.Original answer:
If I understand you want children with
data-type, and of the children that are notdata-type, you need too add their children that aredata-type.This uses the
multiple-selector[docs].The first selector is:
…which will get children that have a
data-typeattribute.The second selector is:
…which will first get children that do not have
data-type, but of those, it will get their children that do havedata-type.Does that look like what you want?