-1

所以,我有一个脚本,它采用 body 的 innerHTML(是的,body 标记中的所有内容),将所有阿拉伯数字 (123) 转换为阿拉伯-印度数字 (١٢٣),并用更改后的替换 innerHTML。现在,解析器完美运行,只更改用户在页面上可见的数字,并避免标签属性中的数字,并保留“敏感”标签内的内容(如脚本、样式、noscript ...)不变(使用我正在解决的一些问题),就像我想要的那样!(顺便说一下,这是在chrome扩展中运行的,脚本在触发onLoad事件时运行)

但是由于某种原因,有些事情会停止正常运行。例如,对堆栈溢出进行随机问题;向上/向下投票按钮停止工作。我什至继续比较原始和未解析的 html:

http://www.diffchecker.com/gJE1v50f

那里一切看起来都很好;唯一的区别是数字,虽然一些对用户可见的链接(例如,格式帮助部分中的一个)被改变了,但我计划修复它,它对脚本没有影响,所以我忽略了它们目前。

感谢您花时间阅读,更感谢您的回答:)

4

2 回答 2

1

如上面评论中所述,替换页面正文中的 html 会导致生成所有新的(尽管与原始元素相同)元素,这会导致附加到它们的所有事件被丢弃。您要做的是遍历正文中的所有文本节点。使用 xpath 最容易做到这一点:

xpath = new XPathEvaluator()
xpath.evaluate("//text()", document.body)

这将返回当前文档正文中所有文本节点的数组。然后,您可以遍历它们并修改它们的每个内容。

另一个问题是,这可能仍然会破坏从您正在修改的文本节点中解析数字的脚本。我能想到的唯一解决方案(是的,它非常hackish)是扩展Number函数的行为:

(function (){
  var oldNumber = Number
  window.Number = function(obj){
    if(typeof obj == "string"){
      // replace numerals
      var numerals = ["٠","١","٢","٣","٤","٥","٦","٧","٨","٩"]
      for(idx in numerals){
        obj = obj.replace(new RegExp(numerals[idx],"g"), idx)
      }
      // replace decimal point
      obj.replace(/٫/g,".")
    }
    return oldNumber(obj)
  }
})()

您还必须扩展 parseInt 和 parseFloat 函数以使一切正常,尽管代码几乎相同。这将使从 html 中解析数字的脚本不会中断;但请注意,当它们将数字显示回网页时,它们将是普通的阿拉伯数字。要解决这个问题,您可以扩展 Number 的toString方法,但这可能比扩展相对安全的数字解析函数更危险。

于 2012-12-18T22:21:24.930 回答
1

我建议获取文本节点并直接修改它们:http: //jsfiddle.net/6pLeR/

// this will get all text nodes that are descendant of element. 
function getTextNodes(element) {
    var nodes = [],
        children = element.childNodes,
        i=0, child = children[0];

    for (; i < children.length; i++, child=children[i]) {
        if (child.nodeType === 3) nodes.push(child);
        else nodes = nodes.concat(getTextNodes(child));
    }

    return nodes;
}

var nodes = getTextNodes(document.body); // get all text nodes in the body.

for (var i = 0; i < nodes.length; i++) {
    var node = nodes[i];

    node.data = node.data.replace(/text/g, "banana"); // replace "text" with "banana"
}​

在demo中可以看到点击事件不受节点数据变化的影响。

于 2012-12-18T23:14:00.460 回答