How to make all parent menu items clickable (Dawn 15.4)

Hello, everyone!
I’d like to make all parent menu items clickable on my website (Dawn 15.4 theme). I want the parent items to open their linked collections when clicked, not only expanding the submenu.

I saw that a solution was shared on the forum earlier, but most of the code has disappeared from the posts, so I can’t use it :frowning:
Can anyone advise? Thank you!

My website: Products – DrawWithDi

1 Like

Hi @DRAWandCARE

Ok dear, please share your store URL and collaborator code with me so I can check and provide you with the proper solution.

To make parent menu items clickable in the Dawn 15.4 theme, go to header.liquid, find the menu loop, and remove or modify the JavaScript or HTML that prevents default link behavior (e.g., e.preventDefault()), allowing parent links to navigate to their assigned URLs.

Hi @DRAWandCARE

Go to Online Store > Themes > Edit Code > assets/header.js

Find the code like below:

this.parentLink.addEventListener(‘click’, (evt) => {
if (this.hasChildren) {
evt.preventDefault();
this.toggleSubmenu();
}
});

Replace it with below code:

this.parentLink.addEventListener(‘click’, (evt) => {
if (this.hasChildren) {
// Only prevent default if the toggle icon/button was clicked
if (evt.target.closest(‘.menu__toggle’)) {
evt.preventDefault();
this.toggleSubmenu();
}
}
});

On click of parent link text it will goes to the linked collection and on Click toggle arrow submenu will expands/collapse.

1 Like

Hi, thank you so much for your reply! Unfortunately, I don’t have a header.js file in my assets. Is there another file where I could add the code?

OK, you can check the code either in below files:

  1. global.js
  2. header-drawer.js
  3. navigation.js
1 Like

Alternatively, you can add below code before tag in theme.liquid file, it will link parent menu and make it clickable.

1 Like
<script>
  (() => {
    document.querySelectorAll("nav.header__inline-menu details").forEach(details => {
      const summary = details.querySelector("summary");
      const parentLink = details.querySelector("a"); 

      if (!summary || !parentLink) return;

      summary.addEventListener("click", e => {
         if (e.target.closest("svg")) return;

         window.location.href = parentLink.href;
      });
    });
  })();
</script>
1 Like

I had this code in my theme.liquid file, shouid I replace it or place below/above? Before which tag?

<script>
function addAnchorToIcons(){
var $icons = document.querySelectorAll(`.list-social__item a`);

if (!$icons){
return;
}

for (var each of $icons){
each.setAttribute("target", "_blank");
}

}

addAnchorToIcons();
</script>

You can add the given script just below this code you shared.

1 Like

Didn’t work, unfortunately :frowning:

Also, I have something like that in my global.js, but I don’t understand where to put your code or what I should change…

 // Sets inner HTML and reinjects the script tags to allow execution. By default, scripts are disabled when using element.innerHTML.
  static setInnerHTML(element, html) {
    element.innerHTML = html;
    element.querySelectorAll('script').forEach((oldScriptTag) => {
      const newScriptTag = document.createElement('script');
      Array.from(oldScriptTag.attributes).forEach((attribute) => {
        newScriptTag.setAttribute(attribute.name, attribute.value);
      });
      newScriptTag.appendChild(document.createTextNode(oldScriptTag.innerHTML));
      oldScriptTag.parentNode.replaceChild(newScriptTag, oldScriptTag);
    });
  }
}

document.querySelectorAll('[id^="Details-"] summary').forEach((summary) => {
  summary.setAttribute('role', 'button');
  summary.setAttribute('aria-expanded', summary.parentNode.hasAttribute('open'));

  if (summary.nextElementSibling.getAttribute('id')) {
    summary.setAttribute('aria-controls', summary.nextElementSibling.id);
  }

  summary.addEventListener('click', (event) => {
    event.currentTarget.setAttribute('aria-expanded', !event.currentTarget.closest('details').hasAttribute('open'));
  });

  if (summary.closest('header-drawer, menu-drawer')) return;
  summary.parentElement.addEventListener('keyup', onKeyUpEscape);
});

  onSummaryClick(event) {
    const summaryElement = event.currentTarget;
    const detailsElement = summaryElement.parentNode;
    const parentMenuElement = detailsElement.closest('.has-submenu');
    const isOpen = detailsElement.hasAttribute('open');
    const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)');

    function addTrapFocus() {
      trapFocus(summaryElement.nextElementSibling, detailsElement.querySelector('button'));
      summaryElement.nextElementSibling.removeEventListener('transitionend', addTrapFocus);
    }

    if (detailsElement === this.mainDetailsToggle) {
      if (isOpen) event.preventDefault();
      isOpen ? this.closeMenuDrawer(event, summaryElement) : this.openMenuDrawer(summaryElement);

      if (window.matchMedia('(max-width: 990px)')) {
        document.documentElement.style.setProperty('--viewport-height', `${window.innerHeight}px`);
      }
    } else {
      setTimeout(() => {
        detailsElement.classList.add('menu-opening');
        summaryElement.setAttribute('aria-expanded', true);
        parentMenuElement && parentMenuElement.classList.add('submenu-open');
        !reducedMotion || reducedMotion.matches
          ? addTrapFocus()
          : summaryElement.nextElementSibling.addEventListener('transitionend', addTrapFocus);
      }, 100);
    }
  }

  openMenuDrawer(summaryElement) {
    setTimeout(() => {
      this.mainDetailsToggle.classList.add('menu-opening');
    });
    summaryElement.setAttribute('aria-expanded', true);
    trapFocus(this.mainDetailsToggle, summaryElement);
    document.body.classList.add(`overflow-hidden-${this.dataset.breakpoint}`);
  }

  closeMenuDrawer(event, elementToFocus = false) {
    if (event === undefined) return;

    this.mainDetailsToggle.classList.remove('menu-opening');
    this.mainDetailsToggle.querySelectorAll('details').forEach((details) => {
      details.removeAttribute('open');
      details.classList.remove('menu-opening');
    });
    this.mainDetailsToggle.querySelectorAll('.submenu-open').forEach((submenu) => {
      submenu.classList.remove('submenu-open');
    });
    document.body.classList.remove(`overflow-hidden-${this.dataset.breakpoint}`);
    removeTrapFocus(elementToFocus);
    this.closeAnimation(this.mainDetailsToggle);

    if (event instanceof KeyboardEvent) elementToFocus?.setAttribute('aria-expanded', false);
  }

  onFocusOut() {
    setTimeout(() => {
      if (this.mainDetailsToggle.hasAttribute('open') && !this.mainDetailsToggle.contains(document.activeElement))
        this.closeMenuDrawer();
    });
  }

  onCloseButtonClick(event) {
    const detailsElement = event.currentTarget.closest('details');
    this.closeSubmenu(detailsElement);
  }

  closeSubmenu(detailsElement) {
    const parentMenuElement = detailsElement.closest('.submenu-open');
    parentMenuElement && parentMenuElement.classList.remove('submenu-open');
    detailsElement.classList.remove('menu-opening');
    detailsElement.querySelector('summary').setAttribute('aria-expanded', false);
    removeTrapFocus(detailsElement.querySelector('summary'));
    this.closeAnimation(detailsElement);
  }

  closeAnimation(detailsElement) {
    let animationStart;

    const handleAnimation = (time) => {
      if (animationStart === undefined) {
        animationStart = time;
      }

      const elapsedTime = time - animationStart;

      if (elapsedTime < 400) {
        window.requestAnimationFrame(handleAnimation);
      } else {
        detailsElement.removeAttribute('open');
        if (detailsElement.closest('details[open]')) {
          trapFocus(detailsElement.closest('details[open]'), detailsElement.querySelector('summary'));
        }
      }
    };

    window.requestAnimationFrame(handleAnimation);
  }
}

