Created
November 25, 2012 21:27
-
-
Save Fordi/4145449 to your computer and use it in GitHub Desktop.
Replace in DOM textNodes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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