Skip to content

Commit 75a7d4a

Browse files
committed
use worker in code to avoid freezing
1 parent 60d10a0 commit 75a7d4a

File tree

8 files changed

+240
-154
lines changed

8 files changed

+240
-154
lines changed

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
public/
32
resources/
43
node_modules/
@@ -7,4 +6,5 @@ content/en/docs/latest/
76
content/static/latest/
87
content/static/**/*.dtmp
98
content/static/**/*.bkp
10-
content/static/**/*.crswap
9+
content/static/**/*.crswap
10+
assets/json/lunr-index.json

assets/js/generate-lunr-index.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const fs = require('fs');
2+
const lunr = require('lunr');
3+
4+
const data = JSON.parse(fs.readFileSync('docs/offline-search-index.json'));
5+
6+
const idx = lunr(function () {
7+
this.ref('ref');
8+
this.field('title', { boost: 5 });
9+
this.field('categories', { boost: 3 });
10+
this.field('tags', { boost: 3 });
11+
this.field('description', { boost: 2 });
12+
this.field('body');
13+
14+
data.forEach((doc) => {let docToAdd;
15+
if (doc
16+
&& doc.ref !== undefined
17+
&& !doc.ref.includes('/_shared/')
18+
) {
19+
this.add(doc);
20+
}
21+
});
22+
});
23+
24+
fs.writeFileSync('assets/json/lunr-index.json', JSON.stringify(idx));

assets/js/offline-search.js

Lines changed: 142 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -17,192 +17,185 @@
1717
'<div class="popover offline-search-result" role="tooltip"><div class="arrow"></div><h3 class="popover-header"></h3><div class="popover-body"></div></div>'
1818
);
1919

20-
//
21-
// Register handler
22-
//
23-
24-
$searchInput.on('change', (event) => {
25-
render($(event.target));
26-
27-
// Hide keyboard on mobile browser
28-
$searchInput.blur();
29-
});
30-
31-
// Prevent reloading page by enter key on sidebar search.
32-
$searchInput.closest('form').on('submit', () => {
33-
return false;
34-
});
35-
3620
//
3721
// Lunr
3822
//
3923

4024
let idx = null; // Lunr index
4125
const resultDetails = new Map(); // Will hold the data for the search results (titles and summaries)
26+
let worker = null;
4227

