Is there some method in jQuery to get all nested children? I mean plete collection from all nested levels so that I do not need to call function recursively.
Here is my function
$.fn.extend({
pressElementsWidth: function() {
var range = { min: 9999, max: 0 };
console.log( $(this).contents() );
$(this).contents().filter(
function() {
if (this.nodeType == 3 )
return this.nodeValue && this.nodeValue.replace(/\s{1,6}/,'') ? $(this) : null;
else
return this.nodeName.match(/IMG|A|GROUP|FIELDSET|INPUT|SELECT|TEXTAREA|BUTTON|SUBMIT/) ? $(this) : null;
}).each(function(e) {
var left = $(this).position();
if (p.left < range.min )
range.min = p.left;
var right = p.left + $(this).width;
if ( right > range.max )
range.max = right;
});
var max_width = range.max - range.min;
$(this).contents().filter(
function()
{
if (this.nodeType == 3 )
return this.nodeValue && this.nodeValue.replace(/\s{1,6}/,'') ? $(this) : null;
else
return this.nodeName.match(/IMG|A|GROUP|FIELDSET|INPUT|SELECT|TEXTAREA|BUTTON|SUBMIT/) ? $(this) : null;
}).each(function(e) {
$(this).css("max-width:", max_width );
});
}
});
window.onload = function() {
$("div.column-right-outer")pressElementsWidth();
};
So I need to get all elements inside the div.column-right-outer. You can test this code on this page, just save it and include jQuery and the code above. For example in the Blog Archive, there is huge list of links and I need to get all the links and all the visible text which is under the right column. If there would be images or form elements I need them in the collection too.
Results of recursion and $(node).find("*") are about 10.000-16.000 and extremely slow performance.
Is there some method in jQuery to get all nested children? I mean plete collection from all nested levels so that I do not need to call function recursively.
Here is my function
$.fn.extend({
pressElementsWidth: function() {
var range = { min: 9999, max: 0 };
console.log( $(this).contents() );
$(this).contents().filter(
function() {
if (this.nodeType == 3 )
return this.nodeValue && this.nodeValue.replace(/\s{1,6}/,'') ? $(this) : null;
else
return this.nodeName.match(/IMG|A|GROUP|FIELDSET|INPUT|SELECT|TEXTAREA|BUTTON|SUBMIT/) ? $(this) : null;
}).each(function(e) {
var left = $(this).position();
if (p.left < range.min )
range.min = p.left;
var right = p.left + $(this).width;
if ( right > range.max )
range.max = right;
});
var max_width = range.max - range.min;
$(this).contents().filter(
function()
{
if (this.nodeType == 3 )
return this.nodeValue && this.nodeValue.replace(/\s{1,6}/,'') ? $(this) : null;
else
return this.nodeName.match(/IMG|A|GROUP|FIELDSET|INPUT|SELECT|TEXTAREA|BUTTON|SUBMIT/) ? $(this) : null;
}).each(function(e) {
$(this).css("max-width:", max_width );
});
}
});
window.onload = function() {
$("div.column-right-outer").pressElementsWidth();
};
So I need to get all elements inside the div.column-right-outer. You can test this code on this page, just save it and include jQuery and the code above. For example in the Blog Archive, there is huge list of links and I need to get all the links and all the visible text which is under the right column. If there would be images or form elements I need them in the collection too.
Results of recursion and $(node).find("*") are about 10.000-16.000 and extremely slow performance.
Share Improve this question edited Sep 1, 2016 at 17:00 John Boe asked Sep 1, 2016 at 15:16 John BoeJohn Boe 3,62110 gold badges43 silver badges78 bronze badges 2- What are you planning on doing with all of this info? – ntgCleaner Commented Sep 1, 2016 at 15:23
- This is a function which should calculate "plete content width" of the column (wrapper). In this particular page it is not perfect example. But if you would remove the column "Popular Posts", than it should press width of the column so that the redundant width is removed. – John Boe Commented Sep 1, 2016 at 15:28
5 Answers
Reset to default 4method in JQuery to get all nested children
You can use the all selector : "*"
Combine this with the parent element in any number of ways:
var nodes = $("div.column-right-outer *");
var nodes = $("div.column-right-outer > *");
var nodes = $("div.column-right-outer").find("*");
If you need all items, then don't apply a parent:
var nodes = $("*")
Example fiddle: https://jsfiddle/9xted244/
.contents()
is similar to "*" and will include text and ments
What about element.childNodes
?
https://developer.mozilla/en-US/docs/Web/API/Node/childNodes
EDIT
childNodes
returns a collection of node, including text nodes. Every tabulation and line break are text nodes.
I would suggest using jQuery's contents() method. It is used for this exact purpose, if I am not mistaken.
See the API here: https://api.jquery./contents/
Are you calling it in a frame load?
$("#frame").load(function() {
... contents method
});
maybe write a function that dives into each thing?
function dive(that) {
var element_width = that.width();
array_width.push(that.width());
if(that.children().length > 0){
that.children().each(function(){
dive($(this));
});
}
}
var array_width = [];
dive($('div.column-right-outer'));
This should push the widths of your elements into an array. I haven't tested it, but maybe this is a start?
Also, not sure how fast/slow it would be.
Here is the result of my tests.
1) console.log($('div.column-right-outer').contents());
gives three results
2.1) recursive call with contents()
produces about 27.000 of results +/- extremely slow performance.
2.2) find("*") is similar, same count of results and extremely slow performance
3) console.log($('div.column-right-outer').find("*").filter(":visible"));
produces 224 results. This is correct. The performance seems better but I think the find("*") still can reduce performance.
Now, the code of updated function:
<script src="https://ajax.googleapis./ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script>
$.fn.extend({
pressElementsWidth: function() {
var range = { min: 9999, max: 0 };
$(this).find("*").filter(":visible").filter(
function() {
if (this.nodeType == 3 )
return this.nodeValue && this.nodeValue.replace(/\s{1,6}/,'') ? $(this) : null;
else
{
var result = this.nodeName.match(/IMG|A|GROUP|FIELDSET|INPUT|SELECT|TEXTAREA|BUTTON|SUBMIT/);
return this.nodeName.match(/IMG|A|GROUP|FIELDSET|INPUT|SELECT|TEXTAREA|BUTTON|SUBMIT/) ? $(this) : null;
}
}).each(function(e) {
var left = $(this).position();
if (p.left < range.min )
range.min = p.left;
var right = p.left + $(this).width;
if ( right > range.max )
range.max = right;
});
var max_width = range.max - range.min;
$(this).find("*").filter(":visible").filter(
function()
{
if (this.nodeType == 3 )
return this.nodeValue && this.nodeValue.replace(/\s{1,6}/,'') ? $(this) : null;
else
return this.nodeName.match(/IMG|A|GROUP|FIELDSET|INPUT|SELECT|TEXTAREA|BUTTON|SUBMIT/) ? $(this) : null;
}).each(function(e) {
$(this).css("max-width:", max_width );
});
}
});
window.onload = function() {
$("div.column-right-outer").pressElementsWidth();
// console.log($('div.column-right-outer').find("*").filter(":visible"));
};
</script>
To test it just save this page and insert the code above into the file.
Note: the function is still not fully working because it should enter to the function on line #16 where is var left =
... this does not happen. It returns $(this) when result of the match is array. This happens when .nodeName is "A". But still it does not enter to the next function after return from here. I also tried to return this. Any idea how to fix this?