[jQuery] speeding up search and replace on lots of elements
I had originally written a script called the Jargon buster that does
search and replace on the html() of a page to insert links to jargon
terms. The code looks like this (cut down to incluse just the parts I
am interested in)
function JargonBuster (jargonFile)
{
var self = this;
// Jargon XML vars
self.jargon = new Object;
// HTML vars
self.targetContainer = $('body');
// Regular Expressions
self.regexPrefix = '(';
self.regexPostfix = ')(?!([a-zA-Z0-9 _:;/#\?&-]*?"?(>| [a-zA-
Z0-9_-]*?="?[a-zA-Z0-9 _:;/#\?&-]"?)|.*?</(a|h[1-2]|button|option|
script|style|textarea)>|.*?" />))';
self.regexOptions = 'gi';
self.insertJargon = function (xml)
// Insert each jargon term into the page
{
workingHtml = self.targetContainer.html ();
$('jargonterm', xml).each (function ()
{
thisTerm = $(this);
// Store each term in an array for easy access
self.jargon [thisTerm.attr ('id')] =
{
term : thisTerm.attr ('term'),
description : $('description', thisTerm).text (),
href : thisTerm.attr ('href'),
regex : thisTerm.attr ('regex')
};
// Insert links into HTML
thisSearch = new RegExp (self.regexPrefix + thisTerm.attr ('regex')
+ self.regexPostfix, self.regexOptions);
workingHtml = workingHtml.replace (
thisSearch,
'\r\n<a class="jargonbuster '+ thisTerm.attr ('id')
+ '" href="' + thisTerm.attr ('href')
+ '">$1</a>\r\n'
);
});
// Update the page HTML
self.targetContainer.html (workingHtml);
};
}
This runs pretty well and is fast, but it has a problem if there is a
jQuery effect occuring inside the container at the time that the
search and replace runs. The end result is a massive mess.
I determined the problem could be avoided if I did search and replace
on each element at a time instead of the entire body at once, and if I
exclude elements that may be having a jQuery effect executed on or in
them then the problem could be avoided. I rewrote my code as follows:
function JargonBuster (jargonFile)
{
var self = this;
// Jargon XML vars
self.jargon = new Object;
// HTML vars
self.targetContainer = $('body');
self.targetElements = 'p, h3, th, td, li';
// Regular Expressions
self.regexPrefix = '(';
self.regexPostfix = ')(?!([a-zA-Z0-9 _:;/#\?&-]*?"?(>| [a-zA-
Z0-9_-]*?="?[a-zA-Z0-9 _:;/#\?&-]"?)|.*?</(a|h[1-2]|button|option|
script|style|textarea)>|.*?" />))';
self.regexOptions = 'gi';
self.insertJargon = function (xml)
// Insert each jargon term into the page
{
elementsToProcess = $(self.targetElements, self.targetContainer);
$('jargonterm', xml).each (function ()
{
thisTerm = $(this);
// Store each term in an array for easy access
self.jargon [thisTerm.attr ('id')] =
{
term : thisTerm.attr ('term'),
description : $('description', thisTerm).text (),
href : thisTerm.attr ('href'),
regex : thisTerm.attr ('regex')
};
// Insert links into HTML
thisSearch = new RegExp (self.regexPrefix + thisTerm.attr ('regex')
+ self.regexPostfix, self.regexOptions);
elementsToProcess.each (function ()
{
thisElem = $(this);
thisElem.html (thisElem.html ().replace (
thisSearch,
'\r\n<a class="jargonbuster '+ thisTerm.attr ('id')
+ '" href="' + thisTerm.attr ('href')
+ '">$1</a>\r\n'
));
});
});
};
}
This approach allows both the search and replace and the jQuery
effexts to run at the same time without interfering with each other as
I hoped, but I have hit another big snag, namely that this new
approach is very slow. It can take several seconds for the search and
replace to complete, during which time the CPU usage is pegged at
100%.
What I really need is to find a way of achieving the results of the
second example with speed approaching that of the first example. I am
hoping that there is some way to do this, and that you guys can give
me some pointers. I am prepared to sacrifice some speed so that the
script can run in conjunction with the jQuery effects I want to apply,
but I need it to be faster than the version I have posted here. I'd
really appreciate any help and tips you can give.