259 lines
8.9 KiB
JavaScript
259 lines
8.9 KiB
JavaScript
/* Template Name: LotusLabs Docs
|
|
Author: Colin Wilson
|
|
E-mail: colin@aigis.uk
|
|
Created: October 2022
|
|
Version: 1.0.0
|
|
File Description: Main JS file of the docs template
|
|
*/
|
|
|
|
|
|
/*********************************/
|
|
/* INDEX */
|
|
/*================================
|
|
* 01. Toggle Menus *
|
|
* 02. Active Menu *
|
|
* 03. Clickable Menu *
|
|
* 04. Back to top *
|
|
* 05. DD Menu *
|
|
* 06. Active Sidebar Menu *
|
|
* 07. ScrollSpy *
|
|
================================*/
|
|
|
|
|
|
// Menu
|
|
// Toggle menu
|
|
function toggleMenu() {
|
|
document.getElementById('isToggle').classList.toggle('open');
|
|
var isOpen = document.getElementById('navigation')
|
|
if (isOpen.style.display === "block") {
|
|
isOpen.style.display = "none";
|
|
} else {
|
|
isOpen.style.display = "block";
|
|
}
|
|
};
|
|
|
|
// Menu Active
|
|
function getClosest(elem, selector) {
|
|
|
|
// Element.matches() polyfill
|
|
if (!Element.prototype.matches) {
|
|
Element.prototype.matches =
|
|
Element.prototype.matchesSelector ||
|
|
Element.prototype.mozMatchesSelector ||
|
|
Element.prototype.msMatchesSelector ||
|
|
Element.prototype.oMatchesSelector ||
|
|
Element.prototype.webkitMatchesSelector ||
|
|
function (s) {
|
|
var matches = (this.document || this.ownerDocument).querySelectorAll(s),
|
|
i = matches.length;
|
|
while (--i >= 0 && matches.item(i) !== this) { }
|
|
return i > -1;
|
|
};
|
|
}
|
|
|
|
// Get the closest matching element
|
|
for (; elem && elem !== document; elem = elem.parentNode) {
|
|
if (elem.matches(selector)) return elem;
|
|
}
|
|
return null;
|
|
|
|
};
|
|
|
|
function activateMenu() {
|
|
var menuItems = document.getElementsByClassName("sub-menu-item");
|
|
if (menuItems) {
|
|
|
|
var matchingMenuItem = null;
|
|
for (var idx = 0; idx < menuItems.length; idx++) {
|
|
if (menuItems[idx].href === window.location.href) {
|
|
matchingMenuItem = menuItems[idx];
|
|
}
|
|
}
|
|
|
|
if (matchingMenuItem) {
|
|
matchingMenuItem.classList.add('active');
|
|
var immediateParent = getClosest(matchingMenuItem, 'li');
|
|
if (immediateParent) {
|
|
immediateParent.classList.add('active');
|
|
}
|
|
|
|
var parent = getClosest(matchingMenuItem, '.parent-menu-item');
|
|
if (parent) {
|
|
parent.classList.add('active');
|
|
var parentMenuitem = parent.querySelector('.menu-item');
|
|
if (parentMenuitem) {
|
|
parentMenuitem.classList.add('active');
|
|
}
|
|
var parentOfParent = getClosest(parent, '.parent-parent-menu-item');
|
|
if (parentOfParent) {
|
|
parentOfParent.classList.add('active');
|
|
}
|
|
} else {
|
|
var parentOfParent = getClosest(matchingMenuItem, '.parent-parent-menu-item');
|
|
if (parentOfParent) {
|
|
parentOfParent.classList.add('active');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Sidebar Menu
|
|
function activateSidebarMenu() {
|
|
var current = location.pathname.substring(location.pathname.lastIndexOf('/') + 1);
|
|
if (current !== "" && document.getElementById("sidebar")) {
|
|
var menuItems = document.querySelectorAll('#sidebar button');
|
|
for (var i = 0, len = menuItems.length; i < len; i++) {
|
|
if (menuItems[i].getAttribute("href").indexOf(current) !== -1) {
|
|
menuItems[i].parentElement.className += " active";
|
|
if (menuItems[i].closest(".sidebar-submenu")) {
|
|
menuItems[i].closest(".sidebar-submenu").classList.add("d-block");
|
|
}
|
|
if (menuItems[i].closest(".sidebar-dropdown")) {
|
|
menuItems[i].closest(".sidebar-dropdown").classList.add("active");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (document.getElementById("close-sidebar")) {
|
|
document.getElementById("close-sidebar").addEventListener("click", function () {
|
|
document.getElementsByClassName("page-wrapper")[0].classList.toggle("toggled");
|
|
});
|
|
}
|
|
|
|
// Close Sidebar (mobile)
|
|
if (!window.matchMedia('(min-width: 1024px)').matches) {
|
|
if (document.getElementById("close-sidebar")) {
|
|
const closeSidebar = document.getElementById("close-sidebar");
|
|
const sidebar = document.getElementById("sidebar");
|
|
const sidebarMenuLinks = Array.from(document.querySelectorAll(".sidebar-root-link,.sidebar-nested-link"));
|
|
// Close sidebar by clicking outside
|
|
document.addEventListener('click', function(elem) {
|
|
if (!closeSidebar.contains(elem.target) && !sidebar.contains(elem.target))
|
|
document.getElementsByClassName("page-wrapper")[0].classList.add("toggled");
|
|
});
|
|
// Close sidebar immediately when clicking sidebar menu item
|
|
sidebarMenuLinks.forEach(menuLink => {
|
|
menuLink.addEventListener("click", function () {
|
|
document.getElementsByClassName("page-wrapper")[0].classList.add("toggled");
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
// Clickable Menu
|
|
if (document.getElementById("navigation")) {
|
|
var elements = document.getElementById("navigation").getElementsByTagName("a");
|
|
for (var i = 0, len = elements.length; i < len; i++) {
|
|
elements[i].onclick = function (elem) {
|
|
if (elem.target.getAttribute("href") === "javascript:void(0)") {
|
|
var submenu = elem.target.nextElementSibling.nextElementSibling;
|
|
submenu.classList.toggle('open');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (document.getElementById("sidebar")) {
|
|
var elements = document.getElementById("sidebar").getElementsByTagName("button");
|
|
for (var i = 0, len = elements.length; i < len; i++) {
|
|
elements[i].onclick = function (elem) {
|
|
// if(elem.target !== document.querySelectorAll("li.sidebar-dropdown.active > a")[0]){
|
|
// document.querySelectorAll("li.sidebar-dropdown.active")[0]?.classList?.toggle("active");
|
|
// document.querySelectorAll("div.sidebar-submenu.d-block")[0]?.classList?.toggle("d-block");
|
|
// }
|
|
// if(elem.target.getAttribute("href") === "javascript:void(0)") {
|
|
elem.target.parentElement.classList.toggle("active");
|
|
elem.target.nextElementSibling.classList.toggle("d-block");
|
|
// }
|
|
}
|
|
}
|
|
}
|
|
|
|
// Menu sticky
|
|
function windowScroll() {
|
|
var navbar = document.getElementById("topnav");
|
|
if (navbar === null) {
|
|
|
|
} else if (document.body.scrollTop >= 50 ||
|
|
document.documentElement.scrollTop >= 50) {
|
|
navbar.classList.add("nav-sticky");
|
|
} else {
|
|
navbar.classList.remove("nav-sticky");
|
|
}
|
|
}
|
|
|
|
window.addEventListener('scroll', (ev) => {
|
|
ev.preventDefault();
|
|
windowScroll();
|
|
})
|
|
|
|
// back-to-top
|
|
var mybutton = document.getElementById("back-to-top");
|
|
window.onscroll = function () {
|
|
scrollFunction();
|
|
};
|
|
|
|
function scrollFunction() {
|
|
if (mybutton != null) {
|
|
if (document.body.scrollTop > 500 || document.documentElement.scrollTop > 500) {
|
|
mybutton.style.display = "block";
|
|
} else {
|
|
mybutton.style.display = "none";
|
|
}
|
|
}
|
|
}
|
|
|
|
function topFunction() {
|
|
document.body.scrollTop = 0;
|
|
document.documentElement.scrollTop = 0;
|
|
}
|
|
|
|
// dd-menu
|
|
if (document.getElementsByClassName("dd-menu")) {
|
|
var ddmenu = document.getElementsByClassName("dd-menu");
|
|
for (var i = 0, len = ddmenu.length; i < len; i++) {
|
|
ddmenu[i].onclick = function (elem) {
|
|
elem.stopPropagation();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Active Sidebar
|
|
(function () {
|
|
var current = location.pathname.substring(location.pathname.lastIndexOf('/') + 1);
|
|
if (current === "") return;
|
|
var menuItems = document.querySelectorAll('.sidebar-nav a');
|
|
for (var i = 0, len = menuItems.length; i < len; i++) {
|
|
if (menuItems[i].getAttribute("href").indexOf(current) !== -1) {
|
|
menuItems[i].parentElement.className += " active";
|
|
}
|
|
}
|
|
})();
|
|
|
|
// Last Modified Date of current page (relative time format)
|
|
if (document.getElementById("relativetime")) {
|
|
dayjs.extend(window.dayjs_plugin_relativeTime);
|
|
const modId = document.getElementById('relativetime');
|
|
let modAgo = dayjs(modId.getAttribute('data-authdate')).fromNow();
|
|
document.getElementById("relativetime").innerHTML = modAgo;
|
|
};
|
|
|
|
// Initialize Bootstrap Tooltips
|
|
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
|
|
const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new Tooltip(tooltipTriggerEl))
|
|
|
|
/**
|
|
* Sanitize and encode all HTML in a user-submitted string
|
|
* https://portswigger.net/web-security/cross-site-scripting/preventing
|
|
* @param {String} str The user-submitted string
|
|
* @return {String} str The sanitized string
|
|
*/
|
|
var sanitizeHTML = function (str) {
|
|
return str.replace(/[^\w. ]/gi, function (c) {
|
|
return '&#' + c.charCodeAt(0) + ';';
|
|
});
|
|
}; |