Udoro

Val -JS

Sep 16th, 2024 (edited)
152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // automatically rename the text on back button to show the panel name  
  2. //e.g. 'back to reviews' instead of the default text 'back'
  3. const updateBackText = 1; // true (1) or false (0)
  4. // calculate header height for mobile menu top offset
  5. const calcHeaderHeight = 1; // true (1) or false (0)
  6. // mobile breakpoint
  7. const mq = window.matchMedia("(max-width: 1024px)");
  8. // automatically opens the current menu item's panel
  9. const autoCurrentPosition = 1; // true (1) or false (0)
  10. const enableTopBar = 1;
  11. const enableOffCanvas = 0;
  12. const offCanvasBreakpoint = window.matchMedia("(max-width:10024px)");
  13. const offCanvasPushContent = 0; // enable offcanvas for this to work
  14. const fixedNavTrigger = 0;  // fix the toggle button when pushing content
  15. const openFirstDropDown = 0; // open first dropdwon conent on page load
  16. const autoCloseDropdown = 1; // automaticaly close dropdown when it loses focus
  17. const overlaySidebar = 0; // overlays the sidebar on a fullwidth page | disable offcanves for this to work
  18. const overlayTopBar = 0; // overlays the topbar when using offcanvas
  19. const enableRTL = 0; // support for RTL layout
  20. const offsetHashLinkScroll = 1; // add offset when scrolling to hashlink, useful for sticky header
  21.  
  22.  if (enableTopBar && !enableOffCanvas){  
  23.    document.body.classList.add('dwc-topbar-enabled')
  24.   }
  25.  
  26.  if (enableRTL){  
  27.    document.body.classList.add('dwc-rtl')
  28.   }
  29.  
  30.  if (overlaySidebar  && !enableOffCanvas){  
  31.    document.body.classList.add('dwc-overlay-sidebar')
  32.   }
  33.  
  34.  if (overlayTopBar  && enableOffCanvas){  
  35.    document.body.classList.add('dwc-overlay-topbar')
  36.   }
  37.  
  38.  
  39. //document.addEventListener('DOMContentLoaded', () => {
  40. const header = document.querySelector("header");
  41. const navTrigger = document.querySelector(".dwc-nav-trigger");
  42. const closeBtn =  document.querySelector(".dwc-sidebar__nav-close-btn");
  43. const mobileMenuOverlay = document.querySelector(".dwc-mobile-menu-overlay");
  44. const body = document.body;
  45. const nav = document.querySelector('.dwc-sidebar__nav');
  46. const homePanel = document.querySelector('.dwc-sidebar__nav__panel--home');
  47. const dropdownToggles = document.querySelectorAll('.dwc-sidebar__dropdown-toggle [role = "button"]');
  48. const dropdownContents = document.querySelectorAll('.dwc-sidebar__dropdown-content');
  49. const menuLinks = document.querySelectorAll('.dwc-sidebar__nav__li a');
  50. const offCanvasMobileOnly = offCanvasBreakpoint.matches;
  51.  
  52. const select = selector => document.querySelectorAll(selector);
  53.  
  54. const initInert = () => select('.dwc-sidebar__nav__panel').forEach(nPanel => {
  55.  
  56.     mobileMenuIsClosed()
  57.  
  58.     if (!nPanel.classList.contains('dwc-sidebar__nav__panel--home')) {
  59.         nPanel.inert = true;
  60.     } else {
  61.         nPanel.inert = false;
  62.     }
  63. });
  64.  
  65.  
  66.  
  67. //OPEN FIRST DROP DOWN
  68. if (openFirstDropDown){
  69.     setTimeout(function () {  
  70.             dropdownToggles[0].click();
  71. }, 600);
  72. }
  73.  
  74. // Get DROPWDOWN LEVELS
  75. dropdownContents.forEach(function (element) {
  76.     let level = 1;
  77.     let parent = element.parentElement.closest('.dwc-sidebar__dropdown-content');
  78.  
  79.     // Calculate the level by checking the number of ancestors
  80.     while (parent) {
  81.         level++;
  82.         parent = parent.parentElement.closest('.dwc-sidebar__dropdown-content');
  83.     }
  84.  
  85.     // Assign the appropriate level class to the dropdown content
  86.     element.classList.add(`level-${level}`);
  87.  
  88.     // Find the previous sibling with the class .dwc-sidebar__dropdown-toggle
  89.     const previousToggle = element.previousElementSibling;
  90.  
  91.     // Check if the previous sibling is a dropdown toggle and assign the level class
  92.     if (previousToggle && previousToggle.classList.contains('dwc-sidebar__dropdown-toggle')) {
  93.         previousToggle.classList.add(`level-${level}`);
  94.     }
  95. });
  96.  
  97.  
  98.  
  99. // CURRENT MENU ITEM ****************
  100.  
  101.  
  102.    // Get the current page address without trailing slash
  103. var currentPage = window.location.pathname.replace(/\/$/, '');
  104.  
  105. for (var i = 0; i < menuLinks.length; i++) {
  106.     var link = menuLinks[i];
  107.  
  108.     // Extract the pathname from the link's href attribute without trailing slash
  109.     var linkPathname = link.href.replace(window.location.origin, '').replace(/\/$/, '');
  110.  
  111.     // Check if the pathname matches the current page
  112.     if (linkPathname === currentPage) {
  113.         // Add the class 'dwc-current-menu-item' to the matching link
  114.         link.classList.add("dwc-current-menu-item");
  115.    
  116.       // Break out of the loop since we found the matching link
  117.         break;
  118.     } else {
  119.         // Skip to the next iteration if the link doesn't match
  120.         continue;
  121.     }
  122. }
  123.  
  124. setTimeout(function () {
  125.     const currentDropDownLink = document.querySelector('.dwc-current-menu-item.dwc-sidebar__nav__link');
  126.     if (currentDropDownLink) {
  127.         const parent = currentDropDownLink.closest('.dwc-sidebar__dropdown-content');
  128.         if (parent) {
  129.             const toggle = parent.previousElementSibling.querySelector('[role="button"]');
  130.             if (toggle) {
  131.                 toggle.click();
  132.             }
  133.         }
  134.         setTimeout(function () {
  135.             currentDropDownLink.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
  136.             //console.log(currentDropDownLink);
  137.         }, 500);
  138.     }
  139. }, 1800);
  140.  
  141.  
  142. // CURRENT MENU ENDS **********
  143.  
  144. // CURRENT MENU CHECK - we'll be using this to determine if to reset panels on navTrigger click or not
  145. var hasCurrentMenu = Array.from(document.querySelectorAll(".dwc-sidebar__nav__link.dwc-current-menu-item")).some(function (link) {
  146.     var parentPanel = link.closest(".dwc-sidebar__nav__panel");
  147.     return !parentPanel || !parentPanel.classList.contains("dwc-sidebar__nav__panel--home");
  148. });
  149.  
  150. // CURRENT CHECK ENDS *********************
  151.  
  152. const goHome = () => select('.dwc-sidebar__nav__panel').forEach(nPanel => {
  153.     nPanel.classList.remove('dwc-slide-left');
  154.  
  155.     if (!nPanel.classList.contains('dwc-sidebar__nav__panel--home')) {
  156.         nPanel.classList.add('dwc-slide-right');
  157.         nPanel.inert = true;
  158.     } else {
  159.         nPanel.inert = false;
  160.         if (header && !mq.matches) {
  161.             header.setAttribute('tabindex', 0);
  162.             header.focus()
  163.         }
  164.     }
  165.     select('.dwc-sidebar__nav__btn:not(.dwc-nav__back-btn)').forEach(sbtn => {
  166.         sbtn.setAttribute('aria-expanded', 'false');
  167.     })
  168.     mobileMenuIsClosed()
  169.     //window.addEventListener("resize", mobileMenuIsClosed);
  170. });
  171.  
  172.  window.addEventListener("resize", mobileMenuIsClosed);
  173. select('.dwc-nav__home-btn').forEach(hbtn => hbtn.addEventListener('click', goHome));
  174.  
  175.  
  176. nav.addEventListener('keydown', event => {
  177.     if (nav.contains(event.target)) {
  178.         if (event.key === 'Escape') {
  179.             if (body.classList.contains('dwc-slide-nav-open')) {
  180.  
  181.                 if (navTrigger) {
  182.                     navTrigger.click()
  183.                     navTrigger.focus()
  184.                 }
  185.                 goHome();
  186.  
  187.             } else {
  188.                 goHome();
  189.             }
  190.         }
  191.     }
  192. });
  193.  
  194. select('.dwc-sidebar__nav__btn:not(.dwc-nav__back-btn)').forEach(sbtn => {
  195.     sbtn.setAttribute('aria-expanded', 'false');
  196.     sbtn.addEventListener('click', function (e) {
  197.         initCollapseContent();
  198.         dropdownToggles.forEach((togglebtn) => {
  199.             togglebtn.setAttribute('aria-expanded', 'false');
  200.         });
  201.         e.preventDefault();
  202.         e.stopPropagation();
  203.         const targetId = this.getAttribute('data-title');
  204.         const targetElement = document.querySelector(`.dwc-sidebar__nav__panel[data-title="${targetId}"]`);
  205.         const parentPanel = this.closest('.dwc-sidebar__nav__panel');
  206.         targetElement.classList.remove('dwc-slide-right');
  207.         targetElement.inert = false;
  208.         targetElement.setAttribute('tabindex', 0);
  209.         targetElement.focus();
  210.         ariaExpanded = !targetElement.classList.contains('dwc-slide-right');
  211.         sbtn.setAttribute('aria-expanded', ariaExpanded);
  212.         select('.dwc-nav__back-btn').forEach(bbtn => {
  213.             bbtn.addEventListener('click', function (e) {
  214.                 ariaExpanded = !targetElement.classList.contains('dwc-slide-right');
  215.                 sbtn.setAttribute('aria-expanded', ariaExpanded);
  216.             })
  217.         })
  218.         if (!parentPanel.classList.contains('dwc-slide-right')) {
  219.             parentPanel.classList.add('dwc-slide-left');
  220.             parentPanel.inert = true;
  221.         }
  222.  
  223.         //handle back button data-title and back to feature
  224.         let bbtn = targetElement.querySelector('.dwc-nav__back-btn');
  225.         bbtnTitle = parentPanel.getAttribute('data-title');
  226.         if (bbtn) {
  227.             bbtn.setAttribute('data-title', bbtnTitle);
  228.             bbtn.setAttribute('aria-label', 'Go back to ' + bbtnTitle + ' menu');
  229.             //console.log(bbtnTitle)
  230.  
  231.             if (updateBackText) {
  232.                 bbtn.querySelector('.dwc-nav__back__text').textContent = 'back to ' + bbtnTitle;
  233.             }
  234.         }
  235.  
  236.     });
  237. })
  238. select('.dwc-nav__back-btn').forEach(bbtn => {
  239.     const btnTitle = bbtn.getAttribute('data-title');
  240.     bbtn.addEventListener('click', function (e) {
  241.         e.preventDefault();
  242.         e.stopPropagation();
  243.         const returnBtnAttr = this.getAttribute('data-title');
  244.         select('[data-title].dwc-sidebar__nav__panel').forEach(returnTarget => {
  245.             if (returnTarget.getAttribute('data-title') === returnBtnAttr) {
  246.                 returnTarget.classList.remove('dwc-slide-left');
  247.                 returnTarget.inert = false;
  248.                 if (returnTarget.classList.contains('dwc-sidebar__nav__panel--home')) {
  249.  
  250.                     if (header) {
  251.                         header.setAttribute('tabindex', 0);
  252.                         header.focus()
  253.                     }
  254.                 } else {
  255.                     returnTarget.setAttribute('tabindex', 0);
  256.                     returnTarget.focus();
  257.                 }
  258.                 if (returnTarget.classList.contains('dwc-slide-right')) {
  259.                     returnTarget.classList.remove('dwc-slide-right');
  260.                 }
  261.             }
  262.         });
  263.         const parentPanel = this.closest('.dwc-sidebar__nav__panel');
  264.         parentPanel.classList.add('dwc-slide-right');
  265.         parentPanel.inert = true;
  266.     });
  267.  
  268. });
  269. select('.dwc-sidebar__nav__panel').forEach(panel => {
  270.     const panelTitle = panel.getAttribute('data-title');
  271.     panel.setAttribute('aria-label', panelTitle + ' menu');
  272. });
  273.  
  274. // mobile trigger
  275.  
  276.  function mobileMenuIsClosed() {
  277.  
  278.         if (mq.matches || enableOffCanvas) {
  279.    
  280.             const isNavOpen = body.classList.contains("dwc-slide-nav-open");
  281.             navTrigger.setAttribute("aria-expanded", isNavOpen);
  282.             if (isNavOpen) {
  283.                 if(!homePanel.classList.contains('dwc-slide-left')){
  284.                 homePanel.inert = false;
  285.                 }
  286.             } else if (offCanvasMobileOnly){
  287.                homePanel.inert = true;
  288.             }
  289.         } else {
  290.             homePanel.inert = false;
  291.          // console.log('desktop')
  292.         }
  293.     }
  294.  
  295.  
  296.  
  297. function setNoScroll() {
  298.  
  299.     let noScrollTimeout;
  300.     let clickCount = 1;
  301.     let isNavOpen = body.classList.contains('dwc-slide-nav-open');
  302.  
  303.     // Check if 'dwc-slide-nav-open' class is applied
  304.     if (isNavOpen) {
  305.         body.classList.add('dwc-no-scroll');
  306.         clickCount++;
  307.     } else {
  308.         clickCount = 0;
  309.     }
  310.    //console.log(clickCount)
  311.  
  312.  
  313.     // Toggle 'dwc-no-scroll' class on the body if clickCount is odd
  314.     if (clickCount == 0) {
  315.  
  316.         // Set a timer to remove 'dwc-no-scroll' class after 0.8 seconds
  317.      
  318.         noScrollTimeout = setTimeout(() => {  
  319.       isNavOpen = body.classList.contains('dwc-slide-nav-open');
  320.          // console.log(isNavOpen)
  321.            if(!isNavOpen){
  322.             body.classList.remove('dwc-no-scroll');
  323.            }
  324.         }, 900);
  325.        
  326.     } else {
  327.         // If 'dwc-no-scroll' class is removed by clicking again, clear the timeout
  328.         clearTimeout(noScrollTimeout);
  329.     }
  330. }
  331.  
  332.  
  333.  
  334. if (navTrigger) {
  335.     navTrigger.addEventListener("click", function () {
  336.         body.classList.toggle("dwc-slide-nav-open");
  337.         setNoScroll()
  338.         mobileMenuIsClosed()
  339.         if (!hasCurrentMenu && !autoCurrentPosition) {
  340.             initCollapseContent()
  341.             goHome();// watch out for this, could be problematic  
  342.         }
  343.         dropdownToggles.forEach((togglebtn) => {
  344.             //togglebtn.setAttribute('aria-expanded', 'false');
  345.         });
  346.     });
  347. }
  348. if (mobileMenuOverlay) {
  349.     mobileMenuOverlay.addEventListener("click", function () {
  350.         body.classList.remove("dwc-slide-nav-open");
  351.         mobileMenuIsClosed()
  352.         setNoScroll()
  353.         if (!hasCurrentMenu && !autoCurrentPosition) {
  354.             initCollapseContent()
  355.             goHome()
  356.         }
  357.     });
  358. }
  359.  
  360. if (closeBtn) {
  361.     closeBtn.addEventListener("click", function () {
  362.         body.classList.remove("dwc-slide-nav-open");
  363.         mobileMenuIsClosed()
  364.         setNoScroll()
  365.       navTrigger.focus();
  366.         if (!hasCurrentMenu && !autoCurrentPosition) {
  367.             initCollapseContent()
  368.             goHome()
  369.         }
  370.     });
  371. }
  372.  
  373.  
  374. //focus on mobile trigger when menu loses focus
  375. mobileMenuOverlay.addEventListener('focusin', (event) => {
  376.     if (event.relatedTarget !== navTrigger && body.classList.contains("dwc-slide-nav-open")) {
  377.         navTrigger.focus();
  378.     }
  379. });
  380.  
  381. const sidebarNavPanels = document.querySelectorAll(".dwc-sidebar__nav__panel");
  382.  
  383. function updateSidebarPadding() {
  384.     if (header && !enableOffCanvas) {
  385.        // const headerHeight = header.clientHeight + 20;
  386.       setTimeout(() => {
  387.   const headerHeight = header.clientHeight + 20;
  388.   // Your code to use headerHeight goes here
  389.  
  390.  
  391.         sidebarNavPanels.forEach(function (sidebarNavPanel) {
  392.             sidebarNavPanel.style.paddingTop = headerHeight + "px";
  393.         });
  394.         mobileMenuOverlay.style.marginTop = headerHeight - 20 + "px";
  395.       }, 50);
  396.     }
  397.                
  398. }
  399.  
  400. function resetPadding() {
  401.    setTimeout(() => {
  402.     sidebarNavPanels.forEach(function (sidebarNavPanel) {
  403.         sidebarNavPanel.style.paddingTop = null;
  404.     });
  405.       }, 50);
  406. }
  407.  
  408. function checkScreenSize() {
  409.     if (mq.matches) {
  410.         updateSidebarPadding();
  411.       body.classList.add('dwc-mobile');
  412.     } else {
  413.        body.classList.remove('dwc-mobile');
  414.      // if(!enableTopBar){
  415.         resetPadding()
  416.      // }
  417.     }
  418. }
  419. if (calcHeaderHeight) {
  420.     checkScreenSize();
  421.     window.addEventListener("resize", checkScreenSize);
  422. }
  423.  
  424.  
  425. initInert()
  426.  
  427.  
  428. //  *********  DROPDOWN TOGGLE FUNCNTIONALITY *******************
  429.  
  430.  
  431. function eCollapseContent(el, btn) {
  432.  
  433.     // Find the closest common ancestor, such as the <li> element
  434.     const btnParentLi = btn.closest('li');
  435.  
  436.     dropdownContents.forEach((content) => {
  437.         // Find the closest <li> ancestor for the dropdown content
  438.         const contentParentLi = content.closest('li');
  439.  
  440.         // Check if the content and the button are at the same level
  441.         const isSameLevel = btnParentLi && contentParentLi && btnParentLi.parentElement === contentParentLi.parentElement;
  442.  
  443.         // Check if the content is an ancestor of the dropdown toggle being clicked
  444.         const isAncestor = btn && content.contains(btn);
  445.  
  446.         // Collapse the dropdown if it's not an ancestor of the toggle and is on the same level
  447.         if (!isAncestor && isSameLevel) {
  448.             content.style.maxHeight = '0';
  449.             content.setAttribute('inert', 'true');
  450.          
  451.              // Update the aria-expanded attribute of the corresponding toggle button
  452.             const correspondingToggle = content.previousElementSibling.querySelector('[role="button"]');
  453.             if (correspondingToggle) {
  454.                 correspondingToggle.setAttribute('aria-expanded', 'false');
  455.             }
  456.          
  457.         }
  458.     });
  459.  
  460. }
  461.  
  462.  
  463. function initCollapseContent(el, btn) {
  464.     dropdownContents.forEach((content) => {
  465.         content.style.maxHeight = '0';
  466.         content.setAttribute('inert', 'true');    
  467.      
  468.     });
  469.  
  470. }
  471.  
  472.  
  473.  
  474. function collapseContent(el, btn) {
  475.  
  476.  
  477.     // Find the closest common ancestor, such as the <li> element
  478.     const btnParentLi = btn.closest('li');
  479.  
  480.     dropdownContents.forEach((content) => {
  481.         // Find the closest <li> ancestor for the dropdown content
  482.         const contentParentLi = content.closest('li');
  483.  
  484.         // Check if the content and the button are at the same level
  485.         const isSameLevel = btnParentLi && contentParentLi && btnParentLi.parentElement === contentParentLi.parentElement;
  486.  
  487.         // Check if the content is an ancestor of the dropdown toggle being clicked
  488.         const isAncestor = btn && content.contains(btn);
  489.  
  490.         // Collapse the dropdown if it's not an ancestor of the toggle and is on the same level
  491.         if (!isAncestor && isSameLevel) {
  492.             content.style.maxHeight = '0';
  493.             content.setAttribute('inert', 'true');
  494.          
  495.         }
  496.     });
  497.      
  498. }
  499.  
  500.  
  501. // Toggle the ARIA attributes for dropdown buttons
  502. function toggleAriaExpanded(activeToggle) {
  503.  
  504.      // If activeToggle is null, reset all buttons to 'false'
  505.     if (activeToggle === null) {
  506.         dropdownToggles.forEach((toggle) => {
  507.             toggle.setAttribute('aria-expanded', 'false');
  508.         });
  509.         return; // Exit the function early since there's nothing else to do
  510.     }
  511.  
  512.     dropdownToggles.forEach((toggle) => {
  513.         if (toggle === activeToggle) {
  514.             // Toggle the aria-expanded attribute for the clicked button
  515.             const isOpen = toggle.getAttribute('aria-expanded') === 'true';
  516.             toggle.setAttribute('aria-expanded', isOpen ? 'false' : 'true');
  517.         } else {
  518.             // Check if the toggle's parent is a sibling to the activeToggle's parent
  519.             const toggleParent = toggle.closest('li');
  520.             const activeToggleParent = activeToggle.closest('li');
  521.         //  console.log('toggle parent', toggleParent)
  522.          // console.log('active toggle parent', activeToggleParent)
  523.  
  524.             if (toggleParent && activeToggleParent && toggleParent.parentElement === activeToggleParent.parentElement) {
  525.                 // Set all other buttons' aria-expanded to false if their parent is a sibling to the activeToggle's parent
  526.                 toggle.setAttribute('aria-expanded', 'false');
  527.             }
  528.         }
  529.     });
  530. }
  531.  
  532.  
  533. // Function to adjust the max-height of parent dropdowns when a nested dropdown is opened
  534. function adjustDropdownHeight(dropdownContent) {
  535.     // Start with the nearest ancestor that is a dropdown content
  536.     let parent = dropdownContent.closest('.dwc-sidebar__dropdown-content');
  537.  
  538.  
  539.     while (parent) {
  540.         // Calculate the cumulative height of all open children
  541.         let totalHeight = Array.from(parent.children).reduce((total, child) => {
  542.             // Add the child scrollHeight to the total if it's open
  543.             total += child.scrollHeight;
  544.             return total;        
  545.         }, 0);
  546.  
  547.         // Move to the next ancestor that is a dropdown content
  548.         parent = parent.parentElement.closest('.dwc-sidebar__dropdown-content');
  549.        if(parent){
  550.           parentHeight = parent.scrollHeight;
  551.                 // Set the parent's max-height to the total calculated height
  552.         parent.style.maxHeight = `${totalHeight + parentHeight}px`;
  553.      // console.log('child: ', dropdownContent)
  554.       //    console.log('parent: ', parent)
  555.      // console.log(`${totalHeight}px`)
  556.          parent.inert = false;
  557.          
  558.          // console.log('parent new: ', parent)
  559.          
  560.          const parentParent = parent.closest('li')
  561.          const toggle = parentParent.querySelector('.dwc-sidebar__dropdown-toggle [role = "button"]')        
  562.          toggle.setAttribute('aria-expanded', 'true');
  563.        }
  564.     }
  565. }
  566.  
  567. // Initialize dropdowns
  568. function initializeDropdowns() {
  569.     initCollapseContent();
  570.  
  571.     dropdownToggles.forEach((toggle, index) => {
  572.         toggle.setAttribute('aria-expanded', 'false');
  573.  
  574.         const dropdownContent = dropdownContents[index];
  575.         const parentDropdown = toggle.closest('.dwc-sidebar__dropdown');
  576.         const dropdownLink = parentDropdown.querySelector('.dwc-nav__link__text');
  577.  
  578.         toggle.setAttribute('aria-label', `Toggle ${dropdownLink.textContent} dropdown`);
  579.  
  580.         toggle.addEventListener('click', function () {
  581.             const isOpen = dropdownContent.style.maxHeight !== '0px';
  582.  
  583.             collapseContent(dropdownContent, this);
  584.  
  585.             if (!isOpen) {
  586.                 dropdownContent.inert = false;
  587.             }
  588.  
  589.             toggleAriaExpanded(this);
  590.  
  591.             if (parentDropdown.contains(this)) {
  592.                 dropdownContent.style.maxHeight = isOpen ? '0' : `${dropdownContent.scrollHeight}px`;
  593.  
  594.                 // Only adjust if opening the dropdown
  595.                 if (!isOpen) {
  596.                     adjustDropdownHeight(dropdownContent);
  597.                  // console.log('other child', dropdownContent)
  598.                 }
  599.             }
  600.         });
  601.  
  602.         toggle.addEventListener('keydown', (event) => {
  603.             closeDropdownOnEscape(event, toggle);
  604.         });
  605.     });
  606. }
  607.  
  608.  
  609. // Close dropdowns on Escape key press
  610. function closeDropdownOnEscape(event, el) {
  611.     if (event.key === 'Escape' && el.contains(event.target)) {
  612.         event.stopPropagation();
  613.  
  614.         if (el.style.maxHeight !== '0px') {
  615.             const button = el.previousElementSibling.querySelector('[role = "button"]');
  616.  
  617.             if (button) {
  618.                 el.style.maxHeight = '0';
  619.                 el.inert = true;
  620.                 button.focus();
  621.             } else {
  622.                 initCollapseContent();
  623.                 el.focus();
  624.             }
  625.  
  626.             toggleAriaExpanded(null); // Reset all buttons to 'false'
  627.         }
  628.     }
  629. }
  630.  
  631. // Initialize dropdowns
  632. initializeDropdowns();
  633.  
  634.  
  635. dropdownContents.forEach((dropdownContent) => {
  636.     // Add event listeners for closing dropdowns on Escape key press
  637.     dropdownContent.addEventListener('keydown', (event) => {
  638.         closeDropdownOnEscape(event, dropdownContent);
  639.     });
  640.  
  641. // close dropdown on focus lost
  642.  
  643.     if(autoCloseDropdown){
  644.     const links = dropdownContent.querySelectorAll('a.dwc-sidebar__nav__link');
  645.  
  646.     links.forEach(link => {
  647.         const linkParent = link.closest('.dwc-sidebar__dropdown-content');
  648.         const dropDownButton = linkParent.previousElementSibling.querySelector('[role = "button"]')
  649.  
  650.         link.addEventListener('blur', () => {
  651.  
  652.  
  653.             setTimeout(function () {
  654.                 if ([...links].every(link => !document.activeElement.isSameNode(link))) {
  655.  
  656.                     eCollapseContent(dropdownContent, dropDownButton)
  657.  
  658.                 }
  659.             }, 50);
  660.         });
  661.     });
  662. }
  663. });
  664.  
  665.  
  666. // AUTOMATIC MENU POSITION
  667.  
  668. function autoMenuPosition() {
  669.     // Select the current menu item
  670.     const currentMenuItem = document.querySelector('.dwc-current-menu-item');
  671.  
  672.     // Select the parent panel of the current menu item
  673.     if (currentMenuItem) {
  674.         const parentPanel = currentMenuItem.closest('.dwc-sidebar__nav__panel');
  675.         const parentIsHome = parentPanel.classList.contains('dwc-sidebar__nav__panel--home')
  676.  
  677.         // Check if the parent panel has the 'dwc-sidebar__nav__panel--home' class
  678.         if (!parentIsHome) {
  679.             // Select the back button in the current menu's parent panel
  680.             const backButton = parentPanel.querySelector('.dwc-nav__back-btn');
  681.  
  682.             // Remove the class 'dwc-slide-right' from the current menu's parent panel
  683.             parentPanel.classList.remove('dwc-slide-right');
  684.  
  685.             // Get the data-title attribute of the current menu's parent panel
  686.  
  687.             // Loop through all panels with class .dwc-sidebar__nav__panel
  688.             const allPanels = document.querySelectorAll('.dwc-sidebar__nav__panel');
  689.  
  690.             // Select all slide buttons .dwc-sidebar__nav__btn of each panel
  691.             const slideButtons = document.querySelectorAll('.dwc-sidebar__nav__btn:not(.dwc-nav__back-btn)');
  692.  
  693.             slideButtons.forEach((slideButton) => {
  694.  
  695.                 allPanels.forEach((panel) => {
  696.  
  697.                     // Get the data-title attribute of the panel
  698.                     const eachPanelTitle = panel.getAttribute('data-title');
  699.                     // Get the back button in each of the panels
  700.                     const panelBackButton = panel.querySelector('.dwc-nav__back-btn');
  701.  
  702.                     const slideTitle = slideButton.getAttribute('data-title')
  703.  
  704.  
  705.                     if (slideTitle === eachPanelTitle) {
  706.                         //get slide button parent
  707.                         const slideParentPanel = slideButton.closest('.dwc-sidebar__nav__panel');
  708.                         //get slide parent titlte attribute
  709.                         const slideParentTitle = slideParentPanel.getAttribute('data-title')
  710.                         // Set the back button title attribute to be equal to the title attribute of the slide parent panel
  711.                         panelBackButton.setAttribute('data-title', slideParentTitle);
  712.                         panelBackButton.querySelector('.dwc-nav__back__text').textContent = 'back to ' + slideParentTitle
  713.                     }
  714.                 });
  715.  
  716.             });
  717.  
  718.             homePanel.classList.add('dwc-slide-left');
  719.         }
  720.         if (!parentIsHome) {
  721.             parentPanel.inert = false;
  722.             homePanel.inert = true;
  723.         }
  724.  
  725.         repositionReturnTargets()
  726.  
  727.     }
  728. }
  729.  
  730. if (autoCurrentPosition) {
  731.   setTimeout(function () {
  732.     autoMenuPosition()
  733.   }, 1000);
  734. }
  735.  
  736.  
  737. //function to reposition the hidden slides after automatically moving to current menu item panel
  738. // to put them in the right position to slide back to
  739. function repositionReturnTargets() {
  740.  
  741.     const panels = document.querySelectorAll('.dwc-sidebar__nav__panel:not(.dwc-sidebar__nav__panel--home)');
  742.     let activePanel;
  743.  
  744.     // Find the first panel without 'dwc-slide-right' and 'dwc-slide-left' classes
  745.     for (const panel of panels) {
  746.         if (!panel.classList.contains('dwc-slide-right') && !panel.classList.contains('dwc-slide-left')) {
  747.             activePanel = panel;
  748.             break;
  749.         }
  750.     }
  751.  
  752.     let returnTarget;
  753.  
  754.     while (activePanel) {
  755.         //  Get the title attribute of each panel
  756.         const panelTitles = Array.from(panels).map(panel => panel.getAttribute('data-title'));
  757.  
  758.         //  Select the active back button in the active panel
  759.         const activeBackButton = activePanel.querySelector('.dwc-nav__back-btn');
  760.  
  761.         // Find the returnTarget panel
  762.         returnTarget = Array.from(panels).find(panel => panel.getAttribute('data-title') === activeBackButton.getAttribute('data-title'));
  763.  
  764.         // Remove and add classes to the returnTarget
  765.         if (returnTarget) {
  766.             returnTarget.classList.remove('dwc-slide-right');
  767.             returnTarget.classList.add('dwc-slide-left');
  768.         }
  769.  
  770.         // Update activePanel for the next iteration
  771.         activePanel = returnTarget;
  772.     }
  773. }
  774.  
  775. // *********AUTOMATIC ENDS************
  776.  
  777. // Button without button tag click on ENTER
  778.  
  779. header.addEventListener('keydown', function (event) {
  780.     if (event.key === 'Enter' && event.target.matches('[role="button"]')) {
  781.         // Check if the target element is a button and if the Enter key was pressed
  782.         event.target.click();
  783.     }
  784. });
  785.  
  786.  
  787.  
  788.  
  789. // **************OFFCANVAS *****************
  790.  
  791.  
  792.   if (offCanvasPushContent) {
  793.              
  794.        // Create a new div element with the class "site-wrapper"
  795.             var siteWrapper = document.createElement('div');
  796.             siteWrapper.className = 'dwc-site-wrapper';
  797.             // Move everything within the body tag into the "site-wrapper" div
  798.             while (document.body.firstChild) {
  799.                 siteWrapper.appendChild(document.body.firstChild);
  800.             }
  801.             // Add the "site-wrapper" div back to the body
  802.             document.body.appendChild(siteWrapper);
  803.     }
  804.  
  805. function offCanvasInit() {
  806.  
  807. if (enableOffCanvas && offCanvasBreakpoint.matches) {
  808.     document.body.classList.add('dwc-offcanvas');
  809.  
  810.     if (offCanvasPushContent) {
  811.         document.body.classList.add('dwc-push-content');
  812.       if(fixedNavTrigger){
  813.             document.body.classList.add('dwc-nav-trigger-is-fixed');
  814.           }
  815.  
  816.     }
  817.  
  818.     // Function to check if header element is focusable
  819.     function isFocusable(element) {
  820.         const focusableTags = ['A', 'BUTTON', 'INPUT', 'SELECT', 'TEXTAREA', 'AREA'];
  821.         return (
  822.             focusableTags.includes(element.tagName) ||
  823.             element.hasAttribute('tabindex') ||
  824.             element.hasAttribute('contenteditable')
  825.         );
  826.     }
  827.  
  828.    
  829. // Function to set inert attribute for focusable elements
  830. function setInertForFocusableElements(inertValue) {
  831.     const allElements = document.querySelectorAll('.dwc-header-inner-wrap *');
  832.     const focusableElements = Array.from(allElements).filter(element => {
  833.         return isFocusable(element) && !element.classList.contains('dwc-nav-trigger');
  834.     });
  835.  
  836.     focusableElements.forEach(element => {
  837.         if (element) {
  838.             element.inert = inertValue;
  839.         }
  840.     });
  841. }
  842.  
  843. // Click event listener for the 'nav-trigger'
  844.  
  845. header.addEventListener('click', function () {
  846.     const isNavOpen = document.body.classList.contains('dwc-slide-nav-open');
  847.  
  848.     // Check if the body contains the class 'dwc-slide-nav-open'
  849.     if (isNavOpen) {
  850.         // Condition is true, set inert=true
  851.         setInertForFocusableElements(isNavOpen);
  852.     } else {
  853.         // Condition is false, set inert=false
  854.         setInertForFocusableElements(isNavOpen);
  855.     }
  856. });
  857.  
  858. } else {
  859.  document.body.classList.remove('dwc-push-content');
  860.    document.body.classList.remove('dwc-offcanvas');
  861. }
  862.  
  863. }
  864.      offCanvasInit()
  865.     window.addEventListener("resize", offCanvasInit);
  866.  
  867.  
  868. //close offcanvas when haslink is clicked
  869.  
  870.  
  871.  
  872. if (enableOffCanvas) {
  873.     const sidebarLinks = document.querySelectorAll('a.dwc-sidebar__nav__link');
  874.  
  875.     // Filter links with hash in the href attribute
  876.     const hashLinks = Array.from(sidebarLinks).filter(link => link.getAttribute('href').includes('#'));
  877.  
  878.     // Add click event listener to each hash link
  879.     hashLinks.forEach(link => {
  880.         link.addEventListener('click', function(event) {
  881.          //   event.preventDefault(); // Prevent the default behavior of the link (e.g., navigating to the hash)
  882.            
  883.             // Perform a click action on the navTrigger button
  884.            
  885.             if (navTrigger) {
  886.               navTrigger.click();        
  887.             }
  888.         });
  889.     });
  890. }
  891.  
  892.  
  893. //Document loaded end
  894. // });
  895.  
  896. function debounce(func, delay) {
  897.     let timeoutId;
  898.  
  899.     return function (...args) {
  900.         clearTimeout(timeoutId);
  901.         timeoutId = setTimeout(() => {
  902.             func.apply(this, args);
  903.         }, delay);
  904.     };
  905. }
  906.  
  907. // Your existing code for adding the 'hasHeaderHeight' class
  908. function addHeaderHeightClass() {
  909.  
  910.  
  911.     if (!document.body) {
  912.         // Body doesn't exist, keep checking
  913.         setTimeout(addHeaderHeightClass, 0);
  914.         return;
  915.     }
  916.  
  917.     let hasHeaderHeight = document.body.classList.contains('hasHeaderHeight');
  918.     let header = document.querySelector('header');
  919.  
  920.     if (!hasHeaderHeight && header) {
  921.         // Header exists, add the 'hasHeaderHeight' class
  922.         document.body.classList.add('hasHeaderHeight');
  923.  
  924.         // Get the initial header height
  925.         updateHeaderHeight();
  926.     } else if (!hasHeaderHeight && !header) {
  927.         // Header doesn't exist, keep checking
  928.         setTimeout(addHeaderHeightClass, 0);
  929.     }
  930. }
  931.  
  932. // Function to update header height and set the CSS variable
  933. function updateHeaderHeight() {
  934.     let sidebar = document.querySelector('.dwc-header-inner-wrap');
  935.    
  936.    
  937.     if (document.body) {
  938.         let headerHeight = sidebar.offsetHeight;
  939.         document.body.style.setProperty('--dwc-header-height', `${headerHeight}px`);
  940.     }
  941.    }
  942.  
  943. // Add the 'hasHeaderHeight' class and set initial header height
  944. addHeaderHeightClass();
  945.  
  946. // Attach the debounced update function to the window resize event
  947. const debouncedUpdateHeaderHeight = debounce(updateHeaderHeight, 50);
  948. window.addEventListener('resize', debouncedUpdateHeaderHeight);
  949.  
  950.  
  951. // Smooth scroll to hashlink with an offset
  952. function smoothScroll(target, offset) {
  953.     const targetElement = document.querySelector(target);
  954.     if (targetElement) {
  955.        
  956.         const targetPosition = targetElement.getBoundingClientRect().top -
  957.       document.body.getBoundingClientRect().top -
  958.       offset;
  959.         window.scrollTo({
  960.             top: targetPosition,
  961.             behavior: 'smooth'
  962.         });
  963.  
  964.           }
  965. }
  966.  
  967. // Listen for hash link clicks
  968. if(offsetHashLinkScroll){
  969. document.querySelectorAll('a[href^="#"]').forEach(anchor => {  
  970.     anchor.addEventListener('click', function (e) {
  971. var headerElement =  document.querySelector('.dwc-header-inner-wrap');
  972. var offset = headerElement.offsetHeight;
  973.         e.preventDefault();
  974.            event.stopPropagation();
  975.         const href = this.getAttribute('href');
  976.         smoothScroll(href, offset);
  977.     });
  978. });
  979. }
  980.  
  981.  
Advertisement
Add Comment
Please, Sign In to add comment