|
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 */ |
31 | 2 |
|
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 | + } |
49 | 19 |
|
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(''); |
57 | 40 | } |
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'); |
63 | 50 | } |
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}); |
83 | 81 | } |
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; |
86 | 97 | } |
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 | | - } |
105 | 98 |
|
106 | | - if (start === 0) { |
107 | | - end = 100; |
108 | | - } |
| 99 | + if (start === 0) { |
| 100 | + end = 100; |
| 101 | + } |
109 | 102 |
|
110 | | - if (end > content.length) { |
111 | | - end = content.length; |
112 | | - } |
| 103 | + if (end > content.length) { |
| 104 | + end = content.length; |
| 105 | + } |
113 | 106 |
|
114 | | - var match_content = content.substring(start, end); |
| 107 | + var match_content = content.substring(start, end); |
115 | 108 |
|
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 | + }); |
121 | 114 |
|
122 | | - str += '<p class=\'search-list-content\'>' + match_content + '...</p>'; |
| 115 | + resultHTML += '<p class=\'search-list-content\'>' + match_content + '...</p>'; |
| 116 | + } |
123 | 117 | } |
| 118 | + }); |
| 119 | + if (resultHTML.indexOf('list-group-item') === -1) { |
| 120 | + return $input.addClass('invalid').removeClass('valid'); |
124 | 121 | } |
| 122 | + $input.addClass('valid').removeClass('invalid'); |
| 123 | + $result.html(resultHTML); |
125 | 124 | }); |
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'); |
133 | 141 | } |
134 | | - }); |
135 | 142 |
|
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); |
139 | 159 | }); |
140 | | -}; |
| 160 | +})(); |
0 commit comments