-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlocal-search.js
159 lines (142 loc) · 5.58 KB
/
local-search.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/* global CONFIG */
(function() {
// Modified from [hexo-generator-search](https://github.com/wzpan/hexo-generator-search)
function localSearchFunc(path, searchSelector, resultSelector) {
'use strict';
// 0x00. environment initialization
var $input = jQuery(searchSelector);
var $result = jQuery(resultSelector);
if ($input.length === 0) {
// eslint-disable-next-line no-console
throw Error('No element selected by the searchSelector');
}
if ($result.length === 0) {
// eslint-disable-next-line no-console
throw Error('No element selected by the resultSelector');
}
if ($result.attr('class').indexOf('list-group-item') === -1) {
$result.html('<div class="m-auto text-center"><div class="spinner-border" role="status"><span class="sr-only">Loading...</span></div><br/>Loading...</div>');
}
jQuery.ajax({
// 0x01. load xml file
url : path,
dataType: 'xml',
success : function(xmlResponse) {
// 0x02. parse xml file
var dataList = jQuery('entry', xmlResponse).map(function() {
return {
title : jQuery('title', this).text(),
content: jQuery('content', this).text(),
url : jQuery('url', this).text()
};
}).get();
if ($result.html().indexOf('list-group-item') === -1) {
$result.html('');
}
$input.on('input', function() {
// 0x03. parse query to keywords list
var content = $input.val();
var resultHTML = '';
var keywords = content.trim().toLowerCase().split(/[\s-]+/);
$result.html('');
if (content.trim().length <= 0) {
return $input.removeClass('invalid').removeClass('valid');
}
// 0x04. perform local searching
dataList.forEach(function(data) {
var isMatch = true;
if (!data.title || data.title.trim() === '') {
data.title = 'Untitled';
}
var orig_data_title = data.title.trim();
var data_title = orig_data_title.toLowerCase();
var orig_data_content = data.content.trim().replace(/<[^>]+>/g, '');
var data_content = orig_data_content.toLowerCase();
var data_url = data.url;
var index_title = -1;
var index_content = -1;
var first_occur = -1;
// Skip matching when content is included in search and content is empty
if (CONFIG.include_content_in_search && data_content === '') {
isMatch = false;
} else {
keywords.forEach(function (keyword, i) {
index_title = data_title.indexOf(keyword);
index_content = data_content.indexOf(keyword);
if (index_title < 0 && index_content < 0) {
isMatch = false;
} else {
if (index_content < 0) {
index_content = 0;
}
if (i === 0) {
first_occur = index_content;
}
}
});
}
// 0x05. show search results
if (isMatch) {
resultHTML += '<a href=\'' + data_url + '\' class=\'list-group-item list-group-item-action font-weight-bolder search-list-title\'>' + orig_data_title + '</a>';
var content = orig_data_content;
if (first_occur >= 0) {
// cut out 100 characters
var start = first_occur - 20;
var end = first_occur + 80;
if (start < 0) {
start = 0;
}
if (start === 0) {
end = 100;
}
if (end > content.length) {
end = content.length;
}
var match_content = content.substring(start, end);
// highlight all keywords
keywords.forEach(function(keyword) {
var regS = new RegExp(keyword, 'gi');
match_content = match_content.replace(regS, '<span class="search-word">' + keyword + '</span>');
});
resultHTML += '<p class=\'search-list-content\'>' + match_content + '...</p>';
}
}
});
if (resultHTML.indexOf('list-group-item') === -1) {
return $input.addClass('invalid').removeClass('valid');
}
$input.addClass('valid').removeClass('invalid');
$result.html(resultHTML);
});
}
});
}
function localSearchReset(searchSelector, resultSelector) {
'use strict';
var $input = jQuery(searchSelector);
var $result = jQuery(resultSelector);
if ($input.length === 0) {
// eslint-disable-next-line no-console
throw Error('No element selected by the searchSelector');
}
if ($result.length === 0) {
// eslint-disable-next-line no-console
throw Error('No element selected by the resultSelector');
}
$input.val('').removeClass('invalid').removeClass('valid');
$result.html('');
}
var modal = jQuery('#modalSearch');
var searchSelector = '#local-search-input';
var resultSelector = '#local-search-result';
modal.on('show.bs.modal', function() {
var path = CONFIG.search_path || '/local-search.xml';
localSearchFunc(path, searchSelector, resultSelector);
});
modal.on('shown.bs.modal', function() {
jQuery('#local-search-input').focus();
});
modal.on('hidden.bs.modal', function() {
localSearchReset(searchSelector, resultSelector);
});
})();