2016-08-01 16 views
0

我需要用跨度替換每個具有同級的#text,以使它們具有ids。下面的代碼應該這樣做,但由於某種原因它會導致許多文檔重新塑造:文檔的部分移動,頁面會改變其外觀。用跨度替換#text元素會導致文檔重新塑造

var eltId = 0; 

function genEltId() { 
    return "my-id-" + ++eltId; 
} 

function hashTextsToSpans(elt) { 
    for (var i in elt.childNodes) { 
     var eltChild = elt.childNodes[i]; 
     if (eltChild.nodeName == "#text" && elt.childNodes.length > 1) { 
      // #text is one of multiple childs 
      var eltDiv = document.createElement("span"); 
      eltDiv.setAttribute("id", genEltId()); 
      elt.replaceChild(eltDiv, eltChild); 
      eltDiv.appendChild(eltChild); 
     } else { 
      if (eltChild.nodeName != "IFRAME") { 
       hashTextsToSpans(eltChild); 
      } 
     } 
    } 
} 

function onKeyPress(e) { 
    if (e.keyCode == 105) { 
     // key I 
     hashTextsToSpans(document.body); 
    } 
} 

window.parent.addEventListener("keypress", onKeyPress); 

例如,(用「CJS」插件)注入它鉻成https://en.wikipedia.org/wiki/Linux,按「i」的,並且觀察到頁面重塑。

什麼問題?是否#text並跨越兩個內聯元素,並且在文本相同且跨度沒有樣式時應以相同的方式顯示?

假設:沒有iframe元素,沒有其他JavaScript同時操作DOM樹。

+0

你使用任何CSS框架? – doge1ord

+0

沒有框架,我正在注入js到維基百科作爲一個例子「cjs」插件。 –

+0

不是一個答案,但你可能想看看['TreeWalker' API](https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker),它可以在所有現代瀏覽器中使用並使這個任務更容易編碼和維護。 – rvighne

回答

1

問題是,在HTML中,許多元素對它們允許包含哪些類型的子節點有限制。

例如,列表元素(例如ulol)只能包含li元素和空白(僅空白)文本節點。當您將這些空白文本節點換成跨度時,該頁面突然不符合標準。

在您鏈接到維基百科頁面的特定情況下,原來的頁面包含了一個表的和td只有空白之間的tr元素文本節點。當您的腳本運行時,這些文本節點會變成跨度,但不允許表格中的trtd元素以外的元素。因此,這會導致大多數瀏覽器自動將幻像列插入到表格中,從而搞亂了佈局。

作爲一種快速解決方案,您可以忽略僅包含空格的文本節點。這是平凡的,如果你使用TreeWalker API,通過下面的函數傳遞作爲過濾器做:

node => /\S/.test(node.nodeValue) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT 

作爲一個更長期的修復,你可能需要尋找通過HTML5 spec知道了確定哪些元素被允許包含跨度節點,並相應地編寫腳本。

+1

謝謝你,你的回答是正確的!通過排除TABLE/TBODY/TR/UL/OL父元素,問題消失了。再次感謝! –