2016-09-01 53 views
1

jQuery中有一些方法可以获取所有嵌套子元素吗?我的意思是从所有嵌套级别完整收集,以便我不需要递归调用函数。如何使用jQuery获取所有嵌套元素?

这里是我的功能

$.fn.extend({ 
    compressElementsWidth: 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").compressElementsWidth(); 
}; 

所以我需要得到内部的所有元素div.column,右外。您可以在this page上测试此代码,只需保存它并包含jQuery和上面的代码即可。例如在博客档案中,有大量的链接列表,我需要获取所有链接和右列下的所有可见文本。如果有图像或表单元素,我也需要它们。

enter image description here

递归和$(节点).find( “*”)的结果是约10.000-16.000和极其缓慢的性能。 enter image description here

+0

你打算如何处理所有这些信息? – ntgCleaner

+0

这是一个函数,它应该计算列(包装器)的“完整内容宽度”。在这个特定的页面中,它并不是完美的例子。但是,如果要删除“热门帖子”列,则应该压缩列的宽度,以便删除多余的宽度。 – user1141649

回答

0

element.childNodes怎么样?

https://developer.mozilla.org/en-US/docs/Web/API/Node/childNodes

编辑

childNodes返回节点的集合,包括文本节点。每个制表符和换行符都是文本节点。

+0

“所有级别的所有孩子” - '.contents()'完全按照您的要求:递归地加载所选项目下的所有子项目。这不是只有低一级的“孩子”。 –

+0

奇怪的功能。当我将它改为收集.prop(“nodeName”)时,它会产生数千个分区......没有任何意义。这是极端缓慢的。疯。类似像... find(“*”)但可能找到更快一点。 – user1141649

0

我会建议使用jQuery的contents()方法。如果我没有弄错,它被用于这个确切的目的。

在这里看到的API:https://api.jquery.com/contents/

你是在一个框架负载打电话呢?在JQuery中

$("#frame").load(function() { 

    ... contents method 

}); 
+0

你能写一个递归函数来调用contents方法,直到没有任何内容/文本为止吗? –

+0

.contents已递归加载所有子节点。 –

+0

查看更新的答案,尝试直接把它放在jQuery的负载,而不是窗口onload –

3

方法来获取所有嵌套子

可以使用all selector: “*”

以任何方式与父元素结合本:

var nodes = $("div.column-right-outer *"); 
var nodes = $("div.column-right-outer > *"); 
var nodes = $("div.column-right-outer").find("*"); 

如果您需要所有项目,则不要应用父项:

var nodes = $("*") 

例小提琴:https://jsfiddle.net/9xted244/


.contents()类似于 “*”,将包括文本和注释

+0

我读到*很慢。我试过了。问题是结果中有大约26000个节点(看起来好像有整个文档中的节点)。确切地说,我试过这个:'$(this).find(“*”)。contents()'...我期望列表中的36个节点或类似的+/- 100个节点。我不需要不可见的文本,只需要可见的元素。 – user1141649

+0

用户要么是'*'要么是'.contents()' - 而不是两者,否则你会多次返回相同的元素。 –

+1

'$(“*”)。filter(“:visible”)' –

0

也许写潜入每个事物的功能?

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')); 

这应该将元素的宽度推入数组中。我还没有测试过,但也许这是一个开始?

另外,不知道它会有多快/多慢。

0

这是我测试的结果。

1)console.log($('div.column-right-outer').contents()); 给出三个结果

2.1)递归调用与contents()产生的结果非常+/-性能慢约27.000。 2.2)发现( “*”)是结果的相似,相同的计数和极慢性能

3)console.log($('div.column-right-outer').find("*").filter(":v‌​isible")); 产生结果。这是对的。性能似乎更好,但我认为find(“*”)仍然会降低性能。现在

,更新功能的代码:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script> 
<script> 
$.fn.extend({ 
    compressElementsWidth: 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").compressElementsWidth(); 
    // console.log($('div.column-right-outer').find("*").filter(":visible")); 
}; 
</script> 

为了测试它只是保存this page并插入上面的代码到文件中。

注意:该功能仍然没有完全工作,因为它应该输入到#16行的功能,其中是var left = ......这种情况没有发生。当匹配的结果是数组时,它返回$(this)。当.nodeName是“A”时会发生这种情况。但是从这里返回后它仍然没有进入下一个功能。我也试图回复这个。任何想法如何解决这个问题?