2013-05-25 49 views
0

隨着HTML這樣的:查找長度到一個點

<div id="container">                     
    <p>Lorem ipsum lorem ipsum 
    <p>This is the second! 
     <span data-attribute="my-span">Hello World</span> 
    </p> 
    </p> 
</div> 

我想找到從容器到我跨度文本長度。所以,通過計算後裔的indicies我得到的42

一個正確的答案,但如果我有HTML這樣的:

<div id="container">                     
     <p>Lorem ipsum lorem ipsum 
     <p>This is the second! 
      <span data-attribute="my-span">Hello World</span> 
     </p> 
     Some preceding HTML that I dont want! 
     </p> 
    </div> 

我不想字符數繼續我的跨度。我只希望字符數達到我的範圍,所以正確的答案仍然是42。但是,通過計算子文本長度,它還會在前面的文本中添加以及跨度的文本(這很容易通過減去從總數)。

我已經探索過列出html和子串,直到我想要的span屬性,拆分結束並解析出html,只留下我想要計數的文本字符。但這似乎過於複雜。

我還在考慮使用類似wicked good xpath的東西來查找所有節點,直到找到我想要的節點,然後總結文本。

我也看過列出所有文本節點到某一點並總結它們,但它列出了我的跨度文本之前的孩子的前面的文本,所以它不以正確的順序求和。

此外,嵌套可能是n級深,所以不要假設只有一個級別。

有關實現此目的的最佳方法的任何建議?

+0

裏面的「ipsum」之間的空間我認爲最簡單的方法是從底部開始,並在迴路中進行備份。選擇'span',然後繼續收集父母,直到找到容器'div'。 – shaun5

+0

@ shaun5父母將包含該文本 - 跨度文本,因此需要使用節點計數更復雜的方法,如Jans解決方案。 – bwvoss

回答

2

一個選項總是可用的是手動遍歷DOM樹。 jQuery並不擅長處理非元素節點(似乎所有孩子的後代都列在每個節點的所有子節點之後,當我們做.find('*').contents()時,只有contents是看到這些節點的唯一方法),但我們仍然可以使用native API。還要注意的是處理的空白是棘手這裏(我假設你想崩潰空白模仿渲染器的行爲)事情是這樣的:

function countCharsUntil(parent, selector, inclusive){ 
    var done = false; 
    return listChars(parent).replace(/\s+/g," ").trim().length; 

    function listChars(elem){ 
    var cn = elem.childNodes; 
    var chars = ""; 
    if(!inclusive && $(elem).is(selector)){ 
     done = true; 
     return "" 
    } 
    for(var i=0; i<cn.length && !done; i++){ 
     var child = cn[i]; 
     switch(child.nodeType){ 
     case Node.ELEMENT_NODE: 
      chars += listChars(child); 
      break; 
     case Node.TEXT_NODE: 
      chars += child.nodeValue; 
      break; 
     } 
    } 
    if(inclusive && $(elem).is(selector)){ 
     done = true; 
     return chars; 
    } 
    return chars; 
    } 
} 

測試:http://jsfiddle.net/8hxb6/1/

注意測試返回43個字符的獨家搜索。這可能是因爲你忽略了div>p裏面的「ipsum」和div>p>p裏面的div>p>p

+0

大聲笑+1,這就像谷歌的猴子解決方案 – Sam

1

這項工作的人

$(document).ready(function(){ 
    var tx = $('#container').text().split($('#container span').text())[0].replace(/[\s]{2,}/g,''); 
    console.log(tx.length); //42 
}); 

DEMO

+0

不錯的訣竅,但是如果跨度文本也存在於跨度之外的某個位置呢?然後它會破壞! –

+0

@JanDvorak他可以更改分割索引並加入其中的一部分,但這是一個基礎:P – Sam

+0

如果您不知道文本出現的次數,該怎麼辦?我認爲這不能起作用。 –