2016-08-01 55 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父元素,问题消失了。再次感谢! –