git ssb

0+

cel / text-node-searcher



Commit 4bf486abd8728a501408a60a50a61755cfa49ae3

Get it working

Charles Lehner committed on 12/18/2015, 7:21:33 PM
Parent: 79bc3a2162c5397f0fc094b0cde3038530cdfd28

Files changed

example.htmlchanged
index.jschanged
example.htmlView
@@ -1,13 +1,13 @@
11 <!doctype html>
22 <html>
33 <head>
4- <meta charset="utf-8">
4 + <meta charset="utf-8"/>
55 <title>demo</title>
66 </head>
77 <body>
88 <div>
9- <input size="80" id="search" type="search"/>
9 + <input size="80" id="search" type="search" value="eli"/>
1010 <input type="button" id="prev-btn" value="&larr;"/>
1111 <input type="button" id="next-btn" value="&rarr;"/>
1212 </div>
1313
@@ -30,31 +30,24 @@
3030 justo. Praesent auctor massa non varius rhoncus. Pellentesque augue
3131 elit, dictum in tortor eu, congue semper augue. Phasellus interdum
3232 malesuada lorem.</p>
3333
34- <script>
35- function toStr(obj) {
36- var str = '';
37- for (var key in obj) {
38- if (str) str += ', ';
39- str += key + ': ' + obj[key];
40- }
41- return '{' + str + '}';
42- }
43- window.addEventListener("error", function (e) {
44- log(e.message, e.filename, e.lineno + ":" + e.colno)
45- }, false);
46- // document.body.appendChild(document.createElement("blockquote"))
47- // .appendChild(document.createTextNode(e.toString()));
48- </script>
4934 <script src="index.js"></script>
5035 <script>
5136 var searcher = new Searcher(document.body);
52- searcher.setQuery("dolor");
53- document.getElementById("search").onkeypress = function () {
37 + var input = document.getElementById("search");
38 + searcher.setQuery(input.value);
39 + input.onkeyup = function () {
5440 searcher.setQuery(this.value);
55- // searcher.highlight();
5641 };
42 + input.onkeypress = function (e) {
43 + if (e.keyCode == 13) { // Enter
44 + if (e.shiftKey)
45 + searcher.selectPrev();
46 + else
47 + searcher.selectNext();
48 + }
49 + };
5750 document.getElementById("next-btn").onclick = function () {
5851 searcher.selectNext();
5952 };
6053 document.getElementById("prev-btn").onclick = function () {
index.jsView
@@ -25,129 +25,131 @@
2525 function Searcher(container) {
2626 this.container = container;
2727 }
2828
29-Searcher.prototype.highlight = function () {
30- // if (this.isHighlighted)
31-
32-};
33-
3429 Searcher.prototype.setQuery = function (str) {
3530 if (str == this.queryStr)
3631 return;
3732
3833 this.queryStr = str;
39- this.queryLen = str.length;
40- this.query = new RegExp(addAccents(str), "i");
34 + this.query = new RegExp(addAccents(str), "ig");
4135 };
4236
43-function log() {
44- var str;
45- try {
46- str = [].slice.call(arguments).join(", ");
47- } catch(e) {
48- str = e.message;
49- }
50- document.body.appendChild(document.createElement("pre"))
51- .appendChild(document.createTextNode(str));
37 +function shouldDescendInto(node) {
38 + return node.nodeName != "SCRIPT" && node.nodeName != "STYLE";
5239 }
53-window.log = log;
5440
5541 function getNextTextNode(node, container, wrap) {
56- do {
57- if (node.firstChild) {
58- console.log('firstchild');
42 + outer: do {
43 + if (shouldDescendInto(node) && node.firstChild) {
5944 node = node.firstChild;
6045 } else if (node.nextSibling) {
61- console.log('nextsib');
6246 node = node.nextSibling;
6347 } else {
6448 do {
65- if (node == container)
66- return wrap ? getFirstTextNode(container) : null;
67- console.log('parent');
49 + if (node == container) {
50 + if (!wrap)
51 + return null;
52 + wrap = false;
53 + continue outer;
54 + }
6855 node = node.parentNode;
6956 } while (!node.nextSibling);
70- console.log('next sib');
7157 node = node.nextSibling;
7258 }
7359 } while (node.nodeType != Node.TEXT_NODE);
7460 return node;
7561 }
7662
7763 function getPrevTextNode(node, container, wrap) {
7864 do {
79- if (node.previousSibling) {
80- console.log('previous sib');
65 + if (node == container) {
66 + if (!wrap)
67 + return null;
68 + while (shouldDescendInto(node) && node.lastChild)
69 + node = node.lastChild;
70 + wrap = false;
71 + } else if (node.previousSibling) {
8172 node = node.previousSibling;
82- while (node.lastChild)
73 + while (shouldDescendInto(node) && node.lastChild)
8374 node = node.lastChild;
84- } else if (node.parentNode != container) {
75 + } else {
8576 node = node.parentNode;
86- } else {
87- return wrap ? getLastTextNode(container) : null;
8877 }
8978 } while (node.nodeType != Node.TEXT_NODE);
9079 return node;
9180 }
9281
9382 function getFirstTextNode(container) {
94- return getNextTextNode(container, container);
83 + return getNextTextNode(container, container, false);
9584 }
9685
9786 function getLastTextNode(container) {
98- return getPrevTextNode(container, container);
87 + return getPrevTextNode(container, container, true);
9988 }
10089
90 +function matchLast(re, str) {
91 + var last;
92 + re.lastIndex = 0;
93 + for (var m = re.exec(str); m; m = re.exec(str))
94 + last = m;
95 + return last;
96 +}
97 +
10198 Searcher.prototype.selectNext = function () {
102- if (!this.queryLen)
99 + if (!this.queryStr)
103100 return;
104101
105102 var sel = window.getSelection();
106- var startNode = sel.focusNode || getFirstTextNode(this.container);
107- var startOffset = sel.focusOffset;
103 + var startNode = sel.focusNode;
104 + var startOffset = 0;
108105 if (!startNode)
109- return;
110- if (!startNode.data)
111- console.log('start', startNode);
106 + startNode = getFirstTextNode(this.container);
107 + else if (startNode.nodeType != Node.TEXT_NODE ||
108 + !this.container.contains(startNode))
109 + startNode = getNextTextNode(startNode, this.container, true);
110 + else
111 + startOffset = sel.focusOffset;
112112
113- for (var node = startNode, str = node.data.substr(startOffset);
114- node;
115- node = getNextTextNode(node, this.container, true),
116- str = node.data)
117- {
118- var m = str.match(this.query);
113 + for (var node = startNode; node;
114 + node = getNextTextNode(node, this.container, true)) {
115 + var str = node.data;
116 + this.query.lastIndex = startOffset;
117 + if (startOffset)
118 + startOffset = 0;
119 + var m = this.query.exec(str);
119120 if (m) {
120- var i = m.index;
121- console.log('next node', node, 'index', i);
122- setSelection(node, i, node, i + m[0].length);
121 + setSelection(node, m.index, node, m.index + m[0].length);
123122 return;
124123 }
125124 }
126125 };
127126
128127 Searcher.prototype.selectPrev = function () {
129- if (!this.queryLen)
128 + if (!this.queryStr)
130129 return;
131130
132131 var sel = window.getSelection();
133- var endNode = sel.anchorNode || getLastTextNode(this.container);
134- var endOffset = sel.anchorOffset;
132 + var endNode = sel.anchorNode;
133 + var endOffset = 0;
135134 if (!endNode)
136- return;
137- if (!endNode.data)
138- console.log('end', endNode);
135 + endNode = getLastTextNode(this.container);
136 + else if (endNode.nodeType != Node.TEXT_NODE ||
137 + !this.container.contains(endNode))
138 + endNode = getPrevTextNode(endNode, this.container, true);
139 + else
140 + endOffset = sel.anchorOffset;
139141
140- for (var node = endNode, str = endNode.data.substr(0, endOffset);
141- node;
142- node = getPrevTextNode(node, this.container, true),
143- str = node.data)
144- {
145- var m = str.match(this.query);
142 + for (var node = endNode; node;
143 + node = getPrevTextNode(node, this.container, true)) {
144 + var str = node.data;
145 + if (endOffset < Infinity) {
146 + str = node.data.substr(0, endOffset);
147 + endOffset = Infinity;
148 + }
149 + var m = matchLast(this.query, str);
146150 if (m) {
147- var i = m.index;
148- console.log('prev node', node, 'index', i);
149- setSelection(node, i, node, i + m[0].length);
151 + setSelection(node, m.index, node, m.index + m[0].length);
150152 return;
151153 }
152154 }
153155 };

Built with git-ssb-web