Rorschach Rorschach - 6 months ago 41
Javascript Question

Highlight hashtags and @usernames using jquery and/or rails JS

I am using ruby on rails and jquery.

I am trying to find a way to notice all @... and #... in comments. I then want to make them links to http://www.example.com/user_profile/... or http://www.example.com/search/... respectively.

Firstly, I have to dynamically find all #...'s and @...'s in comments with jquery.

So, I am using the highlight code below (not made by me):

/*

highlight v5

Highlights arbitrary terms.

<http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html>

MIT license.

Johann Burkard
<http://johannburkard.de>
<mailto:jb@eaio.com>

*/

jQuery.fn.highlight = function(pat) {
function innerHighlight(node, pat) {
var skip = 0;
if (node.nodeType == 3) {
var pos = node.data.toUpperCase().indexOf(pat);
pos -= (node.data.substr(0, pos).toUpperCase().length - node.data.substr(0, pos).length);
if (pos >= 0) {
var spannode = document.createElement('span');
spannode.className = 'highlight';
var middlebit = node.splitText(pos);
var endbit = middlebit.splitText(pat.length);
var middleclone = middlebit.cloneNode(true);
spannode.appendChild(middleclone);
middlebit.parentNode.replaceChild(spannode, middlebit);
skip = 1;
}
}
else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
for (var i = 0; i < node.childNodes.length; ++i) {
i += innerHighlight(node.childNodes[i], pat);
}
}
return skip;
}
return this.length && pat && pat.length ? this.each(function() {
innerHighlight(this, pat.toUpperCase());
}) : this;
};

jQuery.fn.removeHighlight = function() {
return this.find("span.highlight").each(function() {
this.parentNode.firstChild.nodeName;
with (this.parentNode) {
replaceChild(this.firstChild, this);
normalize();
}
}).end();
};


I can find single words like

$('span').highlight('Word');


and it works

But I would like to highlight all words that have a @ or # at the beginning like this

$("span").highlight('/([#])([a-z])\w+/ig');
$("span").highlight('/([@])([a-z])\w+/ig');


But this code above does not work.

I am willing to use a different library and I am open to new higher level suggestions.

Answer

The plugin you've mentioned isn't build for regular expressions. It can only highlight single words without any customization and nothing more.

Use mark.js

With mark.js you can realize what you'd like to do. It is a text highlighter – written in pure JavaScript but also available as jQuery plugin – for keywords/search terms and custom regular expressions. Please have a look at the website for details on installation and API.

If you want to highlight a custom regular expression you would need to call it like:

$(".context").markRegExp(/RegExp/gi);

Demo with your code:

JSFIDDLE DEMO

$(document).ready(function() {
  $(".context").markRegExp(/([@]|[#])([a-z])\w+/gmi);
});
mark {
  background: yellow;
}
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://cdn.rawgit.com/julmot/mark.js/6.1.0/dist/jquery.mark.min.js"></script>
<div class="context">
  Lorem ipsum @dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata
  sanctus est Lorem ipsum dolor sit amet. #Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
  Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
</div>