2016-09-01 71 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」時會發生這種情況。但是從這裏返回後它仍然沒有進入下一個功能。我也試圖回覆這個。任何想法如何解決這個問題?