Skip to content

Commit 653d800

Browse files
committed
Search support
1 parent f65b0d6 commit 653d800

20 files changed

+189
-564
lines changed

Diff for: _includes/scripts/comments.html

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
{% include scripts/common.html %}
2-
<script src="{{ site.baseurl }}/assets/js/md5.min.js"></script>
3-
<script async src="{{ site.baseurl }}/assets/js/comments.min.js"></script>
1+
<script src="/assets/js/md5.min.js"></script>
2+
<script async src="/assets/js/comments.min.js"></script>

Diff for: _includes/scripts/common.html

-4
This file was deleted.

Diff for: _includes/scripts/contact.html

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
{% include scripts/common.html %}
2-
<script async src="{{ site.baseurl }}/assets/js/contact.js"></script>
1+
<script async src="/assets/js/contact.min.js"></script>

Diff for: _includes/scripts/search.html

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<script type="text/javascript" src="/assets/js/ao-search.min.js"></script>
2+
<script type="text/javascript">
3+
Ao.search({
4+
input: 'search-input',
5+
output: 'search-results',
6+
url: '{{ site.baseurl }}/search.json',
7+
template: '<li><a href="{url}" title="{desc}">{title}</a><span class="post-meta"><time class="published" datetime="{date}">{date}</time></span></li>',
8+
limit: 15
9+
});
10+
</script>

Diff for: _includes/search.html

-13
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,6 @@ <h1 class="post-title">{{ page.title }}</h1>
77
<input type="text" id="search-input" class="search-field" placeholder="Type your keywords…">
88
<ul id="search-results" class="search-results"></ul>
99
</div>
10-
<script type="text/javascript" src="{{ site.baseurl }}/assets/js/simple-jekyll-search.min.js"></script>
11-
<script type="text/javascript">
12-
window.simpleJekyllSearch = new SimpleJekyllSearch({
13-
searchInput: document.getElementById('search-input'),
14-
resultsContainer: document.getElementById('search-results'),
15-
json: '{{ site.baseurl }}/search.json',
16-
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a><span class="post-meta"><time class="published" datetime="{date}">{date}</time></span> </li>',
17-
noResultsText: 'No results found',
18-
limit: 15,
19-
fuzzy: false,
20-
exclude: ['Welcome']
21-
})
22-
</script>
2310
{% include tag-cloud.html %}
2411
</div><!-- .inner -->
2512
</main><!-- .site-main -->

Diff for: _layouts/default.html

+4-5
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,12 @@
4242
</div><!-- .site-content -->
4343
</div><!-- .site -->
4444
<!-- Javascript Assets -->
45-
<script src="https://code.jquery.com/jquery-3.5.0.min.js"
46-
integrity="sha256-xNzN2a4ltkB44Mc/Jz3pT4iU1cmeR0FkXs4pru/JxaQ="
47-
crossorigin="anonymous"></script>
48-
<script src="{{ site.baseurl }}/assets/js/ao.js"></script>
49-
<script async src="{{ site.baseurl }}/assets/js/custom.js"></script>
45+
<script src="/assets/js/ao.min.js"></script>
46+
<script async src="/assets/js/custom.min.js"></script>
5047
{% if page.layout == 'post' %}
5148
{% include scripts/comments.html %}
49+
{% elsif page.search %}
50+
{% include scripts/search.html %}
5251
{% elsif page.contact %}
5352
{% include scripts/contact.html %}
5453
{% endif %}