customElements.define('menu-drawer', MenuDrawer);

class HeaderDrawer extends MenuDrawer {
  constructor() {
    super();
  }

  openMenuDrawer(summaryElement) {
    this.header = this.header || document.querySelector('.section-header');
    this.borderOffset =
      this.borderOffset || this.closest('.header-wrapper').classList.contains('header-wrapper--border-bottom') ? 1 : 0;
    document.documentElement.style.setProperty(
      '--header-bottom-position',
      `${parseInt(this.header.getBoundingClientRect().bottom - this.borderOffset)}px`
    );
    this.header.classList.add('menu-open');

    setTimeout(() => {
      this.mainDetailsToggle.classList.add('menu-opening');
    });

    summaryElement.setAttribute('aria-expanded', true);
    window.addEventListener('resize', this.onResize);
    trapFocus(this.mainDetailsToggle, summaryElement);
    document.body.classList.add(`overflow-hidden-${this.dataset.breakpoint}`);
  }

  closeMenuDrawer(event, elementToFocus) {
    if (!elementToFocus) return;
    super.closeMenuDrawer(event, elementToFocus);
    this.header.classList.remove('menu-open');
    window.removeEventListener('resize', this.onResize);
  }

  onResize = () => {
    this.header &&
      document.documentElement.style.setProperty(
        '--header-bottom-position',
        `${parseInt(this.header.getBoundingClientRect().bottom - this.borderOffset)}px`
      );
    document.documentElement.style.setProperty('--viewport-height', `${window.innerHeight}px`);
  };
}

Greatly appreciate your help!

Can you please share the screenshot where you added the below code:

1 Like
<script>
  (() => {
    document.querySelectorAll("nav.header__inline-menu details").forEach(details => {
      const summary = details.querySelector("summary");
      const parentLink = details.querySelector("a"); 

      if (!summary || !parentLink) return;

      summary.addEventListener("click", e => {
         if (e.target.closest("svg")) return;

         window.location.href = parentLink.href;
      });
    });
  })();
</script>
1 Like

Sure! Here it is:

It should work but if it is not working you can add delay to script. Please try below:

1 Like

<script>
  setTimeout(() => {
    (() => {
      document.querySelectorAll("nav.header__inline-menu details").forEach(details => {
        const summary = details.querySelector("summary");
        const parentLink = details.querySelector("a"); 

        if (!summary || !parentLink) return;

        summary.addEventListener("click", e => {
           if (e.target.closest("svg")) return;

          window.location.href = parentLink.href;
        });
      });
    })();
  }, 500); 
</script>

1 Like

or can try below as well:

<script>
(function waitForMenu() {
  const menu = document.querySelector("nav.header__inline-menu");
  if (!menu) {
    // Menu not yet in DOM, try again in 100ms
    setTimeout(waitForMenu, 100);
    return;
  }

  // Menu exists, attach click handlers
  document.querySelectorAll("nav.header__inline-menu details").forEach(details => {
    const summary = details.querySelector("summary");
    const parentLink = details.querySelector("a"); 

    if (!summary || !parentLink) return;

    summary.addEventListener("click", e => {
      // Allow arrow/caret toggle
      if (e.target.closest("svg")) return;

      // Redirect to parent link
      window.location.href = parentLink.href;
    });
  });
})();
</script>

1 Like

I tried both, but still nothing :frowning:

Hey! I believe you still have an access to my website.

Products – DrawWithDi

I have checked the view source but the script is not there. Can you please make sure you added the code at correct file.