Skip to content

Commit a348175

Browse files
author
Roger Shen
authored
Revert "Support matches that cross element boundaries"
1 parent a526611 commit a348175

File tree

4 files changed

+62
-713
lines changed

4 files changed

+62
-713
lines changed

src/js/content.js

Lines changed: 60 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ var ELEMENT_NODE_TYPE = 1;
33
var TEXT_NODE_TYPE = 3;
44
var UNEXPANDABLE = /(script|style|svg|audio|canvas|figure|video|select|input|textarea)/i;
55
var HIGHLIGHT_TAG = 'highlight-tag';
6-
var HIGHLIGHT_CLASS = 'chrome-regex-search-highlighted';
7-
var SELECTED_CLASS = 'chrome-regex-search-selected';
6+
var HIGHLIGHT_CLASS = 'highlighted';
7+
var SELECTED_CLASS = 'selected';
88
var DEFAULT_MAX_RESULTS = 500;
99
var DEFAULT_HIGHLIGHT_COLOR = '#ffff00';
1010
var DEFAULT_SELECTED_COLOR = '#ff9900';
@@ -14,7 +14,6 @@ var DEFAULT_CASE_INSENSITIVE = false;
1414

1515
/*** VARIABLES ***/
1616
var searchInfo;
17-
var finder;
1817
/*** VARIABLES ***/
1918

2019
/*** LIBRARY FUNCTIONS ***/
@@ -35,7 +34,7 @@ function initSearchInfo(pattern) {
3534
searchInfo = {
3635
regexString : pattern,
3736
selectedIndex : 0,
38-
highlights : [],
37+
highlightedNodes : [],
3938
length : 0
4039
}
4140
}
@@ -51,30 +50,58 @@ function returnSearchInfo(cause) {
5150
});
5251
}
5352

