o2c-opendoc-theme 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +2 -0
- data/_includes/directory.html +127 -0
- data/_includes/document-title.txt +57 -0
- data/_includes/toc.html +127 -0
- data/_includes/toolbar.html +68 -0
- data/_includes/welcome.html +5 -0
- data/_layouts/default.html +147 -0
- data/_layouts/home.html +4 -0
- data/_layouts/iframe.html +13 -0
- data/_layouts/page.html +4 -0
- data/_layouts/print.html +27 -0
- data/_sass/_base.scss +398 -0
- data/_sass/_constants.scss +87 -0
- data/_sass/_iframe.scss +7 -0
- data/_sass/_layout.scss +419 -0
- data/_sass/_nav.scss +592 -0
- data/_sass/_print.scss +70 -0
- data/_sass/_syntax-highlighting.scss +61 -0
- data/_sass/_toolbar.scss +372 -0
- data/_sass/_welcome.scss +41 -0
- data/assets/export.md +30 -0
- data/assets/images/chevron-up-white.svg +1 -0
- data/assets/images/chevron-up.svg +1 -0
- data/assets/images/close.svg +17 -0
- data/assets/images/favicon.ico +0 -0
- data/assets/images/feedback-hover.svg +3 -0
- data/assets/images/feedback-mobile.svg +1 -0
- data/assets/images/feedback.svg +1 -0
- data/assets/images/github-hover.svg +3 -0
- data/assets/images/github.svg +1 -0
- data/assets/images/home.svg +14 -0
- data/assets/images/index-img.png +0 -0
- data/assets/images/logo-order2cash.svg +65 -0
- data/assets/images/logo.png +0 -0
- data/assets/images/menu.svg +1 -0
- data/assets/images/opendoc-logo-full.svg +10 -0
- data/assets/images/pdf-hover.svg +11 -0
- data/assets/images/pdf.svg +9 -0
- data/assets/images/search-icon-dark.svg +19 -0
- data/assets/images/search-icon-white.svg +12 -0
- data/assets/images/share.svg +1 -0
- data/assets/images/sidebar-hover.svg +3 -0
- data/assets/images/sidebar.svg +1 -0
- data/assets/images/vertical-dots.svg +1 -0
- data/assets/images/x-mobile.svg +1 -0
- data/assets/index.html +5 -0
- data/assets/js/banner.js +20 -0
- data/assets/js/google_analytics.js +11 -0
- data/assets/js/header.js +31 -0
- data/assets/js/helpers.js +24 -0
- data/assets/js/lunr.min.js +6 -0
- data/assets/js/navigation.js +214 -0
- data/assets/js/page-index.js +57 -0
- data/assets/js/pqueue.js +373 -0
- data/assets/js/pre-loader.js +43 -0
- data/assets/js/search.js +580 -0
- data/assets/js/toolbar.js +144 -0
- data/assets/pdfs/empty +0 -0
- data/assets/siteIndex.json +56 -0
- data/assets/startup/build.sh +41 -0
- data/assets/startup/docprint.html +20 -0
- data/assets/startup/pdf-gen.js +397 -0
- data/assets/startup/prebuild-lunr-index.js +52 -0
- data/assets/styles/main.scss +13 -0
- data/assets/styles/normalize.css +427 -0
- data/assets/vendor/babel-polyfill.min.js +3 -0
- data/assets/vendor/dom4.js +2 -0
- data/assets/vendor/fetch.umd.js +531 -0
- data/assets/vendor/headroom.min.js +7 -0
- data/assets/vendor/jump.min.js +2 -0
- data/assets/vendor/mark.min.js +7 -0
- data/assets/vendor/popper.min.js +5 -0
- data/assets/vendor/web-share-shim.bundle.min.js +2 -0
- metadata +159 -0
data/assets/js/search.js
ADDED
@@ -0,0 +1,580 @@
|
|
1
|
+
---
|
2
|
+
---
|
3
|
+
(function () {
|
4
|
+
// Search Box Element
|
5
|
+
// =============================================================================
|
6
|
+
var siteSearchElement = document.getElementsByClassName('search-box')[0]
|
7
|
+
var searchBoxElement = document.getElementById('search-box')
|
8
|
+
var clearButton = document.getElementsByClassName('clear-button')[0]
|
9
|
+
var main = document.getElementsByTagName('main')[0]
|
10
|
+
var searchFilter = document.getElementsByClassName('search-filter')[0]
|
11
|
+
var searchResults = document.getElementsByClassName('search-results')[0]
|
12
|
+
|
13
|
+
searchBoxElement.oninput = function (event) {
|
14
|
+
if (searchBoxElement.value && searchBoxElement.value.trim().length > 0) {
|
15
|
+
siteSearchElement.classList.add('filled')
|
16
|
+
onSearchChangeDebounced()
|
17
|
+
} else {
|
18
|
+
siteSearchElement.classList.remove('filled')
|
19
|
+
onSearchChange()
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
searchBoxElement.onfocus = function () {
|
24
|
+
siteSearchElement.classList.add('focused')
|
25
|
+
if (siteSearchElement.classList.contains('filled')) {
|
26
|
+
searchResults.classList.add('visible')
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
searchBoxElement.onblur = function() {
|
31
|
+
siteSearchElement.classList.remove('focused')
|
32
|
+
}
|
33
|
+
|
34
|
+
document.body.addEventListener('click', function (event) {
|
35
|
+
var target = event.target
|
36
|
+
if (target.id !== 'search-box' && !target.classList.contains('search-btn') && !target.parentNode.classList.contains('search-btn')) {
|
37
|
+
searchResults.classList.remove('visible')
|
38
|
+
}
|
39
|
+
})
|
40
|
+
|
41
|
+
clearButton.onclick = function () {
|
42
|
+
searchBoxElement.value = ''
|
43
|
+
searchBoxElement.dispatchEvent(new Event('input', {
|
44
|
+
'bubbles': true,
|
45
|
+
'cancelable': true
|
46
|
+
}))
|
47
|
+
}
|
48
|
+
|
49
|
+
// Assign search endpoint based on env config
|
50
|
+
// ===========================================================================
|
51
|
+
var endpoint = null
|
52
|
+
var env = '{{ jekyll.environment }}'
|
53
|
+
var elasticSearchIndex = '{{site.github.owner_name}}-{{site.github.repository_name}}'
|
54
|
+
|
55
|
+
if (env === 'production') {
|
56
|
+
endpoint = '{{ site.server_PROD | append: '/' }}' + elasticSearchIndex
|
57
|
+
} else {
|
58
|
+
// Allow overriding of search index in dev env
|
59
|
+
var configElasticSearchIndex = '{{site.elastic_search_index}}'
|
60
|
+
if (configElasticSearchIndex) {
|
61
|
+
elasticSearchIndex = configElasticSearchIndex
|
62
|
+
}
|
63
|
+
endpoint = '{{ site.server_DEV | append: '/' }}' + elasticSearchIndex
|
64
|
+
}
|
65
|
+
|
66
|
+
var search_endpoint = endpoint + '/search'
|
67
|
+
|
68
|
+
|
69
|
+
// Global Variables
|
70
|
+
// =============================================================================
|
71
|
+
|
72
|
+
var wordsToHighlight = []
|
73
|
+
var sectionIndex = {}
|
74
|
+
var minQueryLength = 3
|
75
|
+
var lunrIndex = null
|
76
|
+
// Begin Lunr Indexing
|
77
|
+
// =============================================================================
|
78
|
+
function getLunrIndex() {
|
79
|
+
return fetch('{{ "/assets/lunrIndex.json" | relative_url }}')
|
80
|
+
.then(function (res) {
|
81
|
+
return res.json()
|
82
|
+
})
|
83
|
+
.then(function (json) {
|
84
|
+
lunrIndex = lunr.Index.load(json.index)
|
85
|
+
lunrIndex.pipeline.remove(lunr.stemmer)
|
86
|
+
sectionIndex = json.sectionIndex
|
87
|
+
})
|
88
|
+
.catch(function (err) {
|
89
|
+
console.error('Fetch failed to read the Lunr index: ' + err)
|
90
|
+
})
|
91
|
+
}
|
92
|
+
|
93
|
+
// Load Lunr Index if set
|
94
|
+
// ============================================================================
|
95
|
+
var searchSetOffline = "{{ site.offline }}" === "true" || false
|
96
|
+
|
97
|
+
if (searchSetOffline) {
|
98
|
+
getLunrIndex()
|
99
|
+
}
|
100
|
+
|
101
|
+
// Search
|
102
|
+
// =============================================================================
|
103
|
+
// Helper function to translate lunr search results
|
104
|
+
// Returns a simple { title, content, link } array
|
105
|
+
var snippetSpace = 40
|
106
|
+
var maxSnippets = 4
|
107
|
+
var maxResults = 10
|
108
|
+
var translateLunrResults = function (allLunrResults) {
|
109
|
+
var lunrResults = allLunrResults.slice(0, maxResults)
|
110
|
+
return lunrResults.map(function (result) {
|
111
|
+
var matchedDocument = sectionIndex[result.ref]
|
112
|
+
var contentSnippets = []
|
113
|
+
var titleSnippets = []
|
114
|
+
var snippetsRangesByFields = {}
|
115
|
+
// Loop over matching terms
|
116
|
+
var rangesByFields = {}
|
117
|
+
// Group ranges according to field type(text / title)
|
118
|
+
for (var term in result.matchData.metadata) {
|
119
|
+
// To highlight the main body later
|
120
|
+
wordsToHighlight.push(term)
|
121
|
+
var fields = result.matchData.metadata[term]
|
122
|
+
for (var field in fields) {
|
123
|
+
positions = fields[field].position
|
124
|
+
rangesByFields[field] = rangesByFields[field] ? rangesByFields[field].concat(positions) : positions
|
125
|
+
}
|
126
|
+
}
|
127
|
+
var snippetCount = 0
|
128
|
+
// Sort according to ascending snippet range
|
129
|
+
for (var field in rangesByFields) {
|
130
|
+
var ranges = rangesByFields[field]
|
131
|
+
.map(function (a) {
|
132
|
+
return [a[0] - snippetSpace, a[0] + a[1] + snippetSpace, a[0], a[0] + a[1]]
|
133
|
+
})
|
134
|
+
.sort(function (a, b) {
|
135
|
+
return a[0] - b[0]
|
136
|
+
})
|
137
|
+
// Merge contiguous ranges
|
138
|
+
var startIndex = ranges[0][0]
|
139
|
+
var endIndex = ranges[0][1]
|
140
|
+
var mergedRanges = []
|
141
|
+
var highlightRanges = []
|
142
|
+
for (rangeIndex in ranges) {
|
143
|
+
var range = ranges[rangeIndex]
|
144
|
+
snippetCount++
|
145
|
+
if (range[0] <= endIndex) {
|
146
|
+
endIndex = Math.max(range[1], endIndex)
|
147
|
+
highlightRanges = highlightRanges.concat([range[2], range[3]])
|
148
|
+
} else {
|
149
|
+
mergedRanges.push([startIndex].concat(highlightRanges).concat([endIndex]))
|
150
|
+
startIndex = range[0]
|
151
|
+
endIndex = range[1]
|
152
|
+
highlightRanges = [range[2], range[3]]
|
153
|
+
}
|
154
|
+
if (snippetCount >= maxSnippets) {
|
155
|
+
mergedRanges.push([startIndex].concat(highlightRanges).concat([endIndex]))
|
156
|
+
snippetsRangesByFields[field] = mergedRanges
|
157
|
+
break
|
158
|
+
}
|
159
|
+
if (+rangeIndex === ranges.length - 1) {
|
160
|
+
if (snippetCount + 1 < maxSnippets) {
|
161
|
+
snippetCount++
|
162
|
+
}
|
163
|
+
mergedRanges.push([startIndex].concat(highlightRanges).concat([endIndex]))
|
164
|
+
snippetsRangesByFields[field] = mergedRanges
|
165
|
+
if (snippetCount >= maxSnippets) {
|
166
|
+
break
|
167
|
+
}
|
168
|
+
}
|
169
|
+
}
|
170
|
+
}
|
171
|
+
// Extract snippets and add highlights to search results
|
172
|
+
for (var field in snippetsRangesByFields) {
|
173
|
+
positions = snippetsRangesByFields[field]
|
174
|
+
positions.forEach(function (position) {
|
175
|
+
matchedText = matchedDocument[field]
|
176
|
+
var snippet = ''
|
177
|
+
// If start of matched text dont use ellipsis
|
178
|
+
if (position[0] > 0) {
|
179
|
+
snippet += '...'
|
180
|
+
}
|
181
|
+
snippet += matchedText.substring(position[0], position[1])
|
182
|
+
for (var i = 1; i <= position.length - 2; i++) {
|
183
|
+
if (i % 2 == 1) {
|
184
|
+
snippet += '<mark>'
|
185
|
+
} else {
|
186
|
+
snippet += '</mark>'
|
187
|
+
}
|
188
|
+
snippet += matchedText.substring(position[i], position[i + 1])
|
189
|
+
}
|
190
|
+
if (field === 'title') {
|
191
|
+
titleSnippets.push(snippet)
|
192
|
+
} else {
|
193
|
+
snippet += '...'
|
194
|
+
contentSnippets.push(snippet)
|
195
|
+
}
|
196
|
+
})
|
197
|
+
}
|
198
|
+
var joinHighlights = function (str) {
|
199
|
+
if (str) {
|
200
|
+
return str.replace(/<\/mark> <mark>/g, ' ')
|
201
|
+
}
|
202
|
+
}
|
203
|
+
// Build a simple flat object per lunr result
|
204
|
+
return {
|
205
|
+
title: joinHighlights(titleSnippets.length === 0 ? matchedDocument.title: titleSnippets.join(' ')),
|
206
|
+
documentTitle: joinHighlights(matchedDocument.documentTitle),
|
207
|
+
content: joinHighlights(contentSnippets.join(' ')),
|
208
|
+
url: matchedDocument.url
|
209
|
+
}
|
210
|
+
})
|
211
|
+
}
|
212
|
+
|
213
|
+
// Displays the search results in HTML
|
214
|
+
// Takes an array of objects with "title" and "content" properties
|
215
|
+
var renderSearchResultsFromLunr = function (searchResults) {
|
216
|
+
var container = document.getElementsByClassName('search-results')[0]
|
217
|
+
container.scrollTop = 0
|
218
|
+
container.innerHTML = ''
|
219
|
+
if (!searchResults || searchResults.length === 0) {
|
220
|
+
var error = generateErrorHTML()
|
221
|
+
container.append(error)
|
222
|
+
} else {
|
223
|
+
searchResults.forEach(function (result, i) {
|
224
|
+
var element = generateResultHTML(result, i)
|
225
|
+
container.appendChild(element)
|
226
|
+
})
|
227
|
+
}
|
228
|
+
}
|
229
|
+
|
230
|
+
var renderSearchResultsFromServer = function (searchResults) {
|
231
|
+
var container = document.getElementsByClassName('search-results')[0]
|
232
|
+
container.scrollTop = 0
|
233
|
+
container.innerHTML = ''
|
234
|
+
if (typeof searchResults.hits === 'undefined') {
|
235
|
+
var error = document.createElement('p')
|
236
|
+
error.classList.add('not-found')
|
237
|
+
error.innerHTML = searchResults
|
238
|
+
container.appendChild(error)
|
239
|
+
// Check if there are hits and max_score is more than 0
|
240
|
+
// Max score is checked as well as filter will always return something
|
241
|
+
} else if (searchResults.hits.hits.length === 0 || searchResults.hits['max_score'] === 0) {
|
242
|
+
var error = generateErrorHTML()
|
243
|
+
container.appendChild(error)
|
244
|
+
} else {
|
245
|
+
searchResults.hits.hits.forEach(function (result, i) {
|
246
|
+
if (result._score) {
|
247
|
+
var formatted = formatResult(result, i)
|
248
|
+
var element = generateResultHTML(formatted)
|
249
|
+
container.appendChild(element)
|
250
|
+
}
|
251
|
+
});
|
252
|
+
highlightBody()
|
253
|
+
}
|
254
|
+
}
|
255
|
+
|
256
|
+
var generateErrorHTML = function () {
|
257
|
+
var error = document.createElement('p')
|
258
|
+
error.innerHTML = 'Results matching your query were not found.'
|
259
|
+
error.classList.add('not-found')
|
260
|
+
return error
|
261
|
+
}
|
262
|
+
|
263
|
+
var generateResultHTML = function (result, i) {
|
264
|
+
var element = document.createElement('a')
|
265
|
+
element.className = 'search-link nav-link'
|
266
|
+
var urlParts = result.url.split('/')
|
267
|
+
urlParts = urlParts.filter(function (part) {
|
268
|
+
return part !== ''
|
269
|
+
})
|
270
|
+
element.href = '/' + urlParts.join('/')
|
271
|
+
var searchResult = document.createElement('div')
|
272
|
+
var searchTitle = document.createElement('p')
|
273
|
+
searchTitle.className = 'search-title'
|
274
|
+
searchTitle.innerHTML = result.documentTitle || {{ site.title | jsonify }}
|
275
|
+
searchResult.appendChild(searchTitle)
|
276
|
+
var searchSubtitle = document.createElement('p')
|
277
|
+
searchSubtitle.className = 'search-subtitle'
|
278
|
+
searchSubtitle.innerHTML = result.title
|
279
|
+
searchResult.appendChild(searchSubtitle)
|
280
|
+
var searchContent = document.createElement('p')
|
281
|
+
searchContent.className = 'search-content'
|
282
|
+
searchContent.innerHTML = result.content
|
283
|
+
searchResult.appendChild(searchContent)
|
284
|
+
element.onmouseup = function() {
|
285
|
+
searchResults.classList.remove('visible')
|
286
|
+
}
|
287
|
+
element.appendChild(searchResult)
|
288
|
+
return element
|
289
|
+
}
|
290
|
+
|
291
|
+
formatResult = function (result) {
|
292
|
+
var content = null
|
293
|
+
var title = result._source.title
|
294
|
+
var url = result._source.url;
|
295
|
+
var documentTitle = result._source.documentTitle;
|
296
|
+
var regex = /<mark>(.*?)<\/mark>/g
|
297
|
+
var joinHighlights = function (str) {
|
298
|
+
if (str) {
|
299
|
+
return str.replace(/<\/mark> <mark>/g, ' ')
|
300
|
+
}
|
301
|
+
}
|
302
|
+
if (result.highlight) {
|
303
|
+
['title', 'content'].forEach(function (field) {
|
304
|
+
var curr, match, term;
|
305
|
+
if (result.highlight[field]) {
|
306
|
+
var curr = result.highlight[field].join('...')
|
307
|
+
// trimLeft not supported in IE
|
308
|
+
var curr = curr.replace(/^\s+/, "")
|
309
|
+
var curr = joinHighlights(curr)
|
310
|
+
var match = true
|
311
|
+
while (match) {
|
312
|
+
match = regex.exec(curr)
|
313
|
+
if (match) {
|
314
|
+
var term = match[1].toLowerCase()
|
315
|
+
if ((wordsToHighlight.indexOf(term)) < 0) {
|
316
|
+
wordsToHighlight.push(term)
|
317
|
+
}
|
318
|
+
}
|
319
|
+
}
|
320
|
+
}
|
321
|
+
})
|
322
|
+
if (result.highlight.content) {
|
323
|
+
content = joinHighlights(result.highlight.content.slice(0, Math.min(3, result.highlight.content.length)).join('...'))
|
324
|
+
}
|
325
|
+
if (result.highlight.title) {
|
326
|
+
title = joinHighlights(result.highlight.title[0])
|
327
|
+
}
|
328
|
+
}
|
329
|
+
return {
|
330
|
+
url: url,
|
331
|
+
content: content ? '...' + content + '...' : '',
|
332
|
+
title: title,
|
333
|
+
documentTitle: documentTitle
|
334
|
+
}
|
335
|
+
}
|
336
|
+
|
337
|
+
var debounce = function (func, threshold, execAsap) {
|
338
|
+
var timeout = null;
|
339
|
+
return function () {
|
340
|
+
var args = 1 <= arguments.length ? slice.call(arguments, 0) : []
|
341
|
+
obj = this
|
342
|
+
var delayed = function () {
|
343
|
+
if (!execAsap) {
|
344
|
+
func.apply(obj, args)
|
345
|
+
}
|
346
|
+
timeout = null
|
347
|
+
}
|
348
|
+
if (timeout) {
|
349
|
+
clearTimeout(timeout)
|
350
|
+
} else if (execAsap) {
|
351
|
+
func.apply(obj, args)
|
352
|
+
}
|
353
|
+
timeout = setTimeout(delayed, threshold || 100)
|
354
|
+
}
|
355
|
+
}
|
356
|
+
|
357
|
+
|
358
|
+
var createEsQuery = function (queryStr) {
|
359
|
+
var source = ['title', 'url', 'documentTitle']
|
360
|
+
var title_automcomplete_q = {
|
361
|
+
'match_phrase_prefix': {
|
362
|
+
'title': {
|
363
|
+
'query': queryStr,
|
364
|
+
'max_expansions': 20,
|
365
|
+
'boost': 100,
|
366
|
+
'slop': 10
|
367
|
+
}
|
368
|
+
}
|
369
|
+
}
|
370
|
+
var content_automcomplete_q = {
|
371
|
+
'match_phrase_prefix': {
|
372
|
+
'content': {
|
373
|
+
'query': queryStr,
|
374
|
+
'max_expansions': 20,
|
375
|
+
'boost': 60,
|
376
|
+
'slop': 10
|
377
|
+
}
|
378
|
+
}
|
379
|
+
}
|
380
|
+
var title_keyword_q = {
|
381
|
+
'match': {
|
382
|
+
'title': {
|
383
|
+
'query': queryStr,
|
384
|
+
'fuzziness': 'AUTO',
|
385
|
+
'max_expansions': 10,
|
386
|
+
'boost': 20,
|
387
|
+
'analyzer': 'stop'
|
388
|
+
}
|
389
|
+
}
|
390
|
+
}
|
391
|
+
var content_keyword_q = {
|
392
|
+
'match': {
|
393
|
+
'content': {
|
394
|
+
'query': queryStr,
|
395
|
+
'fuzziness': 'AUTO',
|
396
|
+
'max_expansions': 10,
|
397
|
+
'analyzer': 'stop'
|
398
|
+
}
|
399
|
+
}
|
400
|
+
}
|
401
|
+
|
402
|
+
var bool_q = {
|
403
|
+
'bool': {
|
404
|
+
'should': [title_automcomplete_q, content_automcomplete_q, title_keyword_q, content_keyword_q],
|
405
|
+
}
|
406
|
+
}
|
407
|
+
|
408
|
+
// If document filter is present
|
409
|
+
var page = pageIndex[window.location.pathname]
|
410
|
+
if (!searchFilter.classList.contains('hidden') && page && page.documentInfo[0]) {
|
411
|
+
// documentId is the alphanumeric and lowercase version of document title
|
412
|
+
// used as a keyword filter to search within the document
|
413
|
+
var documentId = page.documentInfo[0].replace(/[^\w]/g, '').toLowerCase()
|
414
|
+
var filter_by_document = {
|
415
|
+
'term': {
|
416
|
+
'documentId': documentId
|
417
|
+
}
|
418
|
+
}
|
419
|
+
bool_q.bool.filter = filter_by_document
|
420
|
+
}
|
421
|
+
|
422
|
+
var highlight = {}
|
423
|
+
highlight.require_field_match = false
|
424
|
+
highlight.fields = {}
|
425
|
+
highlight.fields['content'] = {
|
426
|
+
'fragment_size': 80,
|
427
|
+
'number_of_fragments': 6,
|
428
|
+
'pre_tags': ['<mark>'],
|
429
|
+
'post_tags': ['</mark>']
|
430
|
+
}
|
431
|
+
highlight.fields['title'] = {
|
432
|
+
'fragment_size': 80,
|
433
|
+
'number_of_fragments': 6,
|
434
|
+
'pre_tags': ['<mark>'],
|
435
|
+
'post_tags': ['</mark>']
|
436
|
+
}
|
437
|
+
return {
|
438
|
+
'_source': source,
|
439
|
+
'query': bool_q,
|
440
|
+
'highlight': highlight
|
441
|
+
}
|
442
|
+
}
|
443
|
+
|
444
|
+
// Call the API
|
445
|
+
esSearch = function (query) {
|
446
|
+
var esQuery = createEsQuery(query)
|
447
|
+
fetch(search_endpoint, {
|
448
|
+
method: 'POST',
|
449
|
+
headers: {
|
450
|
+
'Content-Type': 'application/json'
|
451
|
+
},
|
452
|
+
body: JSON.stringify(esQuery)
|
453
|
+
})
|
454
|
+
.then(checkStatus)
|
455
|
+
.then(parseJSON)
|
456
|
+
.then(function (data) {
|
457
|
+
renderSearchResultsFromServer(data.body)
|
458
|
+
})
|
459
|
+
.catch(function (err) {
|
460
|
+
console.error(err)
|
461
|
+
renderSearchResultsFromServer('Failed to fetch search results')
|
462
|
+
})
|
463
|
+
}
|
464
|
+
|
465
|
+
var lunrSearch = function (query) {
|
466
|
+
// Add wildcard before and after
|
467
|
+
var queryTerm = refineLunrSearchQuery(query)
|
468
|
+
if (lunrIndex !== null) {
|
469
|
+
var lunrResults = lunrIndex.search(queryTerm)
|
470
|
+
var results = translateLunrResults(lunrResults)
|
471
|
+
highlightBody()
|
472
|
+
renderSearchResultsFromLunr(results)
|
473
|
+
}
|
474
|
+
}
|
475
|
+
|
476
|
+
var refineLunrSearchQuery = function(query) {
|
477
|
+
FUZZY_FACTOR = 4 // range: 1 to INF. Lower is fuzzier *relative to term length*.
|
478
|
+
var addFuzzyOperator = function(term, fuzziness) {
|
479
|
+
return term + '~' +
|
480
|
+
Math.floor(term.length / Math.max(1, fuzziness)).toString()
|
481
|
+
}
|
482
|
+
var stringIsLettersOnly = function(str) {
|
483
|
+
return /^[a-zA-Z]+$/.test(str)
|
484
|
+
}
|
485
|
+
|
486
|
+
var terms = query.split(' ')
|
487
|
+
terms = terms.map(function(term) {
|
488
|
+
if (stringIsLettersOnly(term)) {
|
489
|
+
return addFuzzyOperator(term, FUZZY_FACTOR)
|
490
|
+
}
|
491
|
+
return term
|
492
|
+
})
|
493
|
+
return terms.join(' ')
|
494
|
+
}
|
495
|
+
|
496
|
+
|
497
|
+
var onSearchChange = function () {
|
498
|
+
var query = searchBoxElement.value.trim()
|
499
|
+
// Clear highlights
|
500
|
+
wordsToHighlight = []
|
501
|
+
if (query.length < minQueryLength) {
|
502
|
+
searchResults.classList.remove('visible')
|
503
|
+
highlightBody()
|
504
|
+
return
|
505
|
+
}
|
506
|
+
searchResults.classList.add('visible')
|
507
|
+
|
508
|
+
if (searchSetOffline) {
|
509
|
+
lunrSearch(query)
|
510
|
+
} else {
|
511
|
+
esSearch(query)
|
512
|
+
if (env === 'production' && window.ga) {
|
513
|
+
window.ga('send', 'pageview', '/search?query=' + encodeURIComponent(query))
|
514
|
+
}
|
515
|
+
}
|
516
|
+
}
|
517
|
+
|
518
|
+
var onSearchChangeDebounced = debounce(onSearchChange, 500, false)
|
519
|
+
|
520
|
+
var isBackspaceFirstPress = true
|
521
|
+
var isBackspacePressedOnEmpty = false
|
522
|
+
// Detect that backspace is not part of longpress
|
523
|
+
searchBoxElement.onkeydown = function (e) {
|
524
|
+
searchResults.classList.remove('hidden')
|
525
|
+
if (isBackspaceFirstPress && e.keyCode === 8) {
|
526
|
+
isBackspaceFirstPress = false
|
527
|
+
if (searchBoxElement.value === '') {
|
528
|
+
isBackspacePressedOnEmpty = true
|
529
|
+
}
|
530
|
+
}
|
531
|
+
}
|
532
|
+
|
533
|
+
clearSearchFilter = function () {
|
534
|
+
searchFilter.classList.add('hidden')
|
535
|
+
}
|
536
|
+
|
537
|
+
searchFilter.onclick = clearSearchFilter
|
538
|
+
|
539
|
+
searchBoxElement.onkeyup = function (e) {
|
540
|
+
// flash search results on enter
|
541
|
+
if (e.keyCode === 13) {
|
542
|
+
var container = document.getElementsByClassName('search-results')[0]
|
543
|
+
container.style.opacity = 0
|
544
|
+
return setTimeout(function () {
|
545
|
+
return container.style.opacity = 1
|
546
|
+
}, 100)
|
547
|
+
}
|
548
|
+
// Delete filter on backspace when input is empty and not part of longpress
|
549
|
+
if (e.keyCode === 8) {
|
550
|
+
isBackspaceFirstPress = true
|
551
|
+
if (searchBoxElement.value === '' && isBackspacePressedOnEmpty) {
|
552
|
+
clearSearchFilter()
|
553
|
+
isBackspacePressedOnEmpty = false
|
554
|
+
return
|
555
|
+
}
|
556
|
+
}
|
557
|
+
}
|
558
|
+
|
559
|
+
|
560
|
+
// Highlighting
|
561
|
+
// ============================================================================
|
562
|
+
window.highlightBody = function () {
|
563
|
+
// Check if Mark.js script is already imported
|
564
|
+
if (Mark) {
|
565
|
+
var instance = new Mark(main)
|
566
|
+
instance.unmark()
|
567
|
+
if (wordsToHighlight.length > 0) {
|
568
|
+
instance.mark(wordsToHighlight, {
|
569
|
+
exclude: ['h1'],
|
570
|
+
accuracy: {
|
571
|
+
value: 'exactly',
|
572
|
+
limiters: [',', '.', '(', ')', '-', '\'', '[', ']', '?', '/', '\\', ':', '*', '!', '@', '&']
|
573
|
+
},
|
574
|
+
separateWordSearch: false
|
575
|
+
})
|
576
|
+
}
|
577
|
+
}
|
578
|
+
}
|
579
|
+
|
580
|
+
})()
|