summaryrefslogtreecommitdiffstats
path: root/theme/javascript/core/glossary.js
diff options
context:
space:
mode:
authorSamy Pessé <samypesse@gmail.com>2014-11-12 22:10:35 +0100
committerSamy Pessé <samypesse@gmail.com>2014-11-12 22:10:38 +0100
commit77043464b220cddda02a0d0212a03b1848bc014a (patch)
treeeaed08654e5ca577f13a0f5e80afea12410e2040 /theme/javascript/core/glossary.js
parentb90f74a8210b8939a78ba9664198dce2a2f902f6 (diff)
downloadgitbook-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.js101
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() {