Skip to content

Commit d2ace54

Browse files
committed
⚡ 优化搜索框代码
1 parent 773aebd commit d2ace54

4 files changed

Lines changed: 149 additions & 139 deletions

File tree

layout/_partial/plugins/local-search.ejs

Lines changed: 0 additions & 14 deletions
This file was deleted.

layout/_partial/scripts.ejs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@
4444
<%- js_ex(theme.static_prefix.clipboard, 'clipboard.min.js', 'defer') %>
4545
<% } %>
4646

47+
<% if(theme.search.enable){ %>
48+
<%- js_ex(theme.static_prefix.internal_js, 'local-search.js') %>
49+
<% } %>
50+
4751
<% if ((theme.footer.statistics.enable && theme.footer.statistics.source === 'busuanzi')
4852
|| (page.meta !== false && theme.post.meta.views.enable && theme.post.meta.views.source === 'busuanzi')) { %>
4953
<%- js_ex(theme.static_prefix.busuanzi, 'busuanzi.pure.mini.js', 'defer') %>
@@ -57,7 +61,6 @@
5761
<% } %>
5862

5963
<%- partial('_partial/plugins/typed.ejs') %>
60-
<%- partial('_partial/plugins/local-search.ejs') %>
6164
<%- partial('_partial/plugins/math.ejs') %>
6265
<%- partial('_partial/plugins/mermaid.ejs') %>
6366
<%- partial('_partial/plugins/analytics.ejs') %>