43-
// Set up for an Ajax call to request the JSON data file that is created by Hugo's build process
28+
29+
if (window.Worker) {
30+
worker = new Worker('/js/worker.js');
31+
const url = '/json/lunr-index.json';
32+
33+
worker.postMessage({ type: 'init', url: url });
34+
35+
worker.onerror = function (error) {
36+
console.error('Error in worker:', error);
37+
};
38+
}
39+
4440
$.ajax($searchInput.data('offline-search-index-json-src')).then(
4541
(data) => {
46-
idx = lunr(function () {
47-
this.ref('ref');
48-
49-
// If you added more searchable fields to the search index, list them here.
50-
// Here you can specify searchable fields to the search index - e.g. individual toxonomies for you project
51-
// With "boost" you can add weighting for specific (default weighting without boost: 1)
52-
this.field('title', { boost: 5 });
53-
this.field('categories', { boost: 3 });
54-
this.field('tags', { boost: 3 });
55-
this.field('description', { boost: 2 });
56-
this.field('body');
57-
58-
const searchPath = $searchInput.data('search-path');
59-
60-
data.forEach((doc) => {
61-
let docToAdd;
62-
if (searchPath !== undefined && doc.ref.startsWith(searchPath)) {
63-
docToAdd = doc;
64-
} else if (searchPath === undefined) {
65-
docToAdd = doc;
66-
}
67-
68-
if (docToAdd
69-
&& docToAdd.ref !== undefined
70-
&& !docToAdd.ref.includes('/_shared/')
71-
) {
72-
this.add(doc);
73-
74-
resultDetails.set(doc.ref, {
75-
title: doc.title,
76-
excerpt: doc.excerpt,
77-
});
78-
}
42+
data.forEach((doc) => {
43+
resultDetails.set(doc.ref, {
44+
version: doc.version,
45+
title: doc.title,
46+
excerpt: doc.excerpt,
7947
});
8048
});
81-
82-
$searchInput.trigger('change');
8349
}
8450
);
8551

52+
let currentTarget = null;
53+
54+
worker.onmessage = function (event) {
55+
if (event.data.type === 'search') {
56+
const results = event.data.results
57+
console.log('Search results:', results);
58+
const $html = $('<div>');
59+
60+
$html.append(
61+
$('<div>')
62+
.css({
63+
display: 'flex',
64+
justifyContent: 'space-between',
65+
marginBottom: '1em',
66+
})
67+
.append(
68+
$('<span>')
69+
.text('Search results')
70+
.css({ fontWeight: 'bold' })
71+
)
72+
.append(
73+
$('<i>')
74+
.addClass('fas fa-times search-result-close-button')
75+
.css({
76+
cursor: 'pointer',
77+
})
78+
)
79+
);
80+
81+
const $searchResultBody = $('<div>').css({
82+
maxHeight: `calc(100vh - ${currentTarget.offset().top -
83+
$(window).scrollTop() +
84+
180
85+
}px)`,
86+
overflowY: 'auto',
87+
});
88+
$html.append($searchResultBody);
89+
90+
if (results.length === 0) {
91+
currentTarget.append(
92+
$('<p>').text(`No results found for query "${searchQuery}"`)
93+
);
94+
} else {
95+
results.forEach((r) => {
96+
const doc = resultDetails.get(r.ref);
97+
98+
const href =
99+
$searchInput.data('offline-search-base-href') +
100+
r.ref.replace(/^\//, '');
101+
102+
const $entry = $('<div>').addClass('mt-4').addClass('search-result');
103+
104+
$entry.append(
105+
$('<a>')
106+
.addClass('d-block')
107+
.css({
108+
fontSize: '1.2rem',
109+
})
110+
.attr('href', href)
111+
.text(doc.title)
112+
);
113+
114+
$entry.append(
115+
$('<small>').addClass('d-block text-muted').text(r.ref)
116+
);
117+
118+
$entry.append($('<p>').text(doc.excerpt));
119+
120+
$searchResultBody.append($entry);
121+
});
122+
}
123+
124+
currentTarget.on('shown.bs.popover', () => {
125+
$('.search-result-close-button').on('click', () => {
126+
currentTarget.val('');
127+
currentTarget.trigger('change');
128+
});
129+
});
130+
131+
currentTarget
132+
.data('content', $html[0].outerHTML)
133+
.popover('show');
134+
}
135+
}
136+
86137
const render = ($targetSearchInput) => {
87138
// Dispose the previous result
88139
$targetSearchInput.popover('dispose');
140+
currentTarget = $targetSearchInput;
89141

90142
//
91143
// Search
92144
//
93145

94-
if (idx === null) {
95-
return;
96-
}
97146

98147
const searchQuery = $targetSearchInput.val();
99148
if (searchQuery === '') {
100149
return;
101150
}
102151

103-
const results = idx
104-
.query((q) => {
105-
const tokens = lunr.tokenizer(searchQuery.toLowerCase());
106-
tokens.forEach((token) => {
107-
const queryString = token.toString();
108-
q.term(queryString, {
109-
boost: 100,
110-
});
111-
q.term(queryString, {
112-
wildcard:
113-
lunr.Query.wildcard.LEADING |
114-
lunr.Query.wildcard.TRAILING,
115-
boost: 10,
116-
});
117-
q.term(queryString, {
118-
editDistance: 2,
119-
});
120-
});
121-
})
122-
.slice(
123-
0,
124-
$targetSearchInput.data('offline-search-max-results')
125-
);
152+
worker.postMessage({ type: 'search', query: searchQuery, maxResults: $targetSearchInput.data('offline-search-max-results') });
153+
154+
// const results = idx
155+
// .query((q) => {
156+
// const tokens = lunr.tokenizer(searchQuery.toLowerCase());
157+
// tokens.forEach((token) => {
158+
// const queryString = token.toString();
159+
// q.term(queryString, {
160+
// boost: 100,
161+
// });
162+
// q.term(queryString, {
163+
// wildcard:
164+
// lunr.Query.wildcard.LEADING |
165+
// lunr.Query.wildcard.TRAILING,
166+
// boost: 10,
167+
// });
168+
// q.term(queryString, {
169+
// editDistance: 2,
170+
// });
171+
// });
172+
// })
173+
// .slice(
174+
// 0,
175+
// $targetSearchInput.data('offline-search-max-results')
176+
// );
126177

127178
//
128179
// Make result html
129180
//
130181

131-
const $html = $('<div>');
132-
133-
$html.append(
134-
$('<div>')
135-
.css({
136-
display: 'flex',
137-
justifyContent: 'space-between',
138-
marginBottom: '1em',
139-
})
140-
.append(
141-
$('<span>')
142-
.text('Search results')
143-
.css({ fontWeight: 'bold' })
144-
)
145-
.append(
146-
$('<i>')
147-
.addClass('fas fa-times search-result-close-button')
148-
.css({
149-
cursor: 'pointer',
150-
})
151-
)
152-
);
153-
154-
const $searchResultBody = $('<div>').css({
155-
maxHeight: `calc(100vh - ${$targetSearchInput.offset().top -
156-
$(window).scrollTop() +
157-
180
158-
}px)`,
159-
overflowY: 'auto',
160-
});
161-
$html.append($searchResultBody);
162-
163-
if (results.length === 0) {
164-
$searchResultBody.append(
165-
$('<p>').text(`No results found for query "${searchQuery}"`)
166-
);
167-
} else {
168-
results.forEach((r) => {
169-
const doc = resultDetails.get(r.ref);
170-
const href =
171-
$searchInput.data('offline-search-base-href') +
172-
r.ref.replace(/^\//, '');
173-
174-
const $entry = $('<div>').addClass('mt-4').addClass('search-result');
175-
176-
$entry.append(
177-
$('<a>')
178-
.addClass('d-block')
179-
.css({
180-
fontSize: '1.2rem',
181-
})
182-
.attr('href', href)
183-
.text(doc.title)
184-
);
185182

186-
$entry.append(
187-
$('<small>').addClass('d-block text-muted').text(r.ref)
188-
);
183+
};
189184

190-
$entry.append($('<p>').text(doc.excerpt));
185+
//
186+
// Register handler
187+
//
191188

192-
$searchResultBody.append($entry);
193-
});
194-
}
189+
$searchInput.on('change', (event) => {
190+
render($(event.target));
195191

196-
$targetSearchInput.on('shown.bs.popover', () => {
197-
$('.search-result-close-button').on('click', () => {
198-
$targetSearchInput.val('');
199-
$targetSearchInput.trigger('change');
200-
});
201-
});
192+
// Hide keyboard on mobile browser
193+
$searchInput.blur();
194+
});
202195

203-
$targetSearchInput
204-
.data('content', $html[0].outerHTML)
205-
.popover('show');
206-
};
196+
// Prevent reloading page by enter key on sidebar search.
197+
$searchInput.closest('form').on('submit', () => {
198+
return false;
199+
});
207200
});
208201
})(jQuery);

0 commit comments

Comments
 (0)