The goal is to select any descendant(s) -- regardless of direct-descendant indication -- but not their children. In other words, if I'm searching from document
I'd like to find all children which are not wrapped by the target selector:
<div id="a1" class="scenario-1" data-behavior="test">
test
<div id="a2" data-behavior="test">
test 1
<div id="a3" data-behavior="test">
test 2
</div>
</div>
</div>
<div class="scenario-2">
<div id="b1" data-behavior="test">
test 1
<div id="b2" data-behavior="test">
test 2
</div>
</div>
</div>
$(document).findAllInFirstLayer([data-behavior]);
This, ideally, would select #a1
& #b1
in the result-set. However, #a2
, #a3
, and #b2
should not be included, as this would proceed one scope to many.
The complimentary function for this will be recursive to drill down to the next scope for each layer-element in the set. So the next recursive call would return a set containing #a2
, #b2
, but not #a3
or any children ([data-behavior]
) of #b2
.
Also, this Question should not be marked as a duplicate of this question as the Accepted-Answer is not acceptable here -- the accepted answer here should use a jQuery selector or prove its impossibility with only using a jQuery selector.
With @guest271314's help, we reached the following answer:
'[data-behavior]:not([data-behavior] [data-behavior]), [data-behavior]:first'
Now, a recursive function can be used to take a parent-context and find the first-level scopes -- and recur in that fashion indefinitely. Here's an example:
arm: function autoRegisterModules(parent) {
var $firstScope = $(parent).find('[data-behavior]:not([data-behavior] [data-behavior]), [data-behavior]:first');
console.log('#context, #first-scope', parent, $firstScope);
if ($firstScope.length) {
$firstScope.each(function (i, p) {
autoRegisterModules(p);
});
}
},
Please be sure to give credit where it's due.
#prethanks
This, ideally, would select
#a1
&#b1
in the result-set.
Try using :not()
for first result set , :first
for next results
var first = $("[data-behavior]:not([data-behavior] [data-behavior])"),
second = first.find("[data-behavior]:first"),
third = second.find("[data-behavior]:first");
console.log(first, second, third);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div id="a1" class="scenario-1" data-behavior="test">
test
<div id="a2" data-behavior="test">
test 1
<div id="a3" data-behavior="test">
test 2
</div>
</div>
</div>
<div class="scenario-2">
<div id="b1" data-behavior="test">
test 1
<div id="b2" data-behavior="test">
test 2
</div>
</div>
</div>
So the next recursive call would return a set containing
#a2
,#b2
, but not#a3
or any children ([data-behavior]
) of#b2
.
using $.fn.extend()
(function($) {
$.fn.extend({
layers: function(sel) {
var root, next, res = [],
sel = sel || this.selector;
if ($(sel + ":not(" + sel + " " + sel + ")").length) {
root = $(sel + ":not(" + sel + " " + sel + ")");
res.push([root]);
if (root.find(sel + ":first").length) {
next = root.find(sel + ":first");
res.push([next]);
while (next.find(sel + ":first").length) {
next = next.find(sel + ":first");
res.push([next])
}
}
}
return this.data("layers", res)
}
})
}(jQuery))
var layers = $("[data-behavior]").layers().data("layers");
$.each(layers, function(key, value) {
console.log(key, value[0])
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div id="a1" class="scenario-1" data-behavior="test">
test
<div id="a2" data-behavior="test">
test 1
<div id="a3" data-behavior="test">
test 2
</div>
</div>
</div>
<div class="scenario-2">
<div id="b1" data-behavior="test">
test 1
<div id="b2" data-behavior="test">
test 2
</div>
</div>
</div>