使用JavaScript清除全局搜索和替换?

时间:2009-06-10 18:02:44

标签: javascript replace

我正在编写一个小书市,将当前页面中的所有设备转换为另一个。我非常依赖regexp,而且我使用Jquery来简化工作。

现在,我这样做就像一头大肥猪,取代全身:

$("body").children().each(function(){
    var $this = $(this);
    var h = $.html().replace(/eyes_hurting_regexp/g, "my_super_result");
    $this.html(h);
});

它在静态页面上工作正常,但如果涉及到js事件,那就是启示录。

我能想到的唯一方法是通过所有节点,检查它是否只包含文本,然后替换文本。在沉重的HTML标记上,我很担心这些信息。

这里有什么想法吗?

2 个答案:

答案 0 :(得分:8)

不幸的是,逐步浏览每个文本节点是唯一的可靠方法。这在过去对我有用:( demo

function findAndReplace(searchText, replacement, searchNode) {
    if (!searchText || typeof replacement === 'undefined') {
        // Throw error here if you want...
        return;
    }
    var regex = typeof searchText === 'string' ?
                new RegExp(searchText, 'g') : searchText,
        childNodes = (searchNode || document.body).childNodes,
        cnLength = childNodes.length,
        excludes = 'html,head,style,title,link,meta,script,object,iframe';
    while (cnLength--) {
        var currentNode = childNodes[cnLength];
        if (currentNode.nodeType === 1 &&
            (excludes + ',').indexOf(currentNode.nodeName.toLowerCase() + ',') === -1) {
            arguments.callee(searchText, replacement, currentNode);
        }
        if (currentNode.nodeType !== 3 || !regex.test(currentNode.data) ) {
            continue;
        }
        var parent = currentNode.parentNode,
            frag = (function(){
                var html = currentNode.data.replace(regex, replacement),
                    wrap = document.createElement('div'),
                    frag = document.createDocumentFragment();
                wrap.innerHTML = html;
                while (wrap.firstChild) {
                    frag.appendChild(wrap.firstChild);
                }
                return frag;
            })();
        parent.insertBefore(frag, currentNode);
        parent.removeChild(currentNode);
    }
}

答案 1 :(得分:0)

我根据自己的需要修改了脚本,并将新版本放在这里以防有人需要新功能:

  • 可以处理替换回调函数。
  • 外部节点黑名单。
  • 有些评论所以代码不会伤害别人的眼睛: - )

    function findAndReplace(searchText, replacement, callback, searchNode, blacklist) {
    
    var regex = typeof searchText === 'string' ? new RegExp(searchText, 'g') : searchText,
        childNodes = (searchNode || document.body).childNodes,
        cnLength = childNodes.length,
        excludes = blacklist || {'html' : '',
                    'head' : '',
                    'style' : '',
                    'title' : '',
                    'link'  : '',
                    'meta' : '',
                    'script' : '',
                    'object' : '',
                    'iframe' : ''};
    
    while (cnLength--) 
    {
        var currentNode = childNodes[cnLength];
    
        // see http://www.sutekidane.net/memo/objet-node-nodetype.html for constant ref 
    
        // recursive call if the node is of type "ELEMENT" and not blacklisted
        if (currentNode.nodeType === Node.ELEMENT_NODE &&
            !(currentNode.nodeName.toLowerCase() in excludes)) {
            arguments.callee(searchText, replacement, callback, currentNode, excludes);
        }
    
        // skip to next iteration if the data is not a text node or a text that matches nothing
        if (currentNode.nodeType !== Node.TEXT_NODE || !regex.test(currentNode.data) ) {
            continue;
        }
    
        // generate the new value
        var parent = currentNode.parentNode;
        var new_node = (callback 
                       || (function(text_node, pattern, repl) {
                                text_node.data = text_node.data.replace(pattern, repl); 
                                return text_node;
                           }))
                      (currentNode, regex, replacement);
    
       parent.insertBefore(new_node, currentNode);
       parent.removeChild(currentNode);
    
    }
    }
    

回调函数示例:

findAndReplace(/foo/gi, "bar", function(text_node, pattern, repl){

    var wrap = document.createElement('span');
    var txt = document.createTextNode(text_node.data.replace(pattern, repl));
    wrap.appendChild(txt);

    return wrap;

});

再次感谢J-P,感谢这段非常有用的代码。