diff --git a/code/modules/goonchat/browserassets/js/browserOutput.js b/code/modules/goonchat/browserassets/js/browserOutput.js
index a7a2a1118189..8f7194917c80 100644
--- a/code/modules/goonchat/browserassets/js/browserOutput.js
+++ b/code/modules/goonchat/browserassets/js/browserOutput.js
@@ -78,12 +78,6 @@ function clamp(val, min, max) {
return Math.max(min, Math.min(val, max))
}
-function outerHTML(el) {
- var wrap = document.createElement('div');
- wrap.appendChild(el.cloneNode(true));
- return wrap.innerHTML;
-}
-
//Polyfill for fucking date now because of course IE8 and below don't support it
if (!Date.now) {
Date.now = function now() {
@@ -173,58 +167,62 @@ function byondDecode(message) {
return message;
}
-//Actually turns the highlight term match into appropriate html
-function addHighlightMarkup(match) {
+//Get a highlight markup span
+function createHighlightMarkup() {
var extra = '';
if (opts.highlightColor) {
- extra += ' style="background-color: '+opts.highlightColor+'"';
+ extra += ' style="background-color: ' + opts.highlightColor + '"';
}
- return ''+match+'';
+ return '';
}
-//Highlights words based on user settings
-function highlightTerms(el) {
- if (el.children.length > 0) {
- for(var h = 0; h < el.children.length; h++){
- highlightTerms(el.children[h]);
+// Get all child text nodes that match a regex pattern
+function getTextNodes(elem, pattern) {
+ var result = $([]);
+ $(elem).contents().each(function(idx, child) {
+ if (child.nodeType === 3 && /\S/.test(child.nodeValue) && pattern.test(child.nodeValue)) {
+ result = result.add(child);
}
- }
-
- var hasTextNode = false;
- for (var node = 0; node < el.childNodes.length; node++)
- {
- if (el.childNodes[node].nodeType === 3)
- {
- hasTextNode = true;
- break;
+ else {
+ result = result.add(getTextNodes(child, pattern));
}
- }
+ });
+ return result;
+}
- if (hasTextNode) { //If element actually has text
- var newText = '';
- for (var c = 0; c < el.childNodes.length; c++) { //Each child element
- if (el.childNodes[c].nodeType === 3) { //Is it text only?
- var words = el.childNodes[c].data.split(' ');
- for (var w = 0; w < words.length; w++) { //Each word in the text
- var newWord = null;
- for (var i = 0; i < opts.highlightTerms.length; i++) { //Each highlight term
- if (opts.highlightTerms[i] && words[w].toLowerCase().indexOf(opts.highlightTerms[i].toLowerCase()) > -1) { //If a match is found
- newWord = words[w].replace("<", "<").replace(new RegExp(opts.highlightTerms[i], 'gi'), addHighlightMarkup);
- break;
- }
- if (window.console)
- console.log(newWord)
- }
- newText += newWord || words[w].replace("<", "<");
- newText += w >= words.length ? '' : ' ';
- }
- } else { //Every other type of element
- newText += outerHTML(el.childNodes[c]);
+// Highlight all text terms matching the registered regex patterns
+function highlightTerms(el) {
+ var pattern = new RegExp("(" + opts.highlightTerms.join('|') + ")", 'gi');
+ var nodes = getTextNodes(el, pattern);
+
+ nodes.each(function (idx, node) {
+ var content = $(node).text();
+ var parent = $(node).parent();
+ var pre = $(node.previousSibling);
+ $(node).remove();
+ content.split(pattern).forEach(function (chunk) {
+ // Get our highlighted span/text node
+ var toInsert = null;
+ if (pattern.test(chunk)) {
+ var tmpElem = $(createHighlightMarkup());
+ tmpElem.text(chunk);
+ toInsert = tmpElem;
}
- }
- el.innerHTML = newText;
- }
-}
+ else {
+ toInsert = document.createTextNode(chunk);
+ }
+
+ // Insert back into our element
+ if (pre.length == 0) {
+ var result = parent.prepend(toInsert);
+ pre = $(result[0].firstChild);
+ }
+ else {
+ pre.after(toInsert);
+ pre = $(pre[0].nextSibling);
+ }
+ });
+ });
function iconError(E) {
var that = this;
@@ -408,7 +406,7 @@ function output(message, flag) {
//Actually do the snap
//Stuff we can do after the message shows can go here, in the interests of responsiveness
if (opts.highlightTerms && opts.highlightTerms.length > 0) {
- highlightTerms(entry);
+ highlightTerms($(entry));
}
}
@@ -751,15 +749,11 @@ $(function() {
internalOutput('Loaded ping display of: '+(opts.pingDisabled ? 'hidden' : 'visible')+'', 'internal');
}
if (savedConfig.shighlightTerms) {
- var savedTerms = $.parseJSON(savedConfig.shighlightTerms);
- var actualTerms = '';
- for (var i = 0; i < savedTerms.length; i++) {
- if (savedTerms[i]) {
- actualTerms += savedTerms[i] + ', ';
- }
- }
+ var savedTerms = $.parseJSON(savedConfig.shighlightTerms).filter(function (entry) {
+ return entry !== null && /\S/.test(entry);
+ });
+ var actualTerms = savedTerms.length != 0 ? savedTerms.join(', ') : null;
if (actualTerms) {
- actualTerms = actualTerms.substring(0, actualTerms.length - 2);
internalOutput('Loaded highlight strings of: ' + actualTerms+'', 'internal');
opts.highlightTerms = savedTerms;
}
@@ -1073,20 +1067,12 @@ $(function() {
$('body').on('submit', '#highlightTermForm', function(e) {
e.preventDefault();
- var count = 0;
- while (count < opts.highlightLimit) {
+ opts.highlightTerms = [];
+ for (var count = 0; count < opts.highlightLimit; count++) {
var term = $('#highlightTermInput'+count).val();
- if (term) {
- term = term.trim();
- if (term === '') {
- opts.highlightTerms[count] = null;
- } else {
- opts.highlightTerms[count] = term.toLowerCase();
- }
- } else {
- opts.highlightTerms[count] = null;
+ if (term !== null && /\S/.test(term)) {
+ opts.highlightTerms.push(term.trim().toLowerCase());
}
- count++;
}
var color = $('#highlightColor').val();