My latest attempt tries to handle if the "unlink" file is missing and
uses a linkTopicsOnce setting:

(function($) {

        $.fn.extend({
                linktopics: function( settings ) {
                        var self = this;
                        this.settings = $.extend({}, $.linktopics.defaults, 
settings);
                        this.topics = null;
                        this.trimTopics = function () {
                                for ( var i = 0; i < self.topics.length; i++ ) {
                                        var allowed = true;
                                        for ( var j = 0, numStopLinks = 
self.stopLinks.length; j <
numStopLinks; j++ ) {
                                                if ( self.stopLinks[j] == 
self.topics[i].topic ) {
                                                        allowed = false;
                                                        break;
                                                }
                                        }
                                        if ( ! allowed ) {
                                                void( self.topics.splice( i, 1 
) );
                                        }
                                }
                        };
                        this.setupRegexes = function () {
                                for ( var i = 0, numTopics = 
self.topics.length; i < numTopics; i+
+ ) {
                                        self.topics[i].linked = false;
                                        
self.topics[i].strings.sort(function(a,b) {     // longer strings
come first
                                                if ( a.length > b.length ) {
                                                        return -1;
                                                } else if ( a.length < b.length 
) {
                                                        return 1;
                                                } else {
                                                        return 0;
                                                }
                                        });
                                        self.topics[i].regexes = new
Array(self.topics[i].strings.length);
                                        for ( var j = 0, numStrings = 
self.topics[i].strings.length; j <
numStrings; j++ ) {
                                                self.topics[i].regexes[j] = new 
RegExp( "(^|\\W)(" +
self.topics[i].strings[j].replace( /([\[\]\(\)\.\*\$\^\?\+\\])/g, '\\
$1' ) + ")((?!\\w)(?![^<]*(?:>|<\\/a)))" );
                                        }
                                }
                        };
                        this.linkHtml = function () {
                                self.each(function() {
                                        for ( var i = 0, numTopics = 
self.topics.length; i < numTopics; i+
+ ) {
                                                if ( self.topics[i].linked == 
false ) {
                                                        for ( var j = 0, 
numRegexes = self.topics[i].regexes.length; j
< numRegexes; j++ ) {
                                                                if ( 
$(this).html().search( self.topics[i].regexes[j] ) !=
-1 ) {
                                                                        
$(this).html( $
(this).html().replace( self.topics[i].regexes[j], '$1<a rel="topic"
title="Topic: ' + self.topics[i].topic + '" href="' +
self.topics[i].link + '">$2<\/a>$3' ) );
                                                                        if ( 
self.settings.linkTopicsOnce ) {
                                                                                
self.topics[i].linked = true;
                                                                                
break;
                                                                        }
                                                                }
                                                        }
                                                }
                                        }
                                });
                        };
                        $.getJSON( self.settings.topicLinkJsonUrl, 
function(json) {
                                if ( typeof json.topics == "object" ) {
                                        self.topics = json.topics;
                                        self.stopLinks = new Array();
                                        $.ajax({
                                                type: "GET",
                                                url: 
self.settings.topicUnlinkJsonUrl,
                                                dataType: "json",
                                                success: function(json){
                                                        if ( typeof 
json.stoplinks == "object" ) {
                                                                self.stopLinks 
= json.stoplinks;
                                                        }
                                                        self.trimTopics();
                                                        self.setupRegexes();
                                                        self.linkHtml();
                                                },
                                                error: function(xhr,errType,e) {
                                                        self.setupRegexes();
                                                        self.linkHtml();
                                                }
                                        });
                                }
                        });
                }
        });

        $.linktopics = {};

        // define global defaults, editable by client
        $.linktopics.defaults = {
                topicLinkJsonUrl: "topics_link.json",
                topicUnlinkJsonUrl: "topics_unlink.json",
                linkTopicsOnce: true
        };

})(jQuery);

Reply via email to