53+
/* Check if the given node is a text node */
54+
function isTextNode(node) {
55+
return node && node.nodeType === TEXT_NODE_TYPE;
56+
}
57+
58+
/* Check if the given node is an expandable node that will yield text nodes */
59+
function isExpandable(node) {
60+
return node && node.nodeType === ELEMENT_NODE_TYPE && node.childNodes &&
61+
!UNEXPANDABLE.test(node.tagName) && node.visible();
62+
}
63+
5464
/* Highlight all text that matches regex */
5565
function highlight(regex, highlightColor, selectedColor, textColor, maxResults) {
56-
finder = findAndReplaceDOMText(
57-
document.body,
58-
{
59-
find: regex,
60-
wrap: "span",
61-
wrapClass: HIGHLIGHT_CLASS,
62-
filterElements: function(element) {
63-
/* Check if the element is visible */
64-
/* https://stackoverflow.com/a/21696585 */
65-
return element.offsetParent !== null || element === document.body;
66-
},
67-
preset: "prose"
66+
function highlightRecursive(node) {
67+
if(searchInfo.length >= maxResults){
68+
return;
6869
}
69-
)
70-
searchInfo.highlights = finder.elements;
71-
searchInfo.length = finder.elements.length;
70+
if (isTextNode(node)) {
71+
var index = node.data.search(regex);
72+
if (index >= 0 && node.data.length > 0) {
73+
var matchedText = node.data.match(regex)[0];
74+
var matchedTextNode = node.splitText(index);
75+
matchedTextNode.splitText(matchedText.length);
76+
var spanNode = document.createElement(HIGHLIGHT_TAG);
77+
spanNode.className = HIGHLIGHT_CLASS;
78+
spanNode.style.backgroundColor = highlightColor;
79+
spanNode.style.color = textColor;
80+
spanNode.appendChild(matchedTextNode.cloneNode(true));
81+
matchedTextNode.parentNode.replaceChild(spanNode, matchedTextNode);
82+
searchInfo.highlightedNodes.push(spanNode);
83+
searchInfo.length += 1;
84+
return 1;
85+
}
86+
} else if (isExpandable(node)) {
87+
var children = node.childNodes;
88+
for (var i = 0; i < children.length; ++i) {
89+
var child = children[i];
90+
i += highlightRecursive(child);
91+
}
92+
}
93+
return 0;
94+
}
95+
highlightRecursive(document.getElementsByTagName('body')[0]);
7296
};
7397

7498
/* Remove all highlights from page */
7599
function removeHighlight() {
76-
if (finder) {
77-
finder.revert();
100+
while (node = document.body.querySelector(HIGHLIGHT_TAG + '.' + HIGHLIGHT_CLASS)) {
101+
node.outerHTML = node.innerHTML;
102+
}
103+
while (node = document.body.querySelector(HIGHLIGHT_TAG + '.' + SELECTED_CLASS)) {
104+
node.outerHTML = node.innerHTML;
78105
}
79106
};
80107

@@ -85,41 +112,22 @@ function scrollToElement(element) {
85112
window.scrollTo( 0, Math.max(top, window.pageYOffset - (window.innerHeight/2))) ;
86113
}
87114

88-
/* Select first regex match after selection on page */
115+
/* Select first regex match on page */
89116
function selectFirstNode(selectedColor) {
90-
if (searchInfo.highlights.length === 0) {
91-
return;
92-
}
93-
94-
function selectIndex(index) {
95-
searchInfo.selectedIndex = index;
96-
searchInfo.highlights[index].forEach((e) => { e.className = SELECTED_CLASS; });
97-
scrollToElement(searchInfo.highlights[index][0]);
98-
}
99-
100-
if (getSelection().anchorNode) {
101-
function path(e) {
102-
return e.parentNode === null ? [] : path(e.parentNode).concat([Array.prototype.indexOf.call(e.parentNode.childNodes, e)]);
103-
}
104-
105-
var selection = path(getSelection().anchorNode)
106-
var index = searchInfo.highlights.findIndex((h) => path(h[0]) > selection);
107-
if (index !== -1) {
108-
selectIndex(index);
109-
return;
110-
}
117+
var length = searchInfo.length;
118+
if(length > 0) {
119+
searchInfo.highlightedNodes[0].className = SELECTED_CLASS;
120+
searchInfo.highlightedNodes[0].style.backgroundColor = selectedColor;
121+
scrollToElement(searchInfo.highlightedNodes[0]);
111122
}
112-
113-
selectIndex(0);
114123
}
115124

116125
/* Helper for selecting a regex matched element */
117126
function selectNode(highlightedColor, selectedColor, getNext) {
118127
var length = searchInfo.length;
119128
if(length > 0) {
120-
searchInfo.highlights[searchInfo.selectedIndex].forEach(function(n) {
121-
n.className = HIGHLIGHT_CLASS;
122-
});
129+
searchInfo.highlightedNodes[searchInfo.selectedIndex].className = HIGHLIGHT_CLASS;
130+
searchInfo.highlightedNodes[searchInfo.selectedIndex].style.backgroundColor = highlightedColor;
123131
if(getNext) {
124132
if(searchInfo.selectedIndex === length - 1) {
125133
searchInfo.selectedIndex = 0;
@@ -133,11 +141,10 @@ function selectNode(highlightedColor, selectedColor, getNext) {
133141
searchInfo.selectedIndex -= 1;
134142
}
135143
}
136-
searchInfo.highlights[searchInfo.selectedIndex].forEach(function(n) {
137-
n.className = SELECTED_CLASS;
138-
});
144+
searchInfo.highlightedNodes[searchInfo.selectedIndex].className = SELECTED_CLASS;
145+
searchInfo.highlightedNodes[searchInfo.selectedIndex].style.backgroundColor = selectedColor;
139146
returnSearchInfo('selectNode');
140-
scrollToElement(searchInfo.highlights[searchInfo.selectedIndex][0]);
147+
scrollToElement(searchInfo.highlightedNodes[searchInfo.selectedIndex]);
141148
}
142149
}
143150
/* Forward cycle through regex matched elements */
@@ -174,7 +181,7 @@ function search(regexString, configurationChanged) {
174181
function(result) {
175182
initSearchInfo(regexString);
176183
if(result.caseInsensitive){
177-
regex = new RegExp(regexString, 'gi');
184+
regex = new RegExp(regexString, 'i');
178185
}
179186
highlight(regex, result.highlightColor, result.selectedColor, result.textColor, result.maxResults);
180187
selectFirstNode(result.selectedColor);
@@ -245,17 +252,4 @@ chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
245252

246253
/*** INIT ***/
247254
initSearchInfo();
248-
249-
chrome.storage.local.get({
250-
'highlightColor' : DEFAULT_HIGHLIGHT_COLOR,
251-
'selectedColor' : DEFAULT_SELECTED_COLOR,
252-
'textColor' : DEFAULT_TEXT_COLOR,
253-
}, function(result) {
254-
var css = document.createElement("style");
255-
css.type = "text/css";
256-
css.innerHTML =
257-
"." + HIGHLIGHT_CLASS + " { background: " + result.highlightColor + "; color: " + result.textColor + " }\n" +
258-
"." + SELECTED_CLASS + " { background: " + result.selectedColor + "; color: " + result.textColor + " }";
259-
document.body.appendChild(css);
260-
});
261255
/*** INIT ***/

0 commit comments

Comments
 (0)