/** * Main */ 'use strict'; let isRtl = window.Helpers.isRtl(), isDarkStyle = window.Helpers.isDarkStyle(), menu, animate, isHorizontalLayout = false; if (document.getElementById('layout-menu')) { isHorizontalLayout = document.getElementById('layout-menu').classList.contains('menu-horizontal'); } (function () { if (typeof Waves !== 'undefined') { Waves.init(); Waves.attach(".btn[class*='btn-']:not([class*='btn-outline-']):not([class*='btn-label-'])", ['waves-light']); Waves.attach("[class*='btn-outline-']"); Waves.attach("[class*='btn-label-']"); Waves.attach('.pagination .page-item .page-link'); } // Initialize menu //----------------- let layoutMenuEl = document.querySelectorAll('#layout-menu'); layoutMenuEl.forEach(function (element) { menu = new Menu(element, { orientation: isHorizontalLayout ? 'horizontal' : 'vertical', closeChildren: isHorizontalLayout ? true : false, // ? This option only works with Horizontal menu showDropdownOnHover: localStorage.getItem('templateCustomizer-' + templateName + '--ShowDropdownOnHover') // If value(showDropdownOnHover) is set in local storage ? localStorage.getItem('templateCustomizer-' + templateName + '--ShowDropdownOnHover') === 'true' // Use the local storage value : window.templateCustomizer !== undefined // If value is set in config.js ? window.templateCustomizer.settings.defaultShowDropdownOnHover // Use the config.js value : true // Use this if you are not using the config.js and want to set value directly from here }); // Change parameter to true if you want scroll animation window.Helpers.scrollToActive((animate = false)); window.Helpers.mainMenu = menu; }); // Initialize menu togglers and bind click on each let menuToggler = document.querySelectorAll('.layout-menu-toggle'); menuToggler.forEach(item => { item.addEventListener('click', event => { event.preventDefault(); window.Helpers.toggleCollapsed(); // Enable menu state with local storage support if enableMenuLocalStorage = true from config.js if (config.enableMenuLocalStorage && !window.Helpers.isSmallScreen()) { try { localStorage.setItem( 'templateCustomizer-' + templateName + '--LayoutCollapsed', String(window.Helpers.isCollapsed()) ); } catch (e) {} } }); }); // Menu swipe gesture // Detect swipe gesture on the target element and call swipe In window.Helpers.swipeIn('.drag-target', function (e) { window.Helpers.setCollapsed(false); }); // Detect swipe gesture on the target element and call swipe Out window.Helpers.swipeOut('#layout-menu', function (e) { if (window.Helpers.isSmallScreen()) window.Helpers.setCollapsed(true); }); // Display in main menu when menu scrolls let menuInnerContainer = document.getElementsByClassName('menu-inner'), menuInnerShadow = document.getElementsByClassName('menu-inner-shadow')[0]; if (menuInnerContainer.length > 0 && menuInnerShadow) { menuInnerContainer[0].addEventListener('ps-scroll-y', function () { if (this.querySelector('.ps__thumb-y').offsetTop) { menuInnerShadow.style.display = 'block'; } else { menuInnerShadow.style.display = 'none'; } }); } // Style Switcher (Light/Dark Mode) //--------------------------------- let styleSwitcherToggleEl = document.querySelector('.style-switcher-toggle'); if (window.templateCustomizer) { // setStyle light/dark on click of styleSwitcherToggleEl if (styleSwitcherToggleEl) { styleSwitcherToggleEl.addEventListener('click', function () { if (window.Helpers.isLightStyle()) { window.templateCustomizer.setStyle('dark'); } else { window.templateCustomizer.setStyle('light'); } }); } // Update style switcher icon and tooltip based on current style if (window.Helpers.isLightStyle()) { if (styleSwitcherToggleEl) { styleSwitcherToggleEl.querySelector('i').classList.add('ti-moon-stars'); new bootstrap.Tooltip(styleSwitcherToggleEl, { title: 'Dark mode', fallbackPlacements: ['bottom'] }); } switchImage('light'); } else { if (styleSwitcherToggleEl) { styleSwitcherToggleEl.querySelector('i').classList.add('ti-sun'); new bootstrap.Tooltip(styleSwitcherToggleEl, { title: 'Light mode', fallbackPlacements: ['bottom'] }); } switchImage('dark'); } } else { // Removed style switcher element if not using template customizer styleSwitcherToggleEl.parentElement.remove(); } // Update light/dark image based on current style function switchImage(style) { const switchImagesList = [].slice.call(document.querySelectorAll('[data-app-' + style + '-img]')); switchImagesList.map(function (imageEl) { const setImage = imageEl.getAttribute('data-app-' + style + '-img'); imageEl.src = assetsPath + 'img/' + setImage; // Using window.assetsPath to get the exact relative path }); } // Internationalization (Language Dropdown) // --------------------------------------- if (typeof i18next !== 'undefined' && typeof i18NextHttpBackend !== 'undefined') { i18next .use(i18NextHttpBackend) .init({ lng: 'en', debug: false, fallbackLng: 'en', backend: { loadPath: assetsPath + 'json/locales/{{lng}}.json' }, returnObjects: true }) .then(function (t) { localize(); }); } let languageDropdown = document.getElementsByClassName('dropdown-language'); if (languageDropdown.length) { let dropdownItems = languageDropdown[0].querySelectorAll('.dropdown-item'); for (let i = 0; i < dropdownItems.length; i++) { dropdownItems[i].addEventListener('click', function () { let currentLanguage = this.getAttribute('data-language'), selectedLangFlag = this.querySelector('.fi').getAttribute('class'); for (let sibling of this.parentNode.children) { sibling.classList.remove('selected'); } this.classList.add('selected'); languageDropdown[0].querySelector('.dropdown-toggle .fi').className = selectedLangFlag; i18next.changeLanguage(currentLanguage, (err, t) => { if (err) return console.log('something went wrong loading', err); localize(); }); }); } } function localize() { let i18nList = document.querySelectorAll('[data-i18n]'); // Set the current language in dd let currentLanguageEle = document.querySelector('.dropdown-item[data-language="' + i18next.language + '"]'); if (currentLanguageEle) { currentLanguageEle.click(); } i18nList.forEach(function (item) { item.innerHTML = i18next.t(item.dataset.i18n); }); } // Notification // ------------ const notificationMarkAsReadAll = document.querySelector('.dropdown-notifications-all'); const notificationMarkAsReadList = document.querySelectorAll('.dropdown-notifications-read'); // Notification: Mark as all as read if (notificationMarkAsReadAll) { notificationMarkAsReadAll.addEventListener('click', event => { notificationMarkAsReadList.forEach(item => { item.closest('.dropdown-notifications-item').classList.add('marked-as-read'); }); }); } // Notification: Mark as read/unread onclick of dot if (notificationMarkAsReadList) { notificationMarkAsReadList.forEach(item => { item.addEventListener('click', event => { item.closest('.dropdown-notifications-item').classList.toggle('marked-as-read'); }); }); } // Notification: Mark as read/unread onclick of dot const notificationArchiveMessageList = document.querySelectorAll('.dropdown-notifications-archive'); notificationArchiveMessageList.forEach(item => { item.addEventListener('click', event => { item.closest('.dropdown-notifications-item').remove(); }); }); // Init helpers & misc // -------------------- // Init BS Tooltip const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')); tooltipTriggerList.map(function (tooltipTriggerEl) { return new bootstrap.Tooltip(tooltipTriggerEl); }); // Accordion active class const accordionActiveFunction = function (e) { if (e.type == 'show.bs.collapse' || e.type == 'show.bs.collapse') { e.target.closest('.accordion-item').classList.add('active'); } else { e.target.closest('.accordion-item').classList.remove('active'); } }; const accordionTriggerList = [].slice.call(document.querySelectorAll('.accordion')); const accordionList = accordionTriggerList.map(function (accordionTriggerEl) { accordionTriggerEl.addEventListener('show.bs.collapse', accordionActiveFunction); accordionTriggerEl.addEventListener('hide.bs.collapse', accordionActiveFunction); }); // If layout is RTL add .dropdown-menu-end class to .dropdown-menu if (isRtl) { Helpers._addClass('dropdown-menu-end', document.querySelectorAll('#layout-navbar .dropdown-menu')); } // Auto update layout based on screen size window.Helpers.setAutoUpdate(true); // Toggle Password Visibility window.Helpers.initPasswordToggle(); // Speech To Text window.Helpers.initSpeechToText(); // Init PerfectScrollbar in Navbar Dropdown (i.e notification) window.Helpers.initNavbarDropdownScrollbar(); // On window resize listener // ------------------------- window.addEventListener( 'resize', function (event) { // Hide open search input and set value blank if (window.innerWidth >= window.Helpers.LAYOUT_BREAKPOINT) { if (document.querySelector('.search-input-wrapper')) { document.querySelector('.search-input-wrapper').classList.add('d-none'); document.querySelector('.search-input').value = ''; } } // Horizontal Layout : Update menu based on window size let horizontalMenuTemplate = document.querySelector("[data-template^='horizontal-menu']"); if (horizontalMenuTemplate) { setTimeout(function () { if (window.innerWidth < window.Helpers.LAYOUT_BREAKPOINT) { if (document.getElementById('layout-menu')) { if (document.getElementById('layout-menu').classList.contains('menu-horizontal')) { menu.switchMenu('vertical'); } } } else { if (document.getElementById('layout-menu')) { if (document.getElementById('layout-menu').classList.contains('menu-vertical')) { menu.switchMenu('horizontal'); } } } }, 100); } }, true ); // Manage menu expanded/collapsed with templateCustomizer & local storage //------------------------------------------------------------------ // If current layout is horizontal OR current window screen is small (overlay menu) than return from here if (isHorizontalLayout || window.Helpers.isSmallScreen()) { return; } // If current layout is vertical and current window screen is > small // Auto update menu collapsed/expanded based on the themeConfig if (typeof TemplateCustomizer !== 'undefined') { if (window.templateCustomizer.settings.defaultMenuCollapsed) { window.Helpers.setCollapsed(true, false); } } // Manage menu expanded/collapsed state with local storage support If enableMenuLocalStorage = true in config.js if (typeof config !== 'undefined') { if (config.enableMenuLocalStorage) { try { if ( localStorage.getItem('templateCustomizer-' + templateName + '--LayoutCollapsed') !== null && localStorage.getItem('templateCustomizer-' + templateName + '--LayoutCollapsed') !== 'false' ) window.Helpers.setCollapsed( localStorage.getItem('templateCustomizer-' + templateName + '--LayoutCollapsed') === 'true', false ); } catch (e) {} } } })(); // ! Removed following code if you do't wish to use jQuery. Remember that navbar search functionality will stop working on removal. if (typeof $ !== 'undefined') { $(function () { // ! TODO: Required to load after DOM is ready, did this now with jQuery ready. window.Helpers.initSidebarToggle(); // Toggle Universal Sidebar // Navbar Search with autosuggest (typeahead) // ? You can remove the following JS if you don't want to use search functionality. //---------------------------------------------------------------------------------- var searchToggler = $('.search-toggler'), searchInputWrapper = $('.search-input-wrapper'), searchInput = $('.search-input'), contentBackdrop = $('.content-backdrop'); // Open search input on click of search icon if (searchToggler.length) { searchToggler.on('click', function () { if (searchInputWrapper.length) { searchInputWrapper.toggleClass('d-none'); searchInput.focus(); } }); } // Open search on 'CTRL+/' $(document).on('keydown', function (event) { let ctrlKey = event.ctrlKey, slashKey = event.which === 191; if (ctrlKey && slashKey) { if (searchInputWrapper.length) { searchInputWrapper.toggleClass('d-none'); searchInput.focus(); } } }); // Todo: Add container-xxl to twitter-typeahead searchInput.on('focus', function () { if (searchInputWrapper.hasClass('container-xxl')) { searchInputWrapper.find('.twitter-typeahead').addClass('container-xxl'); } }); if (searchInput.length) { // Filter config var filterConfig = function (data) { return function findMatches(q, cb) { let matches; matches = []; data.filter(function (i) { if (i.name.toLowerCase().startsWith(q.toLowerCase())) { matches.push(i); } else if ( !i.name.toLowerCase().startsWith(q.toLowerCase()) && i.name.toLowerCase().includes(q.toLowerCase()) ) { matches.push(i); matches.sort(function (a, b) { return b.name < a.name ? 1 : -1; }); } else { return []; } }); cb(matches); }; }; // Search JSON var searchJson = 'search-vertical.json'; // For vertical layout if ($('#layout-menu').hasClass('menu-horizontal')) { var searchJson = 'search-horizontal.json'; // For vertical layout } // Search API AJAX call var searchData = $.ajax({ url: assetsPath + 'json/' + searchJson, //? Use your own search api instead dataType: 'json', async: false }).responseJSON; // Init typeahead on searchInput searchInput.each(function () { var $this = $(this); searchInput .typeahead( { hint: false, classNames: { menu: 'tt-menu navbar-search-suggestion', cursor: 'active', suggestion: 'suggestion d-flex justify-content-between px-3 py-2 w-100' } }, // ? Add/Update blocks as per need // Pages { name: 'pages', display: 'name', limit: 5, source: filterConfig(searchData.pages), templates: { header: '
Pages
', suggestion: function ({ url, icon, name }) { return ( '' + '
' + '' + '' + name + '' + '
' + '
' ); }, notFound: '
' + '
Pages
' + '

No Results Found

' + '
' } }, // Files { name: 'files', display: 'name', limit: 4, source: filterConfig(searchData.files), templates: { header: '
Files
', suggestion: function ({ src, name, subtitle, meta }) { return ( '' + '
' + '' +
                    name +
                    '' + '
' + '
' + name + '
' + '' + subtitle + '' + '
' + '
' + '' + meta + '' + '
' ); }, notFound: '
' + '
Files
' + '

No Results Found

' + '
' } }, // Members { name: 'members', display: 'name', limit: 4, source: filterConfig(searchData.members), templates: { header: '
Members
', suggestion: function ({ name, src, subtitle }) { return ( '' + '
' + '' +
                    name +
                    '' + '' + '
' + '
' ); }, notFound: '
' + '
Members
' + '

No Results Found

' + '
' } } ) //On typeahead result render. .bind('typeahead:render', function () { // Show content backdrop, contentBackdrop.addClass('show').removeClass('fade'); }) // On typeahead select .bind('typeahead:select', function (ev, suggestion) { // Open selected page if (suggestion.url) { window.location = suggestion.url; } }) // On typeahead close .bind('typeahead:close', function () { // Clear search searchInput.val(''); $this.typeahead('val', ''); // Hide search input wrapper searchInputWrapper.addClass('d-none'); // Fade content backdrop contentBackdrop.addClass('fade').removeClass('show'); }); // On searchInput keyup, Fade content backdrop if search input is blank searchInput.on('keyup', function () { if (searchInput.val() == '') { contentBackdrop.addClass('fade').removeClass('show'); } }); }); // Init PerfectScrollbar in search result var psSearch; $('.navbar-search-suggestion').each(function () { psSearch = new PerfectScrollbar($(this)[0], { wheelPropagation: false, suppressScrollX: true }); }); searchInput.on('keyup', function () { psSearch.update(); }); } }); }