|
@@ -11,192 +11,19 @@
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
<script>
|
|
- (function ($) {
|
|
|
|
- $main = $('.ins-search');
|
|
|
|
- $container = $('.ins-section-container');
|
|
|
|
- $main.parent().remove('.ins-search');
|
|
|
|
- $('body').append($main);
|
|
|
|
-
|
|
|
|
- $(document).on('click focus', '.search-form-input', function () {
|
|
|
|
- $main.addClass('show');
|
|
|
|
- $main.find('.ins-search-input').focus();
|
|
|
|
- }).on('click', '.ins-search-item', function () {
|
|
|
|
- location.href=$(this).attr('data-url');
|
|
|
|
- }).on('click', '.ins-close', function () {
|
|
|
|
- $main.removeClass('show');
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- function section (title) {
|
|
|
|
- return $('<section>').addClass('ins-section')
|
|
|
|
- .append($('<header>').addClass('ins-section-header').text(title));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- function searchItem (icon, title, slug, preview, url) {
|
|
|
|
- return $('<div>').addClass('ins-selectable').addClass('ins-search-item')
|
|
|
|
- .append($('<header>').append($('<i>').addClass('fa').addClass('fa-' + icon)).append(title)
|
|
|
|
- .append(slug ? $('<span>').addClass('ins-slug').text(slug) : null))
|
|
|
|
- .append(preview ? $('<p>').addClass('ins-search-preview').text(preview) : null)
|
|
|
|
- .attr('data-url', url);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- function sectionFactory (type, array) {
|
|
|
|
- var sectionTitle;
|
|
|
|
- var $searchItems;
|
|
|
|
- if (array.length == 0) return null;
|
|
|
|
- switch (type) {
|
|
|
|
- case 'POSTS':
|
|
|
|
- case 'PAGES':
|
|
|
|
- sectionTitle = type == 'POSTS' ? '<%= __("insight.posts") %>' : '<%= __("insight.pages") %>';
|
|
|
|
- $searchItems = array.map(function (item) {
|
|
|
|
- // Use config.root instead of permalink to fix url issue
|
|
|
|
- return searchItem('file', item.title, null, item.text.slice(0, 150), '<%= config.root %>' + item.path);
|
|
|
|
- });
|
|
|
|
- break;
|
|
|
|
- case 'CATEGORIES':
|
|
|
|
- case 'TAGS':
|
|
|
|
- sectionTitle = type == 'CATEGORIES' ? '<%= __("insight.categories") %>' : '<%= __("insight.tags") %>';
|
|
|
|
- $searchItems = array.map(function (item) {
|
|
|
|
- return searchItem(type == 'CATEGORIES' ? 'folder' : 'tag', item.name, item.slug, null, item.permalink);
|
|
|
|
- });
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- return null;
|
|
|
|
- }
|
|
|
|
- return section(sectionTitle).append($searchItems);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- function extractToSet (json, key) {
|
|
|
|
- var values = {};
|
|
|
|
- var entries = json.pages.concat(json.posts);
|
|
|
|
- entries.forEach(function (entry) {
|
|
|
|
- if (entry[key]) {
|
|
|
|
- entry[key].forEach(function (value) {
|
|
|
|
- values[value.name] = value;
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
- var result = [];
|
|
|
|
- for (var key in values) {
|
|
|
|
- result.push(values[key]);
|
|
|
|
- }
|
|
|
|
- return result;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- function parseKeywords (keywords) {
|
|
|
|
- return keywords.split(' ').filter(function (keyword) {
|
|
|
|
- return !!keyword;
|
|
|
|
- }).map(function (keyword) {
|
|
|
|
- return keyword.toUpperCase();
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Judge if a given post/page/category/tag contains all of the keywords.
|
|
|
|
- * @param Object obj Object to be weighted
|
|
|
|
- * @param Array<String> fields Object's fields to find matches
|
|
|
|
- */
|
|
|
|
- function filter (keywords, obj, fields) {
|
|
|
|
- var result = false;
|
|
|
|
- var keywordArray = parseKeywords(keywords);
|
|
|
|
- var containKeywords = keywordArray.filter(function (keyword) {
|
|
|
|
- var containFields = fields.filter(function (field) {
|
|
|
|
- if (!obj.hasOwnProperty(field))
|
|
|
|
- return false;
|
|
|
|
- if (obj[field].toUpperCase().indexOf(keyword) > -1)
|
|
|
|
- return true;
|
|
|
|
- });
|
|
|
|
- if (containFields.length > 0)
|
|
|
|
- return true;
|
|
|
|
- return false;
|
|
|
|
- });
|
|
|
|
- return containKeywords.length == keywordArray.length;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- function filterFactory (keywords) {
|
|
|
|
- return {
|
|
|
|
- POST: function (obj) {
|
|
|
|
- return filter(keywords, obj, ['title', 'text']);
|
|
|
|
- },
|
|
|
|
- PAGE: function (obj) {
|
|
|
|
- return filter(keywords, obj, ['title', 'text']);
|
|
|
|
- },
|
|
|
|
- CATEGORY: function (obj) {
|
|
|
|
- return filter(keywords, obj, ['name', 'slug']);
|
|
|
|
- },
|
|
|
|
- TAG: function (obj) {
|
|
|
|
- return filter(keywords, obj, ['name', 'slug']);
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Calculate the weight of a matched post/page/category/tag.
|
|
|
|
- * @param Object obj Object to be weighted
|
|
|
|
- * @param Array<String> fields Object's fields to find matches
|
|
|
|
- * @param Array<Integer> weights Weight of every field
|
|
|
|
- */
|
|
|
|
- function weight (keywords, obj, fields, weights) {
|
|
|
|
- var value = 0;
|
|
|
|
- parseKeywords(keywords).forEach(function (keyword) {
|
|
|
|
- var pattern = new RegExp(keyword, 'img'); // Global, Multi-line, Case-insensitive
|
|
|
|
- fields.forEach(function (field, index) {
|
|
|
|
- if (obj.hasOwnProperty(field)) {
|
|
|
|
- var matches = obj[field].match(pattern);
|
|
|
|
- value += matches ? matches.length * weights[index] : 0;
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
- });
|
|
|
|
- return value;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- function weightFactory (keywords) {
|
|
|
|
- return {
|
|
|
|
- POST: function (obj) {
|
|
|
|
- return weight(keywords, obj, ['title', 'text'], [3, 1]);
|
|
|
|
- },
|
|
|
|
- PAGE: function (obj) {
|
|
|
|
- return weight(keywords, obj, ['title', 'text'], [3, 1]);
|
|
|
|
- },
|
|
|
|
- CATEGORY: function (obj) {
|
|
|
|
- return weight(keywords, obj, ['name', 'slug'], [1, 1]);
|
|
|
|
- },
|
|
|
|
- TAG: function (obj) {
|
|
|
|
- return weight(keywords, obj, ['name', 'slug'], [1, 1]);
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- function search (json, keywords) {
|
|
|
|
- var WEIGHTS = weightFactory(keywords);
|
|
|
|
- var FILTERS = filterFactory(keywords);
|
|
|
|
- var posts = json.posts;
|
|
|
|
- var pages = json.pages;
|
|
|
|
- var tags = extractToSet(json, 'tags');
|
|
|
|
- var categories = extractToSet(json, 'categories');
|
|
|
|
- return {
|
|
|
|
- posts: posts.filter(FILTERS.POST).sort(function (a, b) { return WEIGHTS.POST(b) - WEIGHTS.POST(a); }).slice(0, 5),
|
|
|
|
- pages: pages.filter(FILTERS.PAGE).sort(function (a, b) { return WEIGHTS.PAGE(b) - WEIGHTS.PAGE(a); }).slice(0, 5),
|
|
|
|
- categories: categories.filter(FILTERS.CATEGORY).sort(function (a, b) { return WEIGHTS.CATEGORY(b) - WEIGHTS.CATEGORY(a); }).slice(0, 5),
|
|
|
|
- tags: tags.filter(FILTERS.TAG).sort(function (a, b) { return WEIGHTS.TAG(b) - WEIGHTS.TAG(a); }).slice(0, 5)
|
|
|
|
- };
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- function searchResultToDOM (searchResult) {
|
|
|
|
- $container.empty();
|
|
|
|
- for (var key in searchResult) {
|
|
|
|
- $container.append(sectionFactory(key.toUpperCase(), searchResult[key]));
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- $.getJSON('<%- url_for("/content.json")%>', function (json) {
|
|
|
|
- if (location.hash.trim() == '#ins-search') {
|
|
|
|
- $main.addClass('show');
|
|
|
|
- }
|
|
|
|
- $('.ins-search-input').on('input', function () {
|
|
|
|
- var keywords = $(this).val();
|
|
|
|
- searchResultToDOM(search(json, keywords));
|
|
|
|
- });
|
|
|
|
- $('.ins-search-input').trigger('input');
|
|
|
|
- });
|
|
|
|
- })(jQuery);
|
|
|
|
-</script>
|
|
|
|
|
|
+(function (window) {
|
|
|
|
+ var INSIGHT_CONFIG = {
|
|
|
|
+ TRANSLATION: {
|
|
|
|
+ POSTS: '<%= __("insight.posts") %>',
|
|
|
|
+ PAGES: '<%= __("insight.pages") %>',
|
|
|
|
+ CATEGORIES: '<%= __("insight.categories") %>',
|
|
|
|
+ TAGS: '<%= __("insight.tags") %>',
|
|
|
|
+ UNTITLED: '<%= __("insight.untitled") %>',
|
|
|
|
+ },
|
|
|
|
+ ROOT_URL: '<%= config.root %>',
|
|
|
|
+ CONTENT_URL: '<%- url_for("/content.json")%>',
|
|
|
|
+ };
|
|
|
|
+ window.INSIGHT_CONFIG = INSIGHT_CONFIG;
|
|
|
|
+})(window);
|
|
|
|
+</script>
|
|
|
|
+<%- js('js/insight') %>
|