aboutsummaryrefslogtreecommitdiff
path: root/assets_src/js/lib
diff options
context:
space:
mode:
Diffstat (limited to 'assets_src/js/lib')
-rw-r--r--assets_src/js/lib/ajax.js60
-rw-r--r--assets_src/js/lib/dom.js14
-rw-r--r--assets_src/js/lib/search.js77
3 files changed, 118 insertions, 33 deletions
diff --git a/assets_src/js/lib/ajax.js b/assets_src/js/lib/ajax.js
new file mode 100644
index 0000000..048f516
--- /dev/null
+++ b/assets_src/js/lib/ajax.js
@@ -0,0 +1,60 @@
1export class AjaxError extends Error {
2 constructor(status, statusText) {
3 let message = `${status}: ${statusText}`
4 super(message);
5 this.name = this.constructor.name;
6 this.message = message;
7 this.status = status;
8 this.statusText = statusText;
9 Error.captureStackTrace(this, this.constructor.name)
10 }
11}
12
13function applyOptions(xhr, options) {
14 options.headers = options.headers || [];
15 for (let header in options.headers) {
16 xhr.setRequestHeader(header, options.headers[header]);
17 }
18}
19
20function createHandler(xhr, success, fail) {
21 return () => {
22 if (xhr.readyState !== XMLHttpRequest.DONE) {
23 return;
24 }
25 if (xhr.status === 200) {
26 success(xhr.response);
27 } else {
28 fail(xhr.status, xhr.statusText);
29 }
30 };
31}
32
33function request(method, url, body, options) {
34 options = options || {};
35 return new Promise((resolve, reject) => {
36 let xhr = new XMLHttpRequest();
37 xhr.onreadystatechange = createHandler(
38 xhr,
39 (res) => {
40 resolve(res);
41 },
42 (status, statusText) => {
43 reject(new AjaxError(status, statusText));
44 });
45 xhr.open(method, url, true);
46 applyOptions(xhr, options);
47 xhr.onerror = function() {
48 reject(new AjaxError(-1, 'Network error'));
49 };
50 xhr.send(body);
51 });
52}
53
54export async function get(url, options) {
55 return request('GET', url, null, options);
56}
57
58export async function post(url, body, options) {
59 return request('POST', url, body, options);
60}
diff --git a/assets_src/js/lib/dom.js b/assets_src/js/lib/dom.js
new file mode 100644
index 0000000..33845af
--- /dev/null
+++ b/assets_src/js/lib/dom.js
@@ -0,0 +1,14 @@
1export function ready(fn) {
2 document.addEventListener('DOMContentLoaded', (e) => {
3 fn();
4 }, false);
5}
6
7export function closest(el, fn) {
8 while (el) {
9 if (fn(el)) {
10 return el;
11 }
12 el = el.parentNode
13 }
14}
diff --git a/assets_src/js/lib/search.js b/assets_src/js/lib/search.js
index 0cb33df..85559ef 100644
--- a/assets_src/js/lib/search.js
+++ b/assets_src/js/lib/search.js
@@ -1,40 +1,51 @@
1var strokeTimeout = null; 1import * as dom from './dom';
2import * as ajax from './ajax';
2 3
3function instantSearch() { 4export class InstantSearch {
4 if (strokeTimeout) { 5 constructor(element, resultsElem) {
5 clearTimeout(strokeTimeout); 6 this.resultClicked = () => {};
6 } 7 this.element = element;
7 strokeTimeout = setTimeout(doSearch, 150); 8 this.resultsElem = resultsElem;
8} 9 this.strokeTimeout = null;
9 10 element.addEventListener('keydown', e => {
10function doSearch() { 11 if (this.strokeTimeout) {
11 value = document.getElementById("search").value; 12 clearTimeout(this.strokeTimeout);
12
13 if (value === "") {
14 strokeTimeout = null;
15 document.getElementById("search-results").innerHTML = "";
16 return;
17 }
18 var xhr = new XMLHttpRequest();
19 xhr.onreadystatechange = function() {
20 if (xhr.readyState == XMLHttpRequest.DONE) {
21 if (xhr.status === 404 || xhr.status === 400 || typeof xhr.response === 'undefined' || xhr.response === '404 not found') {
22 document.getElementById("search-results").innerHTML = '';
23 return
24 } 13 }
25 if (value === "") { 14 this.strokeTimeout = setTimeout(() => this.doSearch(), 150);
26 document.getElementById("search-results").innerHTML = ""; 15 }, false);
27 return; 16 resultsElem.addEventListener('click', e => {
17 let li = dom.closest(e.target, el => el.tagName.match(/li/i));
18 if (!li) {
19 return true;
28 } 20 }
21 this.resultsElem.innerHTML = '';
22 this.resultClicked(li.getAttribute('data-id'));
23 }, true);
24 }
29 25
30 document.getElementById("search-results").innerHTML = xhr.response.replace(new RegExp('{ (.*?)(' + value + ')(.*?) }', 'gi'), "$1<b>$2</b>$3").replace(new RegExp('{ (.*?) }', 'gi'), '$1'); 26 async doSearch() {
27 let value = this.element.value;
28 if (value.length < 2) {
29 this.strokeTimeout = null;
30 this.resultsElem.innerHTML = "";
31 return;
32 }
33 let response = null;
34 try {
35 response = await ajax.get(`/search/gril_instant/${value}`);
36 } catch (e) {
37 this.resultsElem.innerHTML = '';
38 return;
31 } 39 }
40 this.resultsElem.innerHTML = response
41 .replace(
42 new RegExp('{ (.*?)(' +
43 value +
44 ')(.*?) }', 'gi'),
45 "$1<b>$2</b>$3")
46 .replace(
47 new RegExp('{ (.*?) }', 'gi'),
48 '$1');
49 this.strokeTimeout = null;
32 } 50 }
33 xhr.open('GET', '/search/gril_instant/' + value, true);
34 xhr.send(null);
35 strokeTimeout = null;
36} 51}
37
38function clickSearchResult(resId) {
39
40} \ No newline at end of file