nodebb-theme-harmony/public/harmony.js
2025-02-21 18:26:35 -05:00

298 lines
9.2 KiB
JavaScript

'use strict';
$(document).ready(function () {
setupSkinSwitcher();
setupNProgress();
setupMobileMenu();
setupSearch();
setupDrafts();
handleMobileNavigator();
setupNavTooltips();
fixPlaceholders();
fixSidebarOverflow();
function setupSkinSwitcher() {
$('[component="skinSwitcher"]').on('click', '.dropdown-item', function () {
const skin = $(this).attr('data-value');
$('[component="skinSwitcher"] .dropdown-item .fa-check').addClass('invisible');
$(this).find('.fa-check').removeClass('invisible');
require(['forum/account/settings', 'hooks'], function (accountSettings, hooks) {
hooks.one('action:skin.change', function () {
$('[component="skinSwitcher"] [component="skinSwitcher/icon"]').removeClass('fa-fade');
});
$('[component="skinSwitcher"] [component="skinSwitcher/icon"]').addClass('fa-fade');
accountSettings.changeSkin(skin);
});
});
}
require(['hooks'], function (hooks) {
$(window).on('action:composer.resize action:sidebar.toggle', function () {
const isRtl = $('html').attr('data-dir') === 'rtl';
const css = {
width: $('#panel').width(),
};
const sidebarEl = $('.sidebar-left');
css[isRtl ? 'right' : 'left'] = sidebarEl.is(':visible') ? sidebarEl.outerWidth(true) : 0;
$('[component="composer"]').css(css);
});
hooks.on('filter:chat.openChat', function (hookData) {
// disables chat modals & goes straight to chat page based on user setting
hookData.modal = config.theme.chatModals && !utils.isMobile();
return hookData;
});
});
function setupMobileMenu() {
require(['hooks', 'api', 'navigator'], function (hooks, api, navigator) {
$('[component="sidebar/toggle"]').on('click', async function () {
const sidebarEl = $('.sidebar');
sidebarEl.toggleClass('open');
if (app.user.uid) {
await api.put(`/users/${app.user.uid}/settings`, {
settings: {
openSidebars: sidebarEl.hasClass('open') ? 'on' : 'off',
},
});
}
$(window).trigger('action:sidebar.toggle');
if (ajaxify.data.template.topic) {
hooks.fire('action:navigator.update', { newIndex: navigator.getIndex() });
}
});
const bottomBar = $('[component="bottombar"]');
let stickyTools = null;
const location = config.theme.topMobilebar ? 'top' : 'bottom';
const $body = $('body');
const $window = $(window);
$body.on('shown.bs.dropdown hidden.bs.dropdown', '.sticky-tools', function () {
bottomBar.toggleClass('hidden', $(this).find('.dropdown-menu.show').length);
});
function isSearchVisible() {
return !!$('[component="bottombar"] [component="sidebar/search"] .search-dropdown.show').length;
}
let lastScrollTop = $window.scrollTop();
let newPostsLoaded = false;
function onWindowScroll() {
const st = $window.scrollTop();
if (newPostsLoaded) {
newPostsLoaded = false;
lastScrollTop = st;
return;
}
if (st !== lastScrollTop && !navigator.scrollActive && !isSearchVisible()) {
const diff = Math.abs(st - lastScrollTop);
const scrolledDown = st > lastScrollTop;
const scrolledUp = st < lastScrollTop;
const isHiding = !scrolledUp && scrolledDown;
if (diff > 10) {
bottomBar.css({
[location]: isHiding ?
-bottomBar.find('.bottombar-nav').outerHeight(true) :
0,
});
if (stickyTools && config.theme.topMobilebar && config.theme.autohideBottombar) {
stickyTools.css({
top: isHiding ? 0 : 'var(--panel-offset)',
});
}
}
}
lastScrollTop = st;
}
const delayedScroll = utils.throttle(onWindowScroll, 250);
function enableAutohide() {
$window.off('scroll', delayedScroll);
if (config.theme.autohideBottombar) {
lastScrollTop = $window.scrollTop();
$window.on('scroll', delayedScroll);
}
}
hooks.on('action:posts.loading', function () {
$window.off('scroll', delayedScroll);
});
hooks.on('action:posts.loaded', function () {
newPostsLoaded = true;
setTimeout(enableAutohide, 250);
});
hooks.on('action:ajaxify.end', function () {
bottomBar.removeClass('hidden');
const { template } = ajaxify.data;
stickyTools = (template.category || template.topic) ? $('.sticky-tools') : null;
$window.off('scroll', delayedScroll);
if (config.theme.autohideBottombar) {
bottomBar.css({ [location]: 0 });
setTimeout(enableAutohide, 250);
}
});
});
}
function setupSearch() {
$('[component="sidebar/search"]').on('shown.bs.dropdown', function () {
$(this).find('[component="search/fields"] input[name="query"]').trigger('focus');
});
}
function setupDrafts() {
require(['composer/drafts', 'bootbox'], function (drafts, bootbox) {
const draftsEl = $('[component="sidebar/drafts"]');
function updateBadgeCount() {
const count = drafts.getAvailableCount();
if (count > 0) {
draftsEl.removeClass('hidden');
}
$('[component="drafts/count"]').toggleClass('hidden', count <= 0).text(count);
}
async function renderDraftList() {
const draftListEl = $('[component="drafts/list"]');
const draftItems = drafts.listAvailable();
if (!draftItems.length) {
draftListEl.find('.no-drafts').removeClass('hidden');
draftListEl.find('.placeholder-wave').addClass('hidden');
draftListEl.find('.draft-item-container').html('');
return;
}
draftItems.reverse().forEach((draft) => {
if (draft) {
if (draft.title) {
draft.title = utils.escapeHTML(String(draft.title));
}
draft.text = utils.escapeHTML(
draft.text
).replace(/(?:\r\n|\r|\n)/g, '<br>');
}
});
const html = await app.parseAndTranslate('partials/sidebar/drafts', 'drafts', { drafts: draftItems });
draftListEl.find('.no-drafts').addClass('hidden');
draftListEl.find('.placeholder-wave').addClass('hidden');
draftListEl.find('.draft-item-container').html(html).find('.timeago').timeago();
}
draftsEl.on('shown.bs.dropdown', renderDraftList);
draftsEl.on('click', '[component="drafts/open"]', function () {
drafts.open($(this).attr('data-save-id'));
});
draftsEl.on('click', '[component="drafts/delete"]', function () {
const save_id = $(this).attr('data-save-id');
bootbox.confirm('[[modules:composer.discard-draft-confirm]]', function (ok) {
if (ok) {
drafts.removeDraft(save_id);
renderDraftList();
}
});
return false;
});
$(window).on('action:composer.drafts.save', updateBadgeCount);
$(window).on('action:composer.drafts.remove', updateBadgeCount);
updateBadgeCount();
});
}
function setupNProgress() {
require(['nprogress'], function (NProgress) {
window.nprogress = NProgress;
if (NProgress) {
$(window).on('action:ajaxify.start', function () {
NProgress.set(0.7);
});
$(window).on('action:ajaxify.end', function () {
NProgress.done(true);
});
}
});
}
function handleMobileNavigator() {
const paginationBlockEl = $('.pagination-block');
require(['hooks'], function (hooks) {
hooks.on('action:ajaxify.end', function () {
paginationBlockEl.find('.dropdown-menu.show').removeClass('show');
});
hooks.on('filter:navigator.scroll', function (hookData) {
paginationBlockEl.find('.dropdown-menu.show').removeClass('show');
return hookData;
});
});
}
function setupNavTooltips() {
// remove title from user icon in sidebar to prevent double tooltip
$('.sidebar [component="header/avatar"] .avatar').removeAttr('title');
const tooltipEls = $('.sidebar [title]');
const lefttooltipEls = $('.sidebar-left [title]');
const rightooltipEls = $('.sidebar-right [title]');
const isRtl = $('html').attr('data-dir') === 'rtl';
lefttooltipEls.tooltip({
trigger: 'manual',
animation: false,
placement: isRtl ? 'left' : 'right',
});
rightooltipEls.tooltip({
trigger: 'manual',
animation: false,
placement: isRtl ? 'right' : 'left',
});
tooltipEls.on('mouseenter', function (ev) {
const target = $(ev.target);
const isDropdown = target.hasClass('dropdown-menu') || !!target.parents('.dropdown-menu').length;
if (!$('.sidebar').hasClass('open') && !isDropdown) {
$(this).tooltip('show');
}
});
tooltipEls.on('click mouseleave', function () {
$(this).tooltip('hide');
});
}
function fixPlaceholders() {
if (!config.loggedIn) {
return;
}
['notifications', 'chat'].forEach((type) => {
const countEl = $(`nav.sidebar [component="${type}/count"]`).first();
if (!countEl.length) {
return;
}
const count = parseInt(countEl.text(), 10);
if (count > 1) {
const listEls = $(`.dropdown-menu [component="${type}/list"]`);
listEls.each((index, el) => {
const placeholder = $(el).children().first();
for (let x = 0; x < count - 1; x++) {
const cloneEl = placeholder.clone(true);
cloneEl.insertAfter(placeholder);
}
});
}
});
}
function fixSidebarOverflow() {
// overflow-y-auto needs to be removed on main-nav when dropdowns are opened
const mainNavEl = $('#main-nav');
function toggleOverflow() {
mainNavEl.toggleClass(
'overflow-y-auto',
!mainNavEl.find('.dropdown-menu.show').length
);
}
mainNavEl.on('shown.bs.dropdown', toggleOverflow)
.on('hidden.bs.dropdown', toggleOverflow);
}
});