diff options
author | Samy Pessé <samypesse@gmail.com> | 2014-11-12 22:10:35 +0100 |
---|---|---|
committer | Samy Pessé <samypesse@gmail.com> | 2014-11-12 22:10:38 +0100 |
commit | 77043464b220cddda02a0d0212a03b1848bc014a (patch) | |
tree | eaed08654e5ca577f13a0f5e80afea12410e2040 /theme/javascript/core/glossary.js | |
parent | b90f74a8210b8939a78ba9664198dce2a2f902f6 (diff) | |
download | gitbook-77043464b220cddda02a0d0212a03b1848bc014a.zip gitbook-77043464b220cddda02a0d0212a03b1848bc014a.tar.gz gitbook-77043464b220cddda02a0d0212a03b1848bc014a.tar.bz2 |
Fix #496: improve replacement of glossary terms in html
Diffstat (limited to 'theme/javascript/core/glossary.js')
-rw-r--r-- | theme/javascript/core/glossary.js | 101 |
1 files changed, 51 insertions, 50 deletions
diff --git a/theme/javascript/core/glossary.js b/theme/javascript/core/glossary.js index 4db64d1..44ebab1 100644 --- a/theme/javascript/core/glossary.js +++ b/theme/javascript/core/glossary.js @@ -31,21 +31,57 @@ define([ return d.promise(); } + $.fn.replaceText = function( search, replace, text_only ) { + return this.each(function(){ + var node = this.firstChild, + val, + new_val, + // Elements to be removed at the end. + remove = []; - var pregQuote = function( str ) { - // http://kevin.vanzonneveld.net - // + original by: booeyOH - // + improved by: Ates Goral (http://magnetiq.com) - // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - // + bugfixed by: Onno Marsman - // * example 1: preg_quote("$40"); - // * returns 1: '\$40' - // * example 2: preg_quote("*RRRING* Hello?"); - // * returns 2: '\*RRRING\* Hello\?' - // * example 3: preg_quote("\\.+*?[^]$(){}=!<>|:"); - // * returns 3: '\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:' + // Only continue if firstChild exists. + if ( node ) { + + // Loop over all childNodes. + do { + + // Only process text nodes. + if ( node.nodeType === 3 ) { + + // The original node value. + val = node.nodeValue; + + // The new value. + new_val = val.replace( search, replace ); + + // Only replace text if the new value is actually different! + if ( new_val !== val ) { + + if ( !text_only && /</.test( new_val ) ) { + // The new value contains HTML, set it in a slower but far more + // robust way. + $(node).before( new_val ); + + // Don't remove the node yet, or the loop will lose its place. + remove.push( node ); + } else { + // The new value contains no HTML, so it can be set in this + // very fast, simple way. + node.nodeValue = new_val; + } + } + } + + } while ( node = node.nextSibling ); + } + // Time to remove those elements! + remove.length && $(remove).remove(); + }); + }; + + var pregQuote = function( str ) { return (str+'').replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1"); }; @@ -58,48 +94,13 @@ define([ }); }; - var matchText = function(node, regex, callback, excludeElements) { - excludeElements || (excludeElements = ['script', 'style', 'iframe', 'canvas']); - var child = node.firstChild; - - if (!child) return; - - do { - switch (child.nodeType) { - case 1: - if (excludeElements.indexOf(child.tagName.toLowerCase()) > -1) { - continue; - } - matchText(child, regex, callback, excludeElements); - break; - case 3: - child.data.replace(regex, function(all) { - var args = [].slice.call(arguments), - offset = args[args.length - 2], - newTextNode = child.splitText(offset); - - newTextNode.data = newTextNode.data.substr(all.length); - callback.apply(window, [child].concat(args)); - child = newTextNode; - }); - break; - } - } while (child = child.nextSibling); - - return node; - }; - var replaceTerm = function($el, term) { var r = new RegExp( "\\b(" + pregQuote(term.name.toLowerCase()) + ")\\b" , 'gi' ); - matchText($el.get(0), r, function(node, match, offset) { - var span = document.createElement("span"); - span.className = "glossary-term"; - span.textContent = match; - span.setAttribute("data-glossary-term", term.id); - span.setAttribute("title", term.description); - node.parentNode.insertBefore(span, node.nextSibling); + $el.find("*").replaceText(r, function(match) { + return "<span class='glossary-term' data-glossary-term='"+term.id+"' title='"+term.description+"'>"+match+"</span>"; }); + }; var prepare = function() { |