mirror of
https://gitee.com/handyorg/HandyControl.git
synced 2024-12-02 11:57:37 +08:00
341 lines
11 KiB
JavaScript
341 lines
11 KiB
JavaScript
/* global NexT, CONFIG */
|
|
|
|
NexT.utils = NexT.$u = {
|
|
|
|
/**
|
|
* Wrap images with fancybox support.
|
|
*/
|
|
wrapImageWithFancyBox: function() {
|
|
$('.content img')
|
|
.not(':hidden')
|
|
.each(function() {
|
|
var $image = $(this);
|
|
var imageTitle = $image.attr('title') || $image.attr('alt');
|
|
var $imageWrapLink = $image.parent('a');
|
|
|
|
if ($imageWrapLink.length < 1) {
|
|
var imageLink = $image.attr('data-original') || $image.attr('src');
|
|
$imageWrapLink = $image.wrap('<a class="fancybox fancybox.image" href="' + imageLink + '" itemscope itemtype="http://schema.org/ImageObject" itemprop="url"></a>').parent('a');
|
|
if ($image.is('.post-gallery img')) {
|
|
$imageWrapLink.addClass('post-gallery-img');
|
|
$imageWrapLink.attr('data-fancybox', 'gallery').attr('rel', 'gallery');
|
|
}
|
|
else if ($image.is('.group-picture img')) {
|
|
$imageWrapLink.attr('data-fancybox', 'group').attr('rel', 'group');
|
|
}
|
|
else {
|
|
$imageWrapLink.attr('data-fancybox', 'default').attr('rel', 'default');
|
|
}
|
|
}
|
|
|
|
if (imageTitle) {
|
|
$imageWrapLink.append('<p class="image-caption">' + imageTitle + '</p>');
|
|
// Make sure img title tag will show correctly in fancybox
|
|
$imageWrapLink.attr('title', imageTitle).attr('data-caption', imageTitle);
|
|
}
|
|
});
|
|
|
|
$('.fancybox').fancybox({
|
|
loop: true,
|
|
helpers: {
|
|
overlay: {
|
|
locked: false
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
lazyLoadPostsImages: function() {
|
|
$('#posts').find('img').lazyload({
|
|
//placeholder: '/images/loading.gif',
|
|
effect : 'fadeIn',
|
|
threshold: 0
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Tabs tag listener (without twitter bootstrap).
|
|
*/
|
|
registerTabsTag: function() {
|
|
var tNav = '.tabs ul.nav-tabs ';
|
|
|
|
// Binding `nav-tabs` & `tab-content` by real time permalink changing.
|
|
$(function() {
|
|
$(window).bind('hashchange', function() {
|
|
var tHash = location.hash;
|
|
if (tHash !== '' && !tHash.match(/%\S{2}/)) {
|
|
$(tNav + 'li:has(a[href="' + tHash + '"])').addClass('active').siblings().removeClass('active');
|
|
$(tHash).addClass('active').siblings().removeClass('active');
|
|
}
|
|
}).trigger('hashchange');
|
|
});
|
|
|
|
$(tNav + '.tab').on('click', function(href) {
|
|
href.preventDefault();
|
|
// Prevent selected tab to select again.
|
|
if (!$(this).hasClass('active')) {
|
|
|
|
// Add & Remove active class on `nav-tabs` & `tab-content`.
|
|
$(this).addClass('active').siblings().removeClass('active');
|
|
var tActive = $(this).find('a').attr('href');
|
|
$(tActive).addClass('active').siblings().removeClass('active');
|
|
|
|
// Clear location hash in browser if #permalink exists.
|
|
if (location.hash !== '') {
|
|
history.pushState('', document.title, window.location.pathname + window.location.search);
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
registerESCKeyEvent: function() {
|
|
$(document).on('keyup', function(event) {
|
|
var shouldDismissSearchPopup = event.which === 27
|
|
&& $('.search-popup').is(':visible');
|
|
if (shouldDismissSearchPopup) {
|
|
$('.search-popup').hide();
|
|
$('.search-popup-overlay').remove();
|
|
$('body').css('overflow', '');
|
|
}
|
|
});
|
|
},
|
|
|
|
registerBackToTop: function() {
|
|
var THRESHOLD = 50;
|
|
var $top = $('.back-to-top');
|
|
|
|
function initBackToTop() {
|
|
$top.toggleClass('back-to-top-on', window.pageYOffset > THRESHOLD);
|
|
|
|
var scrollTop = $(window).scrollTop();
|
|
var contentVisibilityHeight = NexT.utils.getContentVisibilityHeight();
|
|
var scrollPercent = scrollTop / contentVisibilityHeight;
|
|
var scrollPercentRounded = Math.round(scrollPercent * 100);
|
|
var scrollPercentMaxed = scrollPercentRounded > 100 ? 100 : scrollPercentRounded;
|
|
$('#scrollpercent>span').html(scrollPercentMaxed);
|
|
}
|
|
|
|
// For init back to top in sidebar if page was scrolled after page refresh.
|
|
$(window).on('load', function() {
|
|
initBackToTop();
|
|
});
|
|
|
|
$(window).on('scroll', function() {
|
|
initBackToTop();
|
|
});
|
|
|
|
$top.on('click', function() {
|
|
$.isFunction($('html').velocity) ? $('body').velocity('scroll') : $('html, body').animate({ scrollTop: 0 });
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Transform embedded video to support responsive layout.
|
|
* @see http://toddmotto.com/fluid-and-responsive-youtube-and-vimeo-videos-with-fluidvids-js/
|
|
*/
|
|
embeddedVideoTransformer: function() {
|
|
var $iframes = $('iframe');
|
|
|
|
// Supported Players. Extend this if you need more players.
|
|
var SUPPORTED_PLAYERS = [
|
|
'www.youtube.com',
|
|
'player.vimeo.com',
|
|
'player.youku.com',
|
|
'music.163.com',
|
|
'www.tudou.com'
|
|
];
|
|
var pattern = new RegExp(SUPPORTED_PLAYERS.join('|'));
|
|
|
|
function getDimension($element) {
|
|
return {
|
|
width : $element.width(),
|
|
height: $element.height()
|
|
};
|
|
}
|
|
|
|
function getAspectRadio(width, height) {
|
|
return height / width * 100;
|
|
}
|
|
|
|
$iframes.each(function() {
|
|
var iframe = this;
|
|
var $iframe = $(this);
|
|
var oldDimension = getDimension($iframe);
|
|
var newDimension;
|
|
|
|
if (this.src.search(pattern) > 0) {
|
|
|
|
// Calculate the video ratio based on the iframe's w/h dimensions
|
|
var videoRatio = getAspectRadio(oldDimension.width, oldDimension.height);
|
|
|
|
// Replace the iframe's dimensions and position the iframe absolute
|
|
// This is the trick to emulate the video ratio
|
|
$iframe.width('100%').height('100%')
|
|
.css({
|
|
position: 'absolute',
|
|
top : '0',
|
|
left : '0'
|
|
});
|
|
|
|
// Wrap the iframe in a new <div> which uses a dynamically fetched padding-top property
|
|
// based on the video's w/h dimensions
|
|
var wrap = document.createElement('div');
|
|
wrap.className = 'fluid-vids';
|
|
wrap.style.position = 'relative';
|
|
wrap.style.marginBottom = '20px';
|
|
wrap.style.width = '100%';
|
|
wrap.style.paddingTop = videoRatio + '%';
|
|
// Fix for appear inside tabs tag.
|
|
(wrap.style.paddingTop === '') && (wrap.style.paddingTop = '50%');
|
|
|
|
// Add the iframe inside our newly created <div>
|
|
var iframeParent = iframe.parentNode;
|
|
iframeParent.insertBefore(wrap, iframe);
|
|
wrap.appendChild(iframe);
|
|
|
|
// Additional adjustments for 163 Music
|
|
if (this.src.search('music.163.com') > 0) {
|
|
newDimension = getDimension($iframe);
|
|
var shouldRecalculateAspect = newDimension.width > oldDimension.width
|
|
|| newDimension.height < oldDimension.height;
|
|
|
|
// 163 Music Player has a fixed height, so we need to reset the aspect radio
|
|
if (shouldRecalculateAspect) {
|
|
wrap.style.paddingTop = getAspectRadio(newDimension.width, oldDimension.height) + '%';
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
},
|
|
|
|
hasMobileUA: function() {
|
|
var nav = window.navigator;
|
|
var ua = nav.userAgent;
|
|
var pa = /iPad|iPhone|Android|Opera Mini|BlackBerry|webOS|UCWEB|Blazer|PSP|IEMobile|Symbian/g;
|
|
|
|
return pa.test(ua);
|
|
},
|
|
|
|
isTablet: function() {
|
|
return window.screen.width < 992 && window.screen.width > 767 && this.hasMobileUA();
|
|
},
|
|
|
|
isMobile: function() {
|
|
return window.screen.width < 767 && this.hasMobileUA();
|
|
},
|
|
|
|
isDesktop: function() {
|
|
return !this.isTablet() && !this.isMobile();
|
|
},
|
|
|
|
/**
|
|
* Escape meta symbols in jQuery selectors.
|
|
*
|
|
* @param selector
|
|
* @returns {string|void|XML|*}
|
|
*/
|
|
escapeSelector: function(selector) {
|
|
return selector.replace(/[!"$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g, '\\$&');
|
|
},
|
|
|
|
displaySidebar: function() {
|
|
if (!this.isDesktop() || this.isPisces() || this.isGemini()) {
|
|
return;
|
|
}
|
|
$('.sidebar-toggle').trigger('click');
|
|
},
|
|
|
|
isMuse: function() {
|
|
return CONFIG.scheme === 'Muse';
|
|
},
|
|
|
|
isMist: function() {
|
|
return CONFIG.scheme === 'Mist';
|
|
},
|
|
|
|
isPisces: function() {
|
|
return CONFIG.scheme === 'Pisces';
|
|
},
|
|
|
|
isGemini: function() {
|
|
return CONFIG.scheme === 'Gemini';
|
|
},
|
|
|
|
getScrollbarWidth: function() {
|
|
var $div = $('<div />').addClass('scrollbar-measure').prependTo('body');
|
|
var div = $div[0];
|
|
var scrollbarWidth = div.offsetWidth - div.clientWidth;
|
|
$div.remove();
|
|
|
|
return scrollbarWidth;
|
|
},
|
|
|
|
getContentVisibilityHeight: function() {
|
|
var docHeight = $('.container').height();
|
|
var winHeight = $(window).height();
|
|
var contentVisibilityHeight = docHeight > winHeight ? docHeight - winHeight : $(document).height() - winHeight;
|
|
return contentVisibilityHeight;
|
|
},
|
|
|
|
getSidebarb2tHeight: function() {
|
|
var sidebarb2tHeight = (CONFIG.back2top && CONFIG.back2top_sidebar) ? $('.back-to-top').height() : 0;
|
|
return sidebarb2tHeight;
|
|
},
|
|
|
|
getSidebarSchemePadding: function() {
|
|
var sidebarNavHeight = $('.sidebar-nav').css('display') === 'block' ? $('.sidebar-nav').outerHeight(true) : 0;
|
|
var sidebarInner = $('.sidebar-inner');
|
|
var sidebarPadding = sidebarInner.innerWidth() - sidebarInner.width();
|
|
var sidebarOffset = CONFIG.sidebar.offset ? CONFIG.sidebar.offset : 12;
|
|
var sidebarSchemePadding = this.isPisces() || this.isGemini()
|
|
? (sidebarPadding * 2) + sidebarNavHeight + sidebarOffset + this.getSidebarb2tHeight()
|
|
: (sidebarPadding * 2) + (sidebarNavHeight / 2);
|
|
return sidebarSchemePadding;
|
|
}
|
|
};
|
|
|
|
$(document).ready(function() {
|
|
|
|
function wrapTable() {
|
|
$('table').not('figure table').wrap('<div class="table-container"></div>');
|
|
}
|
|
|
|
/**
|
|
* Init Sidebar & TOC inner dimensions on all pages and for all schemes.
|
|
* Need for Sidebar/TOC inner scrolling if content taller then viewport.
|
|
*/
|
|
function updateSidebarHeight(height) {
|
|
height = height || 'auto';
|
|
$('.site-overview, .post-toc').css('max-height', height);
|
|
}
|
|
|
|
function initSidebarDimension() {
|
|
var updateSidebarHeightTimer;
|
|
|
|
$(window).on('resize', function() {
|
|
updateSidebarHeightTimer && clearTimeout(updateSidebarHeightTimer);
|
|
|
|
updateSidebarHeightTimer = setTimeout(function() {
|
|
var sidebarWrapperHeight = document.body.clientHeight - NexT.utils.getSidebarSchemePadding();
|
|
|
|
updateSidebarHeight(sidebarWrapperHeight);
|
|
}, 0);
|
|
});
|
|
|
|
// Initialize Sidebar & TOC Width.
|
|
var scrollbarWidth = NexT.utils.getScrollbarWidth();
|
|
if ($('.site-overview-wrap').height() > (document.body.clientHeight - NexT.utils.getSidebarSchemePadding())) {
|
|
$('.site-overview').css('width', 'calc(100% + ' + scrollbarWidth + 'px)');
|
|
}
|
|
if ($('.post-toc-wrap').height() > (document.body.clientHeight - NexT.utils.getSidebarSchemePadding())) {
|
|
$('.post-toc').css('width', 'calc(100% + ' + scrollbarWidth + 'px)');
|
|
}
|
|
|
|
// Initialize Sidebar & TOC Height.
|
|
updateSidebarHeight(document.body.clientHeight - NexT.utils.getSidebarSchemePadding());
|
|
}
|
|
initSidebarDimension();
|
|
wrapTable();
|
|
});
|