Initial website
This commit is contained in:
240
themes/hueman/source/js/insight.js
Normal file
240
themes/hueman/source/js/insight.js
Normal file
@@ -0,0 +1,240 @@
|
||||
/**
|
||||
* Insight search plugin
|
||||
* @author PPOffice { @link https://github.com/ppoffice }
|
||||
*/
|
||||
(function ($, CONFIG) {
|
||||
var $main = $('.ins-search');
|
||||
var $input = $main.find('.ins-search-input');
|
||||
var $wrapper = $main.find('.ins-section-wrapper');
|
||||
var $container = $main.find('.ins-section-container');
|
||||
$main.parent().remove('.ins-search');
|
||||
$('body').append($main);
|
||||
|
||||
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 != null && title != '' ? title : CONFIG.TRANSLATION['UNTITLED'])
|
||||
.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;
|
||||
sectionTitle = CONFIG.TRANSLATION[type];
|
||||
switch (type) {
|
||||
case 'POSTS':
|
||||
case '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_URL + item.path);
|
||||
});
|
||||
break;
|
||||
case 'CATEGORIES':
|
||||
case '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]));
|
||||
}
|
||||
}
|
||||
|
||||
function scrollTo ($item) {
|
||||
if ($item.length === 0) return;
|
||||
var wrapperHeight = $wrapper[0].clientHeight;
|
||||
var itemTop = $item.position().top - $wrapper.scrollTop();
|
||||
var itemBottom = $item[0].clientHeight + $item.position().top;
|
||||
if (itemBottom > wrapperHeight + $wrapper.scrollTop()) {
|
||||
$wrapper.scrollTop(itemBottom - $wrapper[0].clientHeight);
|
||||
}
|
||||
if (itemTop < 0) {
|
||||
$wrapper.scrollTop($item.position().top);
|
||||
}
|
||||
}
|
||||
|
||||
function selectItemByDiff (value) {
|
||||
var $items = $.makeArray($container.find('.ins-selectable'));
|
||||
var prevPosition = -1;
|
||||
$items.forEach(function (item, index) {
|
||||
if ($(item).hasClass('active')) {
|
||||
prevPosition = index;
|
||||
return;
|
||||
}
|
||||
});
|
||||
var nextPosition = ($items.length + prevPosition + value) % $items.length;
|
||||
$($items[prevPosition]).removeClass('active');
|
||||
$($items[nextPosition]).addClass('active');
|
||||
scrollTo($($items[nextPosition]));
|
||||
}
|
||||
|
||||
function gotoLink ($item) {
|
||||
if ($item && $item.length) {
|
||||
location.href = $item.attr('data-url');
|
||||
}
|
||||
}
|
||||
|
||||
$.getJSON(CONFIG.CONTENT_URL, function (json) {
|
||||
if (location.hash.trim() === '#ins-search') {
|
||||
$main.addClass('show');
|
||||
}
|
||||
$input.on('input', function () {
|
||||
var keywords = $(this).val();
|
||||
searchResultToDOM(search(json, keywords));
|
||||
});
|
||||
$input.trigger('input');
|
||||
});
|
||||
|
||||
|
||||
$(document).on('click focus', '.search-form-input', function () {
|
||||
$main.addClass('show');
|
||||
$main.find('.ins-search-input').focus();
|
||||
}).on('click', '.ins-search-item', function () {
|
||||
gotoLink($(this));
|
||||
}).on('click', '.ins-close', function () {
|
||||
$main.removeClass('show');
|
||||
}).on('keydown', function (e) {
|
||||
if (!$main.hasClass('show')) return;
|
||||
switch (e.keyCode) {
|
||||
case 27: // ESC
|
||||
$main.removeClass('show'); break;
|
||||
case 38: // UP
|
||||
selectItemByDiff(-1); break;
|
||||
case 40: // DOWN
|
||||
selectItemByDiff(1); break;
|
||||
case 13: //ENTER
|
||||
gotoLink($container.find('.ins-selectable.active').eq(0)); break;
|
||||
}
|
||||
});
|
||||
})(jQuery, window.INSIGHT_CONFIG);
|
136
themes/hueman/source/js/main.js
Normal file
136
themes/hueman/source/js/main.js
Normal file
@@ -0,0 +1,136 @@
|
||||
(function ($) {
|
||||
// To top button
|
||||
$("#back-to-top").on('click', function () {
|
||||
$('body, html').animate({ scrollTop: 0 }, 600);
|
||||
});
|
||||
|
||||
// Nav bar toggle
|
||||
$('#main-nav-toggle').on('click', function () {
|
||||
$('.nav-container-inner').slideToggle();
|
||||
});
|
||||
|
||||
// Caption
|
||||
$('.article-entry').each(function(i) {
|
||||
$(this).find('img').each(function() {
|
||||
if (this.alt && !(!!$.prototype.justifiedGallery && $(this).parent('.justified-gallery').length)) {
|
||||
$(this).after('<span class="caption">' + this.alt + '</span>');
|
||||
}
|
||||
|
||||
// 对于已经包含在链接内的图片不适用lightGallery
|
||||
if ($(this).parent().prop("tagName") !== 'A') {
|
||||
$(this).wrap('<a href="' + this.src + '" title="' + this.alt + '" class="gallery-item"></a>');
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
if (typeof lightGallery != 'undefined') {
|
||||
var options = {
|
||||
selector: '.gallery-item',
|
||||
};
|
||||
$('.article-entry').each(function(i, entry) {
|
||||
lightGallery(entry, options);
|
||||
});
|
||||
lightGallery($('.article-gallery')[0], options);
|
||||
}
|
||||
if (!!$.prototype.justifiedGallery) { // if justifiedGallery method is defined
|
||||
var options = {
|
||||
rowHeight: 140,
|
||||
margins: 4,
|
||||
lastRow: 'justify'
|
||||
};
|
||||
$('.justified-gallery').justifiedGallery(options);
|
||||
}
|
||||
|
||||
// Sidebar expend
|
||||
$('#sidebar .sidebar-toggle').on('click', function () {
|
||||
if($('#sidebar').hasClass('expend')) {
|
||||
$('#sidebar').removeClass('expend');
|
||||
} else {
|
||||
$('#sidebar').addClass('expend');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Remove extra main nav wrap
|
||||
$('.main-nav-list > li').unwrap();
|
||||
|
||||
// Highlight current nav item
|
||||
$('#main-nav > li > .main-nav-list-link').each(function () {
|
||||
if($('.page-title-link').length > 0){
|
||||
if ($(this).html().toUpperCase() == $('.page-title-link').html().toUpperCase()) {
|
||||
$(this).addClass('current');
|
||||
} else if ($(this).attr('href') == $('.page-title-link').attr('data-url')) {
|
||||
$(this).addClass('current');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Auto hide main nav menus
|
||||
function autoHideMenus(){
|
||||
var max_width = $('.nav-container-inner').width() - 10;
|
||||
var main_nav_width = $('#main-nav').width();
|
||||
var sub_nav_width = $('#sub-nav').width();
|
||||
if (main_nav_width + sub_nav_width > max_width) {
|
||||
// If more link not exists
|
||||
if ($('.main-nav-more').length == 0) {
|
||||
$(['<li class="main-nav-list-item top-level-menu main-nav-more">',
|
||||
'<a class="main-nav-list-link" href="javascript:;">More</a>',
|
||||
'<ul class="main-nav-list-child">',
|
||||
'</ul></li>'].join('')).appendTo($('#main-nav'));
|
||||
// Bind hover event
|
||||
$('.main-nav-more').hover(function () {
|
||||
if($(window).width() < 480) {
|
||||
return;
|
||||
}
|
||||
$(this).children('.main-nav-list-child').slideDown('fast');
|
||||
}, function () {
|
||||
if($(window).width() < 480) {
|
||||
return;
|
||||
}
|
||||
$(this).children('.main-nav-list-child').slideUp('fast');
|
||||
});
|
||||
}
|
||||
var child_count = $('#main-nav').children().length;
|
||||
for (var i = child_count - 2; i >= 0; i--) {
|
||||
var element = $('#main-nav').children().eq(i);
|
||||
if (main_nav_width + sub_nav_width > max_width) {
|
||||
element.prependTo($('.main-nav-more > ul'));
|
||||
main_nav_width = $('#main-nav').width();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Nav bar is wide enough
|
||||
if ($('.main-nav-more').length > 0) {
|
||||
$('.main-nav-more > ul').children().appendTo($('#main-nav'));
|
||||
$('.main-nav-more').remove();
|
||||
}
|
||||
}
|
||||
autoHideMenus();
|
||||
|
||||
$(window).on('resize', function () {
|
||||
autoHideMenus();
|
||||
});
|
||||
|
||||
// Fold second-level menu
|
||||
$('.main-nav-list-item').hover(function () {
|
||||
if ($(window).width() < 480) {
|
||||
return;
|
||||
}
|
||||
$(this).children('.main-nav-list-child').slideDown('fast');
|
||||
}, function () {
|
||||
if ($(window).width() < 480) {
|
||||
return;
|
||||
}
|
||||
$(this).children('.main-nav-list-child').slideUp('fast');
|
||||
});
|
||||
|
||||
// Add second-level menu mark
|
||||
$('.main-nav-list-item').each(function () {
|
||||
if ($(this).find('.main-nav-list-child').length > 0) {
|
||||
$(this).addClass('top-level-menu');
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
Reference in New Issue
Block a user