• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* lws-fts.js - JS supporting lws fulltext search
2 *
3 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24
25(function() {
26
27	var last_ac = "";
28
29	function san(s)
30	{
31		s.replace(/</g, "!");
32		s.replace(/%/g, "!");
33
34		return s;
35	}
36
37	function lws_fts_choose()
38	{
39		var xhr = new XMLHttpRequest();
40		var sr = document.getElementById("searchresults");
41		var ac = document.getElementById("acomplete");
42		var inp = document.getElementById("lws_fts");
43
44		xhr.onopen = function(e) {
45			xhr.setRequestHeader("cache-control", "max-age=0");
46		};
47
48		xhr.onload = function(e) {
49			var jj, n, m, s = "", lic = 0;
50			var sr = document.getElementById("searchresults");
51			var inp = document.getElementById("lws_fts");
52			sr.style.width = (parseInt(sr.parentNode.offsetWidth, 10) - 88) + "px";
53			sr.style.opacity = "1";
54			inp.blur();
55
56			// console.log(xhr.responseText);
57			jj = JSON.parse(xhr.responseText);
58
59			if (jj.fp) {
60				lic = jj.fp.length;
61				for (n = 0; n < lic; n++) {
62
63					s += "<div class='filepath'>" + jj.fp[n].path + "</div>";
64
65					s += "<table>";
66					for (m = 0; m < jj.fp[n].hits.length; m++)
67						s += "<tr><td class='r'>" + jj.fp[n].hits[m].l +
68							 "</td><td>" + jj.fp[n].hits[m].s +
69							 "</td></tr>";
70
71					s += "</table>";
72
73				}
74			}
75
76			sr.innerHTML = s;
77		};
78
79		inp.blur();
80		ac.style.opacity = "0";
81		sr.style.innerHTML = "";
82		xhr.open("GET", "../fts/r/" + document.getElementById("lws_fts").value);
83		xhr.send();
84	}
85
86	function lws_fts_ac_select(e)
87	{
88		var t = e.target;
89
90		while (t) {
91			if (t.getAttribute && t.getAttribute("string")) {
92				document.getElementById("lws_fts").value =
93						t.getAttribute("string");
94
95				lws_fts_choose();
96			}
97
98			t = t.parentNode;
99		}
100	}
101
102	function lws_fts_search_input()
103	{
104		var ac = document.getElementById("acomplete"),
105		    sb = document.getElementById("lws_fts");
106
107		if (last_ac === sb.value)
108			return;
109
110		last_ac = sb.value;
111
112		ac.style.width = (parseInt(sb.offsetWidth, 10) - 2) + "px";
113		ac.style.opacity = "1";
114
115		/* detect loss of focus for popup menu */
116		sb.addEventListener("focusout", function(e) {
117				ac.style.opacity = "0";
118		});
119
120
121		var xhr = new XMLHttpRequest();
122
123		xhr.onopen = function(e) {
124			xhr.setRequestHeader("cache-control", "max-age=0");
125		};
126		xhr.onload = function(e) {
127			var jj, n, s = "", lic = 0;
128			var inp = document.getElementById("lws_fts");
129			var ac = document.getElementById("acomplete");
130
131			// console.log(xhr.responseText);
132			jj = JSON.parse(xhr.responseText);
133
134			switch(parseInt(jj.indexed, 10)) {
135			case 0: /* there is no index */
136				break;
137
138			case 1: /* yay there is an index */
139
140					if (jj.ac) {
141						lic = jj.ac.length;
142						s += "<ul id='menu-ul'>";
143						for (n = 0; n < lic; n++) {
144
145							if (jj.ac[n] && parseInt(jj.ac[n].matches, 10))
146								s += "<li id='mi_ac" + n + "' string='" +
147									san(jj.ac[n].ac) +
148									"'><table><tr><td>" + san(jj.ac[n].ac) +
149									"</td><td class='r'>" +
150									parseInt(jj.ac[n].matches, 10) +
151									"</td></tr></table></li>";
152						}
153
154						s += "</ul>";
155
156					 if (!lic) {
157						//s = "<img class='noentry'>";
158						inp.className = "nonviable";
159						ac.style.opacity = "0";
160					 } else {
161						 inp.className = "viable";
162						 ac.style.opacity = "1";
163					 }
164					}
165
166				break;
167
168			default:
169
170				/* an index is being built... */
171
172				s = "<table><tr><td><img class='spinner'></td><td>" +
173					"<table><tr><td>Indexing</td></tr><tr><td>" +
174					"<div id='bar1' class='bar1'>" +
175					"<div id='bar2' class='bar2'>" +
176					jj.index_done + "&nbsp;/&nbsp;" + jj.index_files +
177					"</div></div></td></tr></table>" +
178					"</td></tr></table>";
179
180				setTimeout(lws_fts_search_input, 300);
181
182				break;
183			}
184
185			ac.innerHTML = s;
186
187			for (n = 0; n < lic; n++)
188				if (document.getElementById("mi_ac" + n))
189					document.getElementById("mi_ac" + n).
190						addEventListener("click", lws_fts_ac_select);
191			if (jj.index_files) {
192				document.getElementById("bar2").style.width =
193					((150 * jj.index_done) / (jj.index_files + 1)) + "px";
194			}
195		};
196
197		xhr.open("GET", "../fts/a/" + document.getElementById("lws_fts").value);
198		xhr.send();
199	}
200
201	document.addEventListener("DOMContentLoaded", function() {
202		var inp = document.getElementById("lws_fts");
203
204		inp.addEventListener("input", lws_fts_search_input, false);
205
206		inp.addEventListener("keydown",
207				function(e) {
208			var inp = document.getElementById("lws_fts");
209			var sr = document.getElementById("searchresults");
210			var ac = document.getElementById("acomplete");
211			if (e.key === "Enter" && inp.className === "viable") {
212				lws_fts_choose();
213				sr.focus();
214				ac.style.opacity = "0";
215			}
216		}, false);
217
218	}, false);
219
220}());
221