85 lines
2.1 KiB
JavaScript
85 lines
2.1 KiB
JavaScript
/*
|
|
* typeahead.js
|
|
* https://github.com/twitter/typeahead.js
|
|
* Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT
|
|
*/
|
|
|
|
// inspired by https://github.com/jharding/bearhug
|
|
|
|
var highlight = (function(doc) {
|
|
'use strict';
|
|
|
|
var defaults = {
|
|
node: null,
|
|
pattern: null,
|
|
tagName: 'strong',
|
|
className: null,
|
|
wordsOnly: false,
|
|
caseSensitive: false
|
|
};
|
|
|
|
return function hightlight(o) {
|
|
var regex;
|
|
|
|
o = _.mixin({}, defaults, o);
|
|
|
|
if (!o.node || !o.pattern) {
|
|
// fail silently
|
|
return;
|
|
}
|
|
|
|
// support wrapping multiple patterns
|
|
o.pattern = _.isArray(o.pattern) ? o.pattern : [o.pattern];
|
|
|
|
regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly);
|
|
traverse(o.node, hightlightTextNode);
|
|
|
|
function hightlightTextNode(textNode) {
|
|
var match, patternNode, wrapperNode;
|
|
|
|
if (match = regex.exec(textNode.data)) {
|
|
wrapperNode = doc.createElement(o.tagName);
|
|
o.className && (wrapperNode.className = o.className);
|
|
|
|
patternNode = textNode.splitText(match.index);
|
|
patternNode.splitText(match[0].length);
|
|
wrapperNode.appendChild(patternNode.cloneNode(true));
|
|
|
|
textNode.parentNode.replaceChild(wrapperNode, patternNode);
|
|
}
|
|
|
|
return !!match;
|
|
}
|
|
|
|
function traverse(el, hightlightTextNode) {
|
|
var childNode, TEXT_NODE_TYPE = 3;
|
|
|
|
for (var i = 0; i < el.childNodes.length; i++) {
|
|
childNode = el.childNodes[i];
|
|
|
|
if (childNode.nodeType === TEXT_NODE_TYPE) {
|
|
i += hightlightTextNode(childNode) ? 1 : 0;
|
|
}
|
|
|
|
else {
|
|
traverse(childNode, hightlightTextNode);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
function getRegex(patterns, caseSensitive, wordsOnly) {
|
|
var escapedPatterns = [], regexStr;
|
|
|
|
for (var i = 0, len = patterns.length; i < len; i++) {
|
|
escapedPatterns.push(_.escapeRegExChars(patterns[i]));
|
|
}
|
|
|
|
regexStr = wordsOnly ?
|
|
'\\b(' + escapedPatterns.join('|') + ')\\b' :
|
|
'(' + escapedPatterns.join('|') + ')';
|
|
|
|
return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, 'i');
|
|
}
|
|
})(window.document);
|