scripts/helpers/export-config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ hexo.extend.helper.register('export_config', function() {
2020
image_zoom : theme.post.image_zoom,
2121
toc : theme.post.toc,
2222
lazyload : theme.lazyload,
23-
web_analytics: theme.web_analytics
23+
web_analytics: theme.web_analytics,
24+
search_path : theme.search.path
2425
};
2526
return `<script id="fluid-configs">
2627
var Fluid = window.Fluid || {};

source/js/local-search.js

Lines changed: 143 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,140 +1,160 @@
1-
// A local search script with the help of [hexo-generator-search](https://github.com/PaicHyperionDev/hexo-generator-search)
2-
// Copyright (C) 2017
3-
// Liam Huang <https://github.com/Liam0205>
4-
// This library is free software; you can redistribute it and/or modify
5-
// it under the terms of the GNU Lesser General Public License as
6-
// published by the Free Software Foundation; either version 2.1 of the
7-
// License, or (at your option) any later version.
8-
//
9-
// This library is distributed in the hope that it will be useful, but
10-
// WITHOUT ANY WARRANTY; without even the implied warranty of
11-
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12-
// Lesser General Public License for more details.
13-
//
14-
// You should have received a copy of the GNU Lesser General Public
15-
// License along with this library; if not, write to the Free Software
16-
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17-
// 02110-1301 USA
18-
//
19-
// Updated by Rook1e <https://github.com/0x2E>
20-
21-
// eslint-disable-next-line no-unused-vars
22-
var searchFunc = function(path, search_id, content_id) {
23-
// 0x00. environment initialization
24-
'use strict';
25-
var $input = document.getElementById(search_id);
26-
var $resultContent = document.getElementById(content_id);
27-
28-
if ($resultContent.innerHTML.indexOf('list-group-item') === -1) {
29-
$resultContent.innerHTML = '<div class="m-auto text-center"><div class="spinner-border" role="status"><span class="sr-only">Loading...</span></div><br/>Loading...</div>';
30-
}
1+
/* global CONFIG */
312

32-
$.ajax({
33-
// 0x01. load xml file
34-
url : path,
35-
dataType: 'xml',
36-
success : function(xmlResponse) {
37-
// 0x02. parse xml file
38-
var dataList = jQuery('entry', xmlResponse).map(function() {
39-
return {
40-
title : jQuery('title', this).text(),
41-
content: jQuery('content', this).text(),
42-
url : jQuery('url', this).text()
43-
};
44-
}).get();
45-
46-
if ($resultContent.innerHTML.indexOf('list-group-item') === -1) {
47-
$resultContent.innerHTML = '';
48-
}
3+
(function() {
4+
// Modify by [hexo-generator-search](https://github.com/wzpan/hexo-generator-search)
5+
function localSearchFunc(path, searchSelector, resultSelector) {
6+
'use strict';
7+
// 0x00. environment initialization
8+
var $input = jQuery(searchSelector);
9+
var $result = jQuery(resultSelector);
10+
11+
if ($input.length === 0) {
12+
// eslint-disable-next-line no-console
13+
throw Error('No element selected by the searchSelector');
14+
}
15+
if ($result.length === 0) {
16+
// eslint-disable-next-line no-console
17+
throw Error('No element selected by the resultSelector');
18+
}
4919

50-
$input.addEventListener('input', function() {
51-
// 0x03. parse query to keywords list
52-
var str = '';
53-
var keywords = this.value.trim().toLowerCase().split(/[\s-]+/);
54-
$resultContent.innerHTML = '';
55-
if (this.value.trim().length <= 0) {
56-
return;
20+
if ($result.attr('class').indexOf('list-group-item') === -1) {
21+
$result.html('<div class="m-auto text-center"><div class="spinner-border" role="status"><span class="sr-only">Loading...</span></div><br/>Loading...</div>');
22+
}
23+
24+
$.ajax({
25+
// 0x01. load xml file
26+
url : path,
27+
dataType: 'xml',
28+
success : function(xmlResponse) {
29+
// 0x02. parse xml file
30+
var dataList = jQuery('entry', xmlResponse).map(function() {
31+
return {
32+
title : jQuery('title', this).text(),
33+
content: jQuery('content', this).text(),
34+
url : jQuery('url', this).text()
35+
};
36+
}).get();
37+
38+
if ($result.html().indexOf('list-group-item') === -1) {
39+
$result.html('');
5740
}
58-
// 0x04. perform local searching
59-
dataList.forEach(function(data) {
60-
var isMatch = true;
61-
if (!data.title || data.title.trim() === '') {
62-
data.title = 'Untitled';
41+
42+
$input.on('input', function() {
43+
// 0x03. parse query to keywords list
44+
var content = $input.val();
45+
var resultHTML = '';
46+
var keywords = content.trim().toLowerCase().split(/[\s-]+/);
47+
$result.html('');
48+
if (content.trim().length <= 0) {
49+
return $input.removeClass('invalid').removeClass('valid');
6350
}
64-
var orig_data_title = data.title.trim();
65-
var data_title = orig_data_title.toLowerCase();
66-
var orig_data_content = data.content.trim().replace(/<[^>]+>/g, '');
67-
var data_content = orig_data_content.toLowerCase();
68-
var data_url = data.url;
69-
var index_title = -1;
70-
var index_content = -1;
71-
var first_occur = -1;
72-
// only match articles with not empty contents
73-
if (data_content !== '') {
74-
keywords.forEach(function(keyword, i) {
75-
index_title = data_title.indexOf(keyword);
76-
index_content = data_content.indexOf(keyword);
77-
78-
if (index_title < 0 && index_content < 0) {
79-
isMatch = false;
80-
} else {
81-
if (index_content < 0) {
82-
index_content = 0;
51+
// 0x04. perform local searching
52+
dataList.forEach(function(data) {
53+
var isMatch = true;
54+
if (!data.title || data.title.trim() === '') {
55+
data.title = 'Untitled';
56+
}
57+
var orig_data_title = data.title.trim();
58+
var data_title = orig_data_title.toLowerCase();
59+
var orig_data_content = data.content.trim().replace(/<[^>]+>/g, '');
60+
var data_content = orig_data_content.toLowerCase();
61+
var data_url = data.url;
62+
var index_title = -1;
63+
var index_content = -1;
64+
var first_occur = -1;
65+
// only match articles with not empty contents
66+
if (data_content !== '') {
67+
keywords.forEach(function(keyword, i) {
68+
index_title = data_title.indexOf(keyword);
69+
index_content = data_content.indexOf(keyword);
70+
71+
if (index_title < 0 && index_content < 0) {
72+
isMatch = false;
73+
} else {
74+
if (index_content < 0) {
75+
index_content = 0;
76+
}
77+
if (i === 0) {
78+
first_occur = index_content;
79+
}
80+
//content_index.push({index_content:index_content, keyword_len:keyword_len});
8381
}
84-
if (i === 0) {
85-
first_occur = index_content;
82+
});
83+
} else {
84+
isMatch = false;
85+
}
86+
// 0x05. show search results
87+
if (isMatch) {
88+
resultHTML += '<a href=\'' + data_url + '\' class=\'list-group-item list-group-item-action font-weight-bolder search-list-title\'>' + orig_data_title + '</a>';
89+
var content = orig_data_content;
90+
if (first_occur >= 0) {
91+
// cut out 100 characters
92+
var start = first_occur - 20;
93+
var end = first_occur + 80;
94+
95+
if (start < 0) {
96+
start = 0;
8697
}
87-
//content_index.push({index_content:index_content, keyword_len:keyword_len});
88-
}
89-
});
90-
} else {
91-
isMatch = false;
92-
}
93-
// 0x05. show search results
94-
if (isMatch) {
95-
str += '<a href=\'' + data_url + '\' class=\'list-group-item list-group-item-action font-weight-bolder search-list-title\'>' + orig_data_title + '</a>';
96-
var content = orig_data_content;
97-
if (first_occur >= 0) {
98-
// cut out 100 characters
99-
var start = first_occur - 20;
100-
var end = first_occur + 80;
101-
102-
if (start < 0) {
103-
start = 0;
104-
}
10598

106-
if (start === 0) {
107-
end = 100;
108-
}
99+
if (start === 0) {
100+
end = 100;
101+
}
109102

110-
if (end > content.length) {
111-
end = content.length;
112-
}
103+
if (end > content.length) {
104+
end = content.length;
105+
}
113106

114-
var match_content = content.substring(start, end);
107+
var match_content = content.substring(start, end);
115108

116-
// highlight all keywords
117-
keywords.forEach(function(keyword) {
118-
var regS = new RegExp(keyword, 'gi');
119-
match_content = match_content.replace(regS, '<span class="search-word">' + keyword + '</span>');
120-
});
109+
// highlight all keywords
110+
keywords.forEach(function(keyword) {
111+
var regS = new RegExp(keyword, 'gi');
112+
match_content = match_content.replace(regS, '<span class="search-word">' + keyword + '</span>');
113+
});
121114

122-
str += '<p class=\'search-list-content\'>' + match_content + '...</p>';
115+
resultHTML += '<p class=\'search-list-content\'>' + match_content + '...</p>';
116+
}
123117
}
118+
});
119+
if (resultHTML.indexOf('list-group-item') === -1) {
120+
return $input.addClass('invalid').removeClass('valid');
124121
}
122+
$input.addClass('valid').removeClass('invalid');
123+
$result.html(resultHTML);
125124
});
126-
const input = jQuery('#local-search-input');
127-
if (str.indexOf('list-group-item') === -1) {
128-
return input.addClass('invalid').removeClass('valid');
129-
}
130-
input.addClass('valid').removeClass('invalid');
131-
$resultContent.innerHTML = str;
132-
});
125+
}
126+
});
127+
}
128+
129+
function localSearchReset(searchSelector, resultSelector) {
130+
'use strict';
131+
var $input = jQuery(searchSelector);
132+
var $result = jQuery(resultSelector);
133+
134+
if ($input.length === 0) {
135+
// eslint-disable-next-line no-console
136+
throw Error('No element selected by the searchSelector');
137+
}
138+
if ($result.length === 0) {
139+
// eslint-disable-next-line no-console
140+
throw Error('No element selected by the resultSelector');
133141
}
134-
});
135142

136-
jQuery('#local-search-close').on('click', function() {
137-
jQuery('#local-search-input').val('').removeClass('invalid').removeClass('valid');
138-
jQuery('#local-search-result').html('');
143+
$input.val('').removeClass('invalid').removeClass('valid');
144+
$result.html('');
145+
}
146+
147+
var modal = jQuery('#modalSearch');
148+
var searchSelector = '#local-search-input';
149+
var resultSelector = '#local-search-result';
150+
modal.on('show.bs.modal', function() {
151+
var path = CONFIG.search_path || '/local-search.xml';
152+
localSearchFunc(path, searchSelector, resultSelector);
153+
});
154+
modal.on('shown.bs.modal', function() {
155+
jQuery('#local-search-input').focus();
156+
});
157+
modal.on('hidden.bs.modal', function() {
158+
localSearchReset(searchSelector, resultSelector);
139159
});
140-
};
160+
})();

0 commit comments

Comments
 (0)