Jquery - Find All Descendants At Any Level, But Not The Descendants Of Those Descendants
QUESTION: I am trying to use JQuery's .find() to find all descendants within an element at any level that have a given attribute, but not the descendants of those descendants with
Solution 1:
You can use :not
to make sure the selected elements do not match a particular selector - here, #some_id [some_attribute] [some_attribute]
(because elements which match that selector will be a some_attribute
nested in another some_attribute
which is not the #some_id
):
const result = $("#some_id")
.find("[some_attribute]:not(#some_id [some_attribute] [some_attribute])")
.each(function() {
console.log(this.innerHTML);
});
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><spanid="some_id"some_attribute><spansome_attribute>sel <!-- SELECT --><spansome_attribute><!-- IGNORE --><spansome_attribute><!-- IGNORE --></span></span><span></span></span><span><spansome_attribute>sel <!-- SELECT --><span><spansome_attribute><!-- IGNORE --></span></span><spansome_attribute><!-- IGNORE --></span></span></span><span><span><span><spansome_attribute>sel <!-- SELECT --></span></span></span></span></span>
If you can't hard-code it, I suppose a option would be to set an attribute so that you can use :not
properly:
const elm = $("#some_id");
elm[0].dataset.parent = '';
elm
.find("[some_attribute]:not([data-parent] [some_attribute] [some_attribute])")
.each(function() {
console.log(this.innerHTML);
});
elm[0].removeAttribute('data-parent');
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><spanid="some_id"some_attribute><spansome_attribute>sel <!-- SELECT --><spansome_attribute><!-- IGNORE --><spansome_attribute><!-- IGNORE --></span></span><span></span></span><span><spansome_attribute>sel <!-- SELECT --><span><spansome_attribute><!-- IGNORE --></span></span><spansome_attribute><!-- IGNORE --></span></span></span><span><span><span><spansome_attribute>sel <!-- SELECT --></span></span></span></span></span>
If you don't want to change the DOM either, .filter
and check that the .closest
element with [some_attribute]
is the parent:
const elm = $("#some_id");
elm
.find("[some_attribute]")
.filter(function() {
return $(this).parent().closest('[some_attribute]')[0] === elm[0];
})
.each(function() {
console.log(this.innerHTML);
});
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><spanid="some_id"some_attribute><spansome_attribute>sel <!-- SELECT --><spansome_attribute><!-- IGNORE --><spansome_attribute><!-- IGNORE --></span></span><span></span></span><span><spansome_attribute>sel <!-- SELECT --><span><spansome_attribute><!-- IGNORE --></span></span><spansome_attribute><!-- IGNORE --></span></span></span><span><span><span><spansome_attribute>sel <!-- SELECT --></span></span></span></span></span>
Using old versions of jQuery, you can use .selector
:
const elm = $("#some_id");
const sel = elm.selector;
elm
.find(`[some_attribute]:not(${sel} [some_attribute] [some_attribute])`)
.each(function() {
console.log(this.innerHTML);
});
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7/jquery.min.js"></script><spanid="some_id"some_attribute><spansome_attribute>sel <!-- SELECT --><spansome_attribute><!-- IGNORE --><spansome_attribute><!-- IGNORE --></span></span><span></span></span><span><spansome_attribute>sel <!-- SELECT --><span><spansome_attribute><!-- IGNORE --></span></span><spansome_attribute><!-- IGNORE --></span></span></span><span><span><span><spansome_attribute>sel <!-- SELECT --></span></span></span></span></span>
Solution 2:
Here is my solution. For more explanation see the code notes below...
// NOTE: Find all descendants at any level, but not the descendants of those descendants.// By QuestorfunctionfindDescsNotDescsOfThose(jqPntElOrPntQry, jqFind){
var jqElInst;
if (typeof jqPntElOrPntQry === "string" ||
jqPntElOrPntQry instanceofString) {
// [Ref.: https://stackoverflow.com/a/9436948/3223785 ]
jqElInst = $(jqPntElOrPntQry);
} else {
jqElInst = jqPntElOrPntQry;
}
return jqElInst.find(jqFind)
.filter(function(){
// NOTE: We need use ".parent ()" and then ".closest ()", otherwise ".closest ()"// will find the element itself if it fits "jqFind". By Questor
descOfjqFind = $(this).parent().closest(jqFind);
// NOTE: Checks if it is not descended from any element that also fits// in "jqFind". Being descended from an element that also fits "jqFind"// checks to see if this element is descended from "jqElInst". By Questorif (descOfjqFind.length > 0 && $(descOfjqFind).
parent().closest(jqElInst).length === 1) {
returnfalse
}
returntrue;
});
}
Thanks! =D
Post a Comment for "Jquery - Find All Descendants At Any Level, But Not The Descendants Of Those Descendants"