Diff for: assets/js/ao-search.js

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
(function (ao) {
2+
'use strict';
3+
4+
var SearchOpts = function () { };
5+
SearchOpts.prototype = {
6+
min: 3,
7+
json: [],
8+
template: '<li><a href="{url}" title="{desc}">{title}</a></li>',
9+
noResults: 'No results found',
10+
limit: 10
11+
};
12+
13+
function isRelevant(key) {
14+
switch (key) {
15+
case 13:
16+
case 16:
17+
case 20:
18+
case 37:
19+
case 38:
20+
case 39:
21+
case 40:
22+
case 91:
23+
return false;
24+
25+
default:
26+
return true;
27+
}
28+
}
29+
30+
var AoSearch = function (userOpts) {
31+
this._ready = false;
32+
this._opts = ao.merge(new SearchOpts(), userOpts);
33+
34+
ao.ajax({
35+
type: 'GET',
36+
url: this._opts.url,
37+
ctx: this,
38+
onSuccess: function (response) {
39+
this._opts.json = response.data;
40+
this._ready = true;
41+
this._search();
42+
}
43+
});
44+
45+
this._input = ao(this._opts.input).keyup(function (evt) {
46+
if (isRelevant(evt.which)) {
47+
this._search();
48+
}
49+
}, this);
50+
51+
this._output = ao(this._opts.output);
52+
};
53+
54+
AoSearch.prototype._search = function () {
55+
if (this._ready === false) { return; }
56+
this._output.clear();
57+
var key = this._input.e.value.trim();
58+
if (Boolean(key) && key.length >= this._opts.min) {
59+
this._render(this._getMatches(key));
60+
}
61+
};
62+
63+
function isMatch(keys, value) {
64+
if (!Boolean(value)) { return false; }
65+
value = value.trim().toLowerCase();
66+
67+
return (keys.filter(function (word) {
68+
return value.indexOf(word) >= 0;
69+
}).length === keys.length);
70+
}
71+
72+
AoSearch.prototype._getMatches = function (key) {
73+
var results = this._opts.json;
74+
var l = results.length;
75+
var limit = this._opts.limit;
76+
var matches = [];
77+
var keys = key.toLowerCase().split(' ');
78+
for (var i = 0; i < l && matches.length <= limit; ++i) {
79+
var result = results[i];
80+
for (var propertyName in result) {
81+
if (result.hasOwnProperty(propertyName) && isMatch(keys, result[propertyName])) {
82+
matches.push(result);
83+
break;
84+
}
85+
}
86+
}
87+
return matches;
88+
};
89+
90+
var placeholderRe = /\{(.*?)\}/g;
91+
92+
function renderResult(match) {
93+
return this._opts.template.replace(placeholderRe, function (_, prop) {
94+
return match[prop] || _;
95+
});
96+
}
97+
98+
AoSearch.prototype._render = function (matches) {
99+
var l = matches.length;
100+
if (l === 0) {
101+
this._output.html(this._opts.noResults);
102+
return;
103+
}
104+
var output = [];
105+
for (var i = 0; i < l; ++i) {
106+
output.push(renderResult.call(this, matches[i]));
107+
}
108+
this._output.html(output.join('\n'));
109+
};
110+
111+
ao.search = function (userOpts) {
112+
return new AoSearch(userOpts);
113+
};
114+
})(Ao);

Diff for: assets/js/ao-search.min.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: assets/js/ao.js

+38-21
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
var Ao = (function () {
2+
'use strict';
3+
24
// Helpers
35
function doNothing() { }
46

@@ -60,21 +62,28 @@
6062
}
6163
};
6264

63-
function registerOrDispatch(eventName, callback) {
65+
function registerOrDispatch(eventName, callback, ctx) {
6466
if (typeof callback === 'function') {
65-
return this.on(eventName, callback);
67+
return this.on(eventName, callback, ctx);
6668
}
6769
this.e.dispatchEvent(new Event(eventName));
6870
return this;
6971
}
7072

7173
AoObj.prototype = {
72-
getByCss: function (selector) {
74+
getByCss: function(selector) {
7375
return this.e.querySelector(selector);
7476
},
75-
getAllByCss: function (selector) {
77+
getAllByCss: function(selector) {
7678
return this.e.querySelectorAll(selector);
7779
},
80+
html: function(updatedHtml) {
81+
if (typeof updatedHtml === 'string') {
82+
this.e.innerHTML = updatedHtml;
83+
return this;
84+
}
85+
return this.e.innerHTML;
86+
},
7887
addClass: function (name) {
7988
return this._do(function (e) {
8089
e.classList.add(name);
@@ -162,11 +171,17 @@
162171
}
163172
});
164173
},
165-
click: function (callback) {
166-
return registerOrDispatch.call(this, 'click', callback);
174+
click: function (callback, ctx) {
175+
return registerOrDispatch.call(this, 'click', callback, ctx);
176+
},
177+
blur: function (callback, ctx) {
178+
return registerOrDispatch.call(this, 'blur', callback, ctx);
179+
},
180+
keyup: function (callback, ctx) {
181+
return registerOrDispatch.call(this, 'keyup', callback, ctx);
167182
},
168-
blur: function (callback) {
169-
return registerOrDispatch.call(this, 'blur', callback);
183+
clear: function() {
184+
return this.html('');
170185
}
171186
};
172187

@@ -201,7 +216,7 @@
201216
if (content.getByCss('.message')) {
202217
this.addClass('with-message');
203218
}
204-
this.e.innerHTML = content.e.innerHTML;
219+
this.html(content.html());
205220
return this;
206221
};
207222

@@ -241,7 +256,7 @@
241256
for (var i = 0, l = this._validators.length; i < l; ++i) {
242257
var validator = this._validators[i];
243258
if (validator.test.call(this) === false) {
244-
this._msg.e.innerHTML = validator.msg;
259+
this._msg.html(validator.msg);
245260
this._msg.removeClass('field-validation-valid').addClass('field-validation-error');
246261
return false;
247262
}
@@ -348,10 +363,7 @@
348363
}
349364

350365
var AjaxOpts = function () { };
351-
AjaxOpts.prototype = {
352-
type: 'GET',
353-
async: true
354-
};
366+
AjaxOpts.prototype = { type: 'GET', async: true };
355367
AjaxOpts.prototype.onFail = doNothing;
356368
AjaxOpts.prototype.onSuccess = doNothing;
357369

@@ -363,19 +375,24 @@
363375
xhr.open(opts.type, opts.url, opts.async);
364376
xhr.onreadystatechange = function () {
365377
if (xhr.readyState === done) {
366-
var response = Boolean(xhr.responseText) ? JSON.parse(xhr.responseText) : {};
367-
response.statusCode = xhr.status;
368-
if (opts.hasOwnProperty('state')) {
369-
response.state = opts.state;
378+
var response = {};
379+
if (Boolean(xhr.responseText)) {
380+
try {
381+
response.data = JSON.parse(xhr.responseText);
382+
} catch (parseErr) {
383+
response.data = xhr.responseText;
384+
}
370385
}
386+
response.statusCode = xhr.status;
387+
var ctx = opts.hasOwnProperty('ctx') ? opts.ctx : null;
371388
if (xhr.status >= 400) {
372-
opts.onFail(response);
389+
opts.onFail.call(ctx, response);
373390
} else {
374391
try {
375-
opts.onSuccess(response);
392+
opts.onSuccess.call(ctx, response);
376393
} catch (err) {
377394
response.error = err;
378-
opts.onFail(response);
395+
opts.onFail.call(ctx, response);
379396
}
380397
}
381398
}

Diff for: assets/js/ao.min.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: assets/js/contact.js

+5-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
(function (ao) {
22
(function (web) {
3+
'use strict';
4+
35
var ContactForm = function () {
46
function contactForm() {
57
this.name = ao.get('contact-form-name');
@@ -26,13 +28,9 @@
2628
type: 'post',
2729
url: form.action,
2830
data: formData,
29-
state: aoForm,
30-
onFail: function(response) {
31-
response.state.error();
32-
},
33-
onSuccess: function(response) {
34-
response.state.ok();
35-
}
31+
ctx: aoForm,
32+
onFail: function() { this.error(); },
33+
onSuccess: function() { this.ok(); }
3634
});
3735

3836
return false;

0 commit comments

Comments
 (0)