Skip to content

Instantly share code, notes, and snippets.

@nfeldman
Last active August 29, 2015 14:01
Show Gist options
  • Save nfeldman/0fad944e56986af9428b to your computer and use it in GitHub Desktop.
Save nfeldman/0fad944e56986af9428b to your computer and use it in GitHub Desktop.
starting point for regexp based page search
// this is just the starting point. you can run it in the console.
// there are numerous problems to solve, like working out whether
// the text it finds is visible or not -- i.e. if a node has display: none,
// or is absolutely positioned offscreen or behind another element, or
// has visiblity: hidden, or has height: 0 and overflow: hidden, and so on.
function find (str, caseSensitive) {
var head = (document.head || document.getElementsByTagName('head')[0]),
body = (document.body || document.getElementsByTagName('body')[0]),
re = RegExp(str, 'g' + (caseSensitive ? '' : 'i')),
nodes = [],
matches = [],
iterator = document.evaluate('//text()', body, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null),
node, highlights, nav, style, current, total, navCount, siv;
while (node = iterator.iterateNext())
nodes.push(node);
nodes.filter(function (t) {
if (t.parentNode.nodeType != 1)
return false;
var parentName = t.parentNode.nodeName.toLowerCase();
return parentName != 'script' && parentName != 'style' && re.test(t.nodeValue);
}).map(function (t) {
var parent = t.parentNode,
frags = [],
idx = 0,
text, m, len, div, frag, next;
text = t.nodeValue;
while (m = re.exec(text)) {
len = m[0].length;
if (idx != m.index)
frags.push(text.slice(idx, m.index));
frags.push('<span class="nsf_highlight" tabindex="-1">' + text.slice(m.index, m.index + len) + '</span>');
idx = m.index + len;
}
frags.push(text.slice(idx));
div = document.createElement('div');
div.innerHTML = frags.join('');
frag = document.createDocumentFragment();
while (div.firstChild)
frag.appendChild(div.firstChild);
return [parent, frag, t];
}).forEach(function (x) {
var parent = x.shift();
parent.replaceChild.apply(parent, x);
matches.push.apply(matches, [].slice.apply(parent.getElementsByClassName('nsf_highlight')));
});
highlights = [];
for (var i = 0, l = matches.length; i < l; i++) {
if (matches[i].id) {
console.warn('highlight already in collection');
continue;
}
matches[i].id = 'nsf_highlight-' + i;
highlights.push(matches[i]);
}
total = highlights.length;
if (!total)
return;
current = -1;
nav = document.createElement('div');
nav.innerHTML = '<a href="#">&laquo;</a> <span>-1</span> of <span>' + total + '</span> <a href="#">&raquo;</a>';
nav.className = 'nsf_highlight-nav';
navCount = nav.querySelector('span');
style = document.createElement('style');
style.innerHTML = '.nsf_highlight {background: #FFA} .nsf_active {background: orange}' +
'.nsf_highlight-nav {font-size: 16px; background: #DDD; position: fixed; top: 0; right: 0; z-index: 100; padding: 15px}';
siv = typeof body.firstElementChild.scrollIntoViewIfNeeded != 'undefined' ? 'scrollIntoViewIfNeeded' : 'scrollIntoView';
function move (back) {
if (~current)
highlights[current].className = 'nsf_highlight';
back ? prev() : next();
navCount.innerHTML = current + 1;
highlights[current].className = 'nsf_highlight nsf_active';
highlights[current][siv]();
highlights[current].focus();
}
function prev () {
--current;
if (!~current)
current = total - 1;
}
function next () {
++current;
if (current >= total)
current = 0;
}
function keyHandler (e) {
if (e.which == 27) {
head.removeChild(style);
document.removeEventListener('keydown', keyHandler);
nav.removeEventListener('click', clickHandler);
for (var i = 0; i < total; i++)
highlights[i].parentNode.replaceChild(highlights[i].firstChild, highlights[i]);
} else if (e.which == 78 && e.shiftKey || e.which == 37) {
move(true);
} else if (e.which == 78 || e.which == 39) {
move(false);
}
}
function clickHandler (e) {
if (e.target != nav.firstChild && e.target != nav.lastChild)
return;
e.preventDefault();
move(e.target == nav.firstChild);
}
document.addEventListener('keydown', keyHandler);
nav.addEventListener('click', clickHandler);
head.appendChild(style);
move(false);
body.appendChild(nav);
}
@nfeldman
Copy link
Author

you can test it with something like

find('(?:is)|(?:if)')

to find all instances of is or if, case insensitive.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment