Skip to content

Commit 7a33738

Browse files
author
cracky5322
committed
1.1.1
1 parent c41a63f commit 7a33738

3 files changed

Lines changed: 5332 additions & 0 deletions

File tree

Volantis/js/search/hexo.js

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
let SearchService = (() => {
2+
fn = {};
3+
fn.queryText = null;
4+
fn.data = null;
5+
fn.template = `<div id="u-search">
6+
<div class="modal">
7+
<header class="modal-header" class="clearfix">
8+
<form id="u-search-modal-form" class="u-search-form" name="uSearchModalForm">
9+
<input type="text" id="u-search-modal-input" class="u-search-input" />
10+
<button type="submit" id="u-search-modal-btn-submit" class="u-search-btn-submit">
11+
<span class="fas fa-search"></span>
12+
</button>
13+
</form>
14+
<a id="u-search-btn-close" class="btn-close"> <span class="fas fa-times"></span> </a>
15+
</header>
16+
<main class="modal-body">
17+
<ul class="modal-results"></ul>
18+
</main>
19+
</div>
20+
<div id="modal-overlay" class="modal-overlay"></div>
21+
</div>
22+
`;
23+
fn.init = () => {
24+
let div = document.createElement("div");
25+
div.innerHTML += fn.template;
26+
document.body.append(div);
27+
document.querySelectorAll(".u-search-form").forEach((e) => {
28+
e.addEventListener("submit", fn.onSubmit, false);
29+
});
30+
let uSearchModalInput = document.querySelector("#u-search-modal-input");
31+
uSearchModalInput.addEventListener("input", fn.onSubmit);
32+
document
33+
.querySelector("#u-search-btn-close")
34+
.addEventListener("click", fn.close, false);
35+
document
36+
.querySelector("#modal-overlay")
37+
.addEventListener("click", fn.close, false);
38+
};
39+
fn.onSubmit = (event) => {
40+
event.preventDefault();
41+
let input = event.target.querySelector(".u-search-input");
42+
if (input) {
43+
fn.queryText = input.value;
44+
} else {
45+
fn.queryText = event.target.value;
46+
}
47+
48+
if (fn.queryText) {
49+
fn.search();
50+
}
51+
};
52+
fn.search = async () => {
53+
document.querySelectorAll(".u-search-input").forEach((e) => {
54+
e.value = fn.queryText;
55+
});
56+
document.querySelector("#u-search").style.display = "block";
57+
if (!fn.data) {
58+
fn.data = await fn.fetchData();
59+
}
60+
let results = "";
61+
results += fn.buildResultList(data.pages);
62+
results += fn.buildResultList(data.posts);
63+
document.querySelector("#u-search .modal-results").innerHTML = results;
64+
window.pjax && pjax.refresh(document.querySelector("#u-search"));
65+
document.addEventListener("keydown", function f(event) {
66+
if (event.code === "Escape") {
67+
fn.close();
68+
document.removeEventListener("keydown", f);
69+
}
70+
});
71+
};
72+
fn.close = () => {
73+
document.querySelector("#u-search").style.display = "none";
74+
};
75+
fn.fetchData = () => {
76+
return fetch(SearchServiceDataPath)
77+
.then((response) => response.text())
78+
.then((res) => {
79+
data = JSON.parse(res);
80+
// console.log(data);
81+
return data;
82+
});
83+
};
84+
fn.buildResultList = (data) => {
85+
let html = "";
86+
data.forEach((post) => {
87+
if (post.text) {
88+
post.text = post.text.replace(/12345\d*/g, "") // 简易移除代码行号
89+
}
90+
if (fn.contentSearch(post)) {
91+
html += fn.buildResult(post.permalink, post.title, post.digest);
92+
}
93+
});
94+
return html;
95+
};
96+
fn.contentSearch = (post) => {
97+
let post_title = post.title.trim().toLowerCase();
98+
let post_content = post.text.trim().toLowerCase();
99+
let keywords = fn.queryText
100+
.trim()
101+
.toLowerCase()
102+
.split(/[-\s]+/);
103+
let foundMatch = false;
104+
let index_title = -1;
105+
let index_content = -1;
106+
let first_occur = -1;
107+
if (post_title && post_content) {
108+
keywords.forEach((word, index) => {
109+
index_title = post_title.indexOf(word);
110+
index_content = post_content.indexOf(word);
111+
if (index_title < 0 && index_content < 0) {
112+
foundMatch = false;
113+
} else {
114+
foundMatch = true;
115+
if (index_content < 0) {
116+
index_content = 0;
117+
}
118+
if (index === 0) {
119+
first_occur = index_content;
120+
}
121+
}
122+
if (foundMatch) {
123+
post_content = post.text.trim();
124+
let start = 0;
125+
let end = 0;
126+
if (first_occur >= 0) {
127+
start = Math.max(first_occur - 40, 0);
128+
end =
129+
start === 0
130+
? Math.min(200, post_content.length)
131+
: Math.min(first_occur + 120, post_content.length);
132+
let match_content = post_content.substring(start, end);
133+
keywords.forEach(function (keyword) {
134+
let regS = new RegExp(keyword, "gi");
135+
match_content = match_content.replace(
136+
regS,
137+
"<b mark>" + keyword + "</b>"
138+
);
139+
});
140+
post.digest = match_content + "......";
141+
} else {
142+
end = Math.min(200, post_content.length);
143+
post.digest = post_content.trim().substring(0, end);
144+
}
145+
}
146+
});
147+
}
148+
return foundMatch;
149+
};
150+
fn.buildResult = (url, title, digest) => {
151+
let result = fn.getUrlRelativePath(url);
152+
let html = "";
153+
html += "<li>";
154+
html +=
155+
"<a class='result' href='" + result + "?keyword=" + fn.queryText + "'>";
156+
html += "<span class='title'>" + title + "</span>";
157+
if (digest !== "") html += "<span class='digest'>" + digest + "</span>";
158+
html += "</a>";
159+
html += "</li>";
160+
return html;
161+
};
162+
fn.getUrlRelativePath = function (url) {
163+
let arrUrl = url.split("//");
164+
let start = arrUrl[1].indexOf("/");
165+
let relUrl = arrUrl[1].substring(start);
166+
if (relUrl.indexOf("?") != -1) {
167+
relUrl = relUrl.split("?")[0];
168+
}
169+
return relUrl;
170+
};
171+
return {
172+
init: () => {
173+
fn.init();
174+
},
175+
setQueryText: (queryText) => {
176+
fn.queryText = queryText;
177+
},
178+
search: () => {
179+
fn.search();
180+
},
181+
};
182+
})();
183+
Object.freeze(SearchService);
184+
185+
SearchService.init();
186+
document.addEventListener("pjax:success", SearchService.init);
187+
document.addEventListener("pjax:send", function () {
188+
document.querySelector("#u-search").style.display = "none";
189+
});

0 commit comments

Comments
 (0)