Find and replace/wrap text non-destructively in jQuery
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
README.md
jquery.safeReplace.js
safeReplace.jquery.json

README.md

jquery.safeReplace

Search and replace text in the DOM without messing up or removing html content! Very awesome for Chrome and Firefox extensions! Will not remove event bindings! You buy now!

$('div').safeReplace('half-empty', 'half-full');

Turns this:

<div><span>half-empty</span></div>

into this:

<div><span>half-full</span></div>

Regular Expression

Search from a root element (or elements) for text matching a regular expression.

$('div').safeReplace(/@[A-Za-z0-9_]+/g, '@Glench');

Turns this:

<div><span>@Jmondo</span></div>

into this:

<div><span>@Glench</span></div>

Also supports capture groups:

$('div').safeReplace(/(@[A-Za-z0-9_]+)/g, '$1_sucks');

Turns this:

<div><span>@Jmondo</span></div>

into this:

<div><span>@Jmondo_sucks</span></div>

Function

Replacing with a static string not good enough? Use a function to manipulate the text:

var wrapTwitterLink = function($textNode, matchedText, match) {
    $textNode.wrap('<a href="http://twitter.com/'+ matchedText +'">');
};

$('div').safeReplace(/@([A-Za-z0-9_]+)/g, wrapTwitterLink);

Turn this:

<div><span>@Glench</span></div>

into:

<div><span><a href="http://twitter.com/@Glench">@Glench</a></span></div>

You could also do the above example like this:

$('div').safeReplace(/@([A-Za-z0-9_]+)/g, '<a href="http://twitter.com/$1">$1</a>');

BUT WAIT!

What happens if you had something like this and ran the above example?

<div><a href="http://twitter.com/Glench">@Glench</a></div>

Well...

<div><a href="http://twitter.com/Glench"><a href="http://twitter.com/Glench">@Glench</a></a></div>

As you can see, this plugin naively tries to put a link inside a link, dawg. That's no good. Use the third argument to the plugin to limit what you traverse:

$('div').safeReplace(/@([A-Za-z0-9_]+)/g, wrapTwitterLink, 'a');

Now we won't look for text in 'a' elements. By default, safeReplace won't look at html, script, iframe, and many other elements.

API

$(selector).safeReplace(finder, replacer [, doNotFollowSelector, doNotFollowHidden])
Argument Explanation Example
finder A string or regular expression to match against. Note that if you don't provide the 'g' flag to regular expressions, this plugin will only replace the first match in a text node. /\d+/g
replacer A string or a function that will replace finder. If a function, the first argument is a jQuery text node of the matched text. The second argument is the matched text. The third argument is the RegExp match object. Note that no jQuery functions that user inner JavaScript functions will work, as this is a text node. That means no append() or prepend(). Use before and after() instead.
function($matchingNode, matchedText, regExpMatch) {
    $matchingNode.wrap("/");
}
doNotFollowSelector A CSS (not jQuery) selector used to determine if this plugin should traverse into an element. If an element in the traversal matches this selector, it will be skipped. By default it will ignore: html, head, style, title, link, meta, script, object, iframe, noscript 'code, pre'
doNotFollowHidden Default: false. Prevents the function from traversing hidden elements. false

Note: If you get double-wrapping, be more careful with your selectors. For example, try not to use $('div') when there are a bunch of nested divs.

Works in most browsers except IE8. If you need IE8 compatability, let me know.