/**
 * jQuery lexique plugin. v0.1
 */

// Create closure. We do that to keep inside functions private.
// http://www.learningjquery.com/2007/10/a-plugin-development-pattern
(function($) {
  
    // Plugin definition
    jQuery.fn.lexique = function(_lexique, options) {
  
        // Extend our default options with those provided.
        // Note that the first arg to extend is an empty object -
        // this is to keep from overriding our "defaults" object.
        var opts = $.extend({}, jQuery.fn.lexique.defaults, options);

        ///////////////////////////////////////////////////////////////////////
        // We create everything we need.
        ///////////////////////////////////////////////////////////////////////

        var i = 0;
        var orig = "";
        var nval = "";
       
        // We create the regexp before (faster)
        var regtext1 = []
        var regtext2 = []
        var regexps0 = [];
        var regexps1 = [];
        var regexps2 = [];
        for (var word in _lexique)
        {
            var exp = "(\\b" + word + "\\b)";
            regtext1[word] = "____1____" + encodeString(_lexique[word]) + "____1____";
            regtext2[word] = "____2____" + encodeString(_lexique[word]) + "____2____";
            regexps0[word] = new RegExp(exp, "gi");
            regexps1[word] = new RegExp(regtext1[word], "g");
            regexps2[word] = new RegExp(regtext2[word], "g");
        }
    
        ///////////////////////////////////////////////////////////////////////
        // Go through each element and do the real work
        ///////////////////////////////////////////////////////////////////////
          
        return this.each(function() {
            var nodes = getTextNodes(this);
            for (var n=0; n<nodes.length; n++) {
                i = 0;
                var node = nodes[n];
                orig = node.nodeValue;
                nval = node.nodeValue;
                for (var word in _lexique) {
                    var reg = regexps0[word];
                    nval = nval.replace(reg, regtext1[word] + "$1" + regtext2[word]);
                }
                for (var word in _lexique) {
                    nval = nval.replace(regexps1[word],"<a class='lexique' title='Aller au lexique' href='" + _lexique[word] + "'>");
                    nval = nval.replace(regexps2[word],"</a>");
                }
                if (nval != orig) {
                    $(node).replaceWith(nval);
                }
            }
            return $(this);
        });
    }

    // Options
    jQuery.fn.lexique.defaults = {};

    ///////////////////////////////////////////////////////////////////////////
    // Encodes a string in numbers
    ///////////////////////////////////////////////////////////////////////////

    function encodeString(str) {
        var s = "";
        for (var i=0; i<str.length; i++) {
            s += str.charCodeAt(i);
        }
        return s;
    }

    ///////////////////////////////////////////////////////////////////////////
    // Goes through all the children recursively and returns text nodes
    // It doesn't go through links though.
    ///////////////////////////////////////////////////////////////////////////

    function getTextNodes(node) {
        var ret = [];
        var reg = new RegExp("^[\n\r\t\s]+$","");
        var tname = "";
        (function(el){
            if (el.nodeType == 3) {
                if (!reg.test(el.nodeValue)) {
                    ret.push(el);
                }
            }
            else {
                tname = el.tagName.toLowerCase();
                if (tname != "a" && tname != "h1" && tname != "h2" && tname != "h3" && tname != "h4" && tname != "h5" && tname != "h6")
                for (var i=0; i < el.childNodes.length; ++i)
                    arguments.callee(el.childNodes[i]);
            }
        })(node);
        return $(ret);
    }

// End of closure
})(jQuery);
