Strange Mobile Navigation Issue

SOLVE
Highlighted
Regular Contributor

I am working on a new webiste on Hubspot CMS for our company and I am experiencing a very strange mobile navigation behvaior. The child menus work fine if you click the + / - signs appropriately on the parent menu items, however, if you click the heading of the parent item the child menu items DO expand but they do not function as expected. Instead, these child menu items simply collapse the menu back up and do not navigate. If you get to the child menu item via the + sign then the links work appropriately.


URL:  (Migrating to permanent URL. Will update this for future reference in the next few hours) Try it for yourself. Anyone experience this?

 

ADDITIONAL NOTE: On iPhone, this does NOT appear to occur. This seems to occur on Chrome or Edge Emulators (F12) and it also occurs on Android (Edge or Chrome). On iOS it does not appear to happen.

Reply
0 Upvotes
1 Accepted solution

Accepted Solutions
Highlighted
Regular Contributor

The final JS to get our menu working as best as we can is below. There are still two or three oddities that I am pretty sure are caused by poor/faulty coding with Hubspots default menu code. Hopefully they can fix it. One note about this solution is during times of heavy load/slow speeds you can see a slide down, up, down if you look really closely. In testing only one of my testers noticed (and he's the pickiest person I know! lol)

 

$(function() {

    /** 
     * Mobile Nav
     *
     * Hubspot Standard Toggle Menu
     */
      
    $('.custom-menu-primary').addClass('js-enabled');
    
    /* Mobile button with three lines icon */
        $('.custom-menu-primary .hs-menu-wrapper').before('<div class="mobile-trigger"><i></i></div>');
        
    /* Uncomment for mobile button that says 'MENU' 
        $('.custom-menu-primary .hs-menu-wrapper').before('<div class="mobile-trigger">MENU</div>');
    */
    
    $('.custom-menu-primary .flyouts .hs-item-has-children > a').after('<div class="child-trigger"><i></i></div>');
    $('.mobile-trigger').click(function() {
        $(this).next('.custom-menu-primary .hs-menu-wrapper').slideToggle(250);
        $('body').toggleClass('mobile-open');
        $('.child-trigger').removeClass('child-open');
        $('.hs-menu-children-wrapper').slideUp(250);
        return false;
     });

    $('.child-trigger').click(function() {
     expandMenu(this); 
    });
    
    $('.custom-menu-primary .flyouts .hs-item-has-children > a').click(function(event) {    
      
      var t = document.querySelector(".hs-menu-wrapper.flyouts > ul > li > ul.open-menu-list"), r = this.parentNode.querySelector("ul");
      if (t) {
        t.removeAttribute("style");
        t.classList.remove("open-menu-list")
      }
      t && t.parentNode.querySelector("a").setAttribute("aria-expanded", "false");
      
      expandMenu($(this).next('.child-trigger'));
      
      return false;
    });  
  
  function expandMenu(childTriggerElement) {
      $(childTriggerElement).parent().siblings('.hs-item-has-children').find('.child-trigger').removeClass('child-open');
      $(childTriggerElement).parent().siblings('.hs-item-has-children').find('.hs-menu-children-wrapper').slideUp(250);
      $(childTriggerElement).next('.hs-menu-children-wrapper').slideToggle(250);
      $(childTriggerElement).next('.hs-menu-children-wrapper').children('.hs-item-has-children').find('.hs-menu-children-wrapper').slideUp(250);
      $(childTriggerElement).next('.hs-menu-children-wrapper').children('.hs-item-has-children').find('.child-trigger').removeClass('child-open');
      $(childTriggerElement).toggleClass('child-open');
      return false;
    }

});

  

17 Replies 17
Highlighted
Regular Contributor

Update: I'm somewhat confident that this is a bug with the navigation out of the box from Hubspot CMS. I have been able to replicate it in a simple example using EXACT code from the tutorial. Some help would be great here. I've tried unbinding events, removing classes, etc. to disable the functionality. The closest I can get is a complex chain of slide up and down events that lead to a very poor experience.

Reply
0 Upvotes
Highlighted
Regular Advisor | Partner

Hey @rmmoore80 

 

I've run into this myself, and though we did not end up remedying it (went a different route) I might be able to shed some light.

 

If you inspect the menus you'll see the two menu elements both have event listeners on them. The first is the parent link for the child list. The eventlisteners attached are a focus and mouseout function. See below:

Screeenshot - 2019-10-21 at 10.48.06 AM.png

So what look like is happening is that the browser is catching the click on the parent link as a focus, because a click listener has not been attached. This should explain the functionality.

 

To accomplish your requirement/expectation, you'll have to go through the JS that the tutorial provided and modify/add event listeners to fire the same function that the "child-trigger" click listerner fires. Or make note of the JS functions and write your own.

 

Be sure to test for viewport sizes and modify the JS accordingly.

Highlighted
Regular Contributor

This melds with what I discovered. I tried having the parent link click the +/- signs but the mouseout was potentially causing additional issues. I also couldn't get the slideup/down right from the parent link. If I manage to get that JS correct based on what you have said here, I will let you know and provide final JS.

 

Highlighted
Regular Advisor | Partner

Looking forward to seeing what you come up with!

Reply
0 Upvotes
Highlighted
Regular Contributor

I was able to solve the problem by adding the following code snippet. You can see at my link that it now functions properly. The ONLY catch is that I seem to still have a slight desktop "oddity" if the user hovers AND clicks a link. That I am okay with because it kind of self corrects. This code fixed my mobile menus:

 

$('.custom-menu-primary .flyouts .hs-item-has-children > a').focus(function(event) {
event.stopPropagation();
event.preventDefault();
return false;
});

 

FYI - I am giving you solution credit. Your tip was what I needed to fix it. Thank you!

Reply
0 Upvotes
Highlighted
Regular Contributor

Hang on, it seems to have reverted back and no longer functions. Ugh! I swear it was working 5 minutes ago. The problem IS the "focus" event. If you disable the project.js focus even in the browser, it works.

Reply
0 Upvotes
Highlighted
Regular Contributor

Attempting to find away to prevent the focus event from project.js from firing.

Reply
0 Upvotes
Highlighted
Regular Contributor

If you load up the site and enable the developer tools and then disable the "focus" event listener attached by project.js, then it works just fine. Re-enable the "project.js" focus event and the menu breaks again. I'm trying to replicate this "fix" in code but no luck so far. My previous "fix" must have been a fluke.

Reply
0 Upvotes
Highlighted
Regular Advisor | Partner

What about using .unbind() to remover the focus listener?

Doc here

Regular Contributor

I'm trying that and "off" from jQuery right now. No luck right now.

Highlighted
Regular Advisor | Partner

Good call. Just noticed the depriciated notice!

Reply
0 Upvotes
Highlighted
Regular Contributor

FYI.  Here is the conflicting code itself:

 

    var e = (document.querySelector(".hs-menu-wrapper.flyouts"),
    document.querySelectorAll(".hs-menu-wrapper.flyouts > ul > li"))
      , t = document.querySelectorAll(".hs-menu-wrapper.flyouts > ul > li > ul > li");
    Array.prototype.forEach.call(e, function(e, t) {
        e.querySelector("a").addEventListener("focus", function(e) {
            var t = document.querySelector(".hs-menu-wrapper.flyouts > ul > li > ul.open-menu-list")
              , r = this.parentNode.querySelector("ul");
            if (t) {
                t.removeAttribute("style");
                t.classList.remove("open-menu-list")
            }
            t && t.parentNode.querySelector("a").setAttribute("aria-expanded", "false");
            if (r) {
                r.style.visibility = "visible";
                r.style.opacity = "1";
                r.style.display = "block";
                r.classList.add("open-menu-list")
            }
            r && this.setAttribute("aria-expanded", "true")
        });
Highlighted
Regular Contributor

I believe I have it fixed. Doing extensive testing through my team to validate before I post here. Stay tuned.

Highlighted
Regular Contributor

The final JS to get our menu working as best as we can is below. There are still two or three oddities that I am pretty sure are caused by poor/faulty coding with Hubspots default menu code. Hopefully they can fix it. One note about this solution is during times of heavy load/slow speeds you can see a slide down, up, down if you look really closely. In testing only one of my testers noticed (and he's the pickiest person I know! lol)

 

$(function() {

    /** 
     * Mobile Nav
     *
     * Hubspot Standard Toggle Menu
     */
      
    $('.custom-menu-primary').addClass('js-enabled');
    
    /* Mobile button with three lines icon */
        $('.custom-menu-primary .hs-menu-wrapper').before('<div class="mobile-trigger"><i></i></div>');
        
    /* Uncomment for mobile button that says 'MENU' 
        $('.custom-menu-primary .hs-menu-wrapper').before('<div class="mobile-trigger">MENU</div>');
    */
    
    $('.custom-menu-primary .flyouts .hs-item-has-children > a').after('<div class="child-trigger"><i></i></div>');
    $('.mobile-trigger').click(function() {
        $(this).next('.custom-menu-primary .hs-menu-wrapper').slideToggle(250);
        $('body').toggleClass('mobile-open');
        $('.child-trigger').removeClass('child-open');
        $('.hs-menu-children-wrapper').slideUp(250);
        return false;
     });

    $('.child-trigger').click(function() {
     expandMenu(this); 
    });
    
    $('.custom-menu-primary .flyouts .hs-item-has-children > a').click(function(event) {    
      
      var t = document.querySelector(".hs-menu-wrapper.flyouts > ul > li > ul.open-menu-list"), r = this.parentNode.querySelector("ul");
      if (t) {
        t.removeAttribute("style");
        t.classList.remove("open-menu-list")
      }
      t && t.parentNode.querySelector("a").setAttribute("aria-expanded", "false");
      
      expandMenu($(this).next('.child-trigger'));
      
      return false;
    });  
  
  function expandMenu(childTriggerElement) {
      $(childTriggerElement).parent().siblings('.hs-item-has-children').find('.child-trigger').removeClass('child-open');
      $(childTriggerElement).parent().siblings('.hs-item-has-children').find('.hs-menu-children-wrapper').slideUp(250);
      $(childTriggerElement).next('.hs-menu-children-wrapper').slideToggle(250);
      $(childTriggerElement).next('.hs-menu-children-wrapper').children('.hs-item-has-children').find('.hs-menu-children-wrapper').slideUp(250);
      $(childTriggerElement).next('.hs-menu-children-wrapper').children('.hs-item-has-children').find('.child-trigger').removeClass('child-open');
      $(childTriggerElement).toggleClass('child-open');
      return false;
    }

});

  

Highlighted
Regular Contributor

@Kevin-C  How do you want me to accept the solution? I want to give you credit for your help but I also want future people to find the final code quickly.

Reply
0 Upvotes
Highlighted
Regular Advisor | Partner

Awesome! Really enjoyed working with you @rmmoore80 .

 

As far as credit/answer goes, mark yours as the answer. As you said others may need this info in the future.

tumblr_oredhxbrvY1qmt01xo3_500.g.jpg

I'm about finding the solutions and the process of finding them rather than gaining the fake internet credit money lol! But thank you!

Highlighted
Regular Contributor

I appreciate your help and look forward to more participating in the Hubspot developer community! I am enjoying this platform!

Reply
0 Upvotes