Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery: How to wrap RegEx matched plain text in an anchor tag?

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?

like image 372
Rusty Fausak Avatar asked Jul 26 '12 02:07

Rusty Fausak


2 Answers

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.

like image 141
Fabrício Matté Avatar answered Oct 27 '22 04:10

Fabrício Matté


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:

  • Fabricio's answer
  • How do I select text nodes with jQuery?
  • http://api.jquery.com/wrap/
  • http://api.jquery.com/contents/
  • Converting HTML string into DOM elements?
like image 32
Rusty Fausak Avatar answered Oct 27 '22 04:10

Rusty Fausak