Skip to content

Instantly share code, notes, and snippets.

@Fordi
Created November 25, 2012 21:27
Show Gist options
  • Save Fordi/4145449 to your computer and use it in GitHub Desktop.
Save Fordi/4145449 to your computer and use it in GitHub Desktop.
Replace in DOM textNodes
// Early version of the Acronym Helper I'm working on.
(function (global) {
"use strict";
var $ = global.jQuery,
acronyms = {
'FAQ' : 'Frequently Asked Questions',
'TIL' : 'Today I Learned',
'ITT' : 'In This Thread',
'SRS' : 'A Load of Dingo\'s Kidneys'
};
function lookup(acronym, location) {
// This is intended to do a complex lookup involving context. For now, it just returns the result of a HashMap.
return acronyms[acronym];
}
$(function () {
$(global.document.body).replaceInText(/(\W)([A-Z]{2,5})(\W)/, function (fullMatch, sym1, acronym, sym2) {
var acr = lookup(acronym, global.window.location.toString()),
elem = $('<span>')
.addClass('acronym-helper')
.attr({
'data-acronym' : acronym,
title: 'Original: ' + acronym
})
.text(acr || acronym),
ret = [sym1, elem, sym2];
if (!acr) {
elem.addClass('no-acronym-found');
}
return ret;
});
});
}(this));
(function (global) {
"use strict";
var $ = global.jQuery;
function toString(obj) {
return obj ? (obj.toString || Object.prototype.toString).call(obj) : '';
}
/**
Is this a DOM node?
@param Object obj javascript varable to test for node-ness
*/
$.isNode = global.Node ?
function (obj) {
return obj instanceof global.Node;
} :
function (obj) {
return (typeof obj === "object") &&
(obj.nodeType) &&
(obj.nodeType !== undefined) &&
(obj.hasChildNodes instanceof Function);
};
/**
Get all text nodes descendent from a given node
*/
$.fn.textNodes = function () {
var ret = [];
this.each(function () {
var node = this.firstChild;
while (node !== null) {
if (node.nodeType === 3) {
ret.push(node);
} else {
ret = ret.concat($(node).textNodes().toArray());
}
node = node.nextSibling;
}
});
return $($.map(ret, function (n) { return n; }));
};
/**
Flatten a jQuery vector into a single layer
*/
$.fn.flatten = function () {
var ret = [];
this.each(function () {
if (this instanceof $) {
ret = ret.concat(this.toArray());
} else if ($.isArray(this)) {
ret = ret.concat(this);
} else {
ret.push(this);
}
});
return $(ret);
};
/**
Globally replace a regular expression with a string or with the result of a function call, but only within the text node descendents of a node
@param RegExp pattern Pattern to match against
@param String replacement replacement pattern
@param Function replacement function that is called with the content of a match, the return value of which is used to replace the matched string. This method should return a string, node, array of mixed strings and nodes, or jQuery object, representing what should be replaced.
@info Important: String return values get cast to TextNodes, not used as HTML. If you wish to return HTML, return $(myHTML), rather than myHTML.
@return jQuery original jQuery object (chainable).
*/
$.fn.replaceInText = function (pattern, replacement) {
this.textNodes().each(function () {
var i, acronym, right, mid,
parent = this.parentNode,
document = this.ownerDocument,
content = this.textContent,
nodes = [];
while (-1 !== (i = content.search(pattern))) {
nodes.push(document.createTextNode(content.substr(0, i)));
right = content.substr(i);
mid = right.match(pattern);
content = right.substr(mid[0].length);
if (replacement instanceof Function) {
mid = replacement.apply(this.parentNode, mid);
} else {
mid = mid[0].replace(pattern, replacement.toString());
}
if (!$.isNode(mid) && !(mid instanceof $) && !$.isArray(mid)) {
mid = document.createTextNode(toString(mid));
}
if (!(mid instanceof $)) {
mid = $(mid);
}
mid = mid.flatten();
nodes = nodes.concat(mid.flatten().toArray());
}
if (nodes.length) {
nodes.push(document.createTextNode(content));
parent = this.parentNode;
parent.replaceChild(nodes[0], this);
for (i = 1; i < nodes.length; i += 1) {
if (!$.isNode(nodes[i])) {
nodes[i] = document.createTextNode(nodes[i]);
}
if (nodes[i - 1].nextSibling) {
parent.insertBefore(nodes[i], nodes[i - 1].nextSibling);
} else {
parent.appendChild(nodes[i]);
}
}
}
});
return this;
};
}(this));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment