views:

54

answers:

1

I am trying to create a glossary system which will get a list of common words and their definitions via ajax, then replace any occurrence of that word in certain elements (those with the useGlossary class) with a link to the full definition and provide a short definition on mouse hover. The way I am doing it works, but for large pages it takes 30-40 seconds, during which the page hangs. I would like to either decrease the time it takes to do the replacement or make it so that the replacement is running in the background without hanging the page.

I am using jquery for most of the javascript, and Qtip for the mouse hover. Here is my existing slow code:

$(document).ready(function () {
    $.get("fetchGlossary.cfm", null, glossCallback, "json");
});

function glossCallback(data)
{

    $(".useGlossary").each(function() {
        var $this = $(this);
        for (var i in data)
        {

            $this.html($this.html().replace(new RegExp("\\b" + data[i].term + "\\b", "gi"), function(m) {return makeLink(m, data[i].def);}));
        }
        $this.find("a.glossary").qtip({ style: { name: 'blue', tip: true } })
    });
}

function makeLink(m, def)
{
    return "<a class='glossary glossary" + m.replace(/\s/gi, "").toUpperCase() + "' href='reference/glossary.cfm' title='" + def + "'>" + m + "</a>";
}

Thanks for any feedback/suggestions!

+2  A: 

Instead of replacing the HTML over and over, why not modify your function like so:

function glossCallback(data) 
{ 

    $(".useGlossary").each(function() { 
        var $this = $(this); 
        var html = $this.html();
        for (var i in data) 
        { 

            html.replace(new RegExp("\\b" + data[i].term + "\\b", "gi"), function(m) {return makeLink(m, data[i].def);}); 
        }
        $this.html(html);
        $this.find("a.glossary").qtip({ style: { name: 'blue', tip: true } }) 
    }); 
}

In this manner the DOM won't have to refresh on every replace.

BradBrening
Thanks. For some reason replace() doesn't work when used like that. I had to take out the function call and replace with the actual string, losing the ability to preserve the original case. Also, while this shaves a little off the time, its nowhere near usable on our longer pages. I'm probably going to have to do it on the server. I'll leave the question open a bit, to see if anyone else has other ideas, otherwise ill accept yours.
adharris
One other thing you could try is to create a global RegExp object and simply change its pattern - i.e. regExp.source="\\b" + data[i].term + "\\b". This would alleviate the recurring "new" on every iteration. I believe that may help.
BradBrening
I actually just took a look at the page our other dev was passing to this, the damn thing has over 3000 instances of useGlossary class, and the source is close to 100000 lines. Starting to think that is not completely my problem. Thanks!
adharris
No problem. Good mind exercise for a Sunday.
BradBrening