jQuery: How to wrap RegEx matched plain text in an

2020-02-11 06:08发布

Suppose I have an HTML page that looks something like this:

<html><body>
00123
<input value="00123">
00456
</body></html>

And I want to use javascript/jQuery to make it look like this:

<html><body>
<a href="#00123">00123</a>
<input value="00123">
<a href="#00456">00456</a>
</body></html>

Essentially I want to wrap regular expression matched plain strings in the document with HTML anchor tags. In this example, I want to do something like:

$('body').html($('body').html().replace(/(00\d+)/, '<a href="#$1">$1</a>'));

See the jsFiddle with this example: http://jsfiddle.net/NATnr/2/

The problem with this solution is that the text inside the input element is matched and replaced.

Does anyone know how to only match and replace plain text in a document in this manner using javascript/jQuery?

4条回答
三岁会撩人
2楼-- · 2020-02-11 06:42

This from a related answer to a question by bobince:

You're right to not want to be processing HTML with regex. It's also bad news to be assigning huge chunks of .html(); apart from the performance drawbacks of serialising and reparsing a large amount of HTML, you'll also lose unserialisable data like event listeners, form data and JS properties/references.

Here's a plain JavaScript/DOM one that allows a RegExp pattern to match. jQuery doesn't really give you much help here since selectors can only select elements, and the ‘:contains’ selector is recursive so not too useful to us.

// Find text in descendents of an element, in reverse document order
// pattern must be a regexp with global flag
//
function findText(element, pattern, callback) {
    for (var childi= element.childNodes.length; childi-->0;) {
        var child= element.childNodes[childi];
        if (child.nodeType==1) {
            findText(child, pattern, callback);
        } else if (child.nodeType==3) {
            var matches= [];
            var match;
            while (match= pattern.exec(child.data))
                matches.push(match);
            for (var i= matches.length; i-->0;)
                callback.call(window, child, matches[i]);
        }
    }
}

findText(document.body, /\bBuyNow\b/g, function(node, match) {
    var span= document.createElement('span');
    span.className= 'highlight';
    node.splitText(match.index+6);
    span.appendChild(node.splitText(match.index+3));
    node.parentNode.insertBefore(span, node.nextSibling);
});
查看更多
霸刀☆藐视天下
3楼-- · 2020-02-11 06:44

The final solution ended up looking like this:

jQuery.fn.linker = function () {
    $(this).contents()
        .filter(function() { return this.nodeType != Node.TEXT_NODE; })
        .each(function () { $(this).linker(); });
    $(this).contents()
        .filter(function() { return this.nodeType == Node.TEXT_NODE; })
        .each(function () {
            $(this).replaceWith(
                $(this).text().replace(/(00\d+)/g, '<a href="#$1">$1</a>')
            );
        });
}
$(document).ready(function () {
    $('body').linker();
});

See the jsFiddle at work here: http://jsfiddle.net/fr4AL/4/

Thanks to:

查看更多
对你真心纯属浪费
4楼-- · 2020-02-11 06:52

Try filtering the body's contents() by nodeType to get only the Text Nodes, then replace them with jQuery-generated anchor elements (any extra text in these nodes will be kept as Text Node):

$('body').contents().filter(function() {
    return this.nodeType === 3;
}).each(function() {
    $(this).replaceWith($(this).text().replace(/(00\d+)/g, '<a href="#$1">$1</a>'));
});

Fiddle

As you know, most often it's not a good idea to parse HTML with Regex (look out for the ponies, they are evil), but if you isolate a part of the HTML you want to parse and it follows a relatively simple pattern, it is a viable option.

edit: Included the g flag (global modifier) in your Regex to allow for matching multiple anchors inside a single Text Node.

查看更多
虎瘦雄心在
5楼-- · 2020-02-11 06:59

Give this a whirl.... Much cleaner!! ;)

$('input').each(function() {
    var temp;
       temp = $(this).val();
       $(this).before('<a href="#' + temp +'">' +temp+ '</a>');
});
$('body').contents().filter(function() {return this.nodeType == 3;}).remove();
查看更多
登录 后发表回答