简体   繁体   中英

Focus controlled dropdown menu closes when children are focused

I have a dropdown menu which uses the focus and blur events to open and close the menu. Currently, everything works fine unless you focus on an element inside the menu, thus causing it to close because of the trigger element .menu-trigger losing focus.

The intended behaviour is for the menu to close when a user clicks outside of the .menu-trigger element, but currently it also closes when an element inside is focused. Is there a way to prevent the menu from closing if an element inside .menu-trigger is focused?

 function menuOpen(options) { options = $.extend(true, { triggerSelector: null, relativeContentSl: '.defaultselector', }, options || {}); const $TRIGGER = $(options.triggerSelector); $TRIGGER.addClass('is-open').find(options.relativeContentSl).removeClass('hide'); } function menuClose(selector) { $(selector).removeClass('is-open').find('.menu-content').addClass('hide'); } const TRIGGER_SELECTOR = '.menu-trigger'; const CONTENT_SELECTOR = '.menu-content'; $('body').on('click', '.menu-trigger:not(.is-open)', function (e) { menuOpen({ triggerSelector: this, relativeContentSl: CONTENT_SELECTOR, }); }) $('body').on('blur', TRIGGER_SELECTOR, function () { menuClose(this); }) 
 .hide { display: none; } .menu-content { border: 2px solid red; padding: 5px; } 
 <div class="menu-trigger" tabindex="1"> <div class="menu-btn"> Click Me </div> <div class="menu-content hide"> <!-- example content --> <button>Clicking this closes the menu</button> <p>Clicking this doesn't</p> </div> </div> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> 

I've already tried using event.stopPropagation() but this prevents any intended behaviour inside the menu from working which I don't want.

I'm not sure about testing whether an element inside the trigger element is focused but you can check if it's being hovered over by wrapping your menuClose() function like so:

if (!$(this).is(':hover')) {
    menuClose(this);
}

Surprisingly, this also works great on mobile, here's the full snippet to prove it:

 function menuOpen(options) { options = $.extend(true, { triggerSelector: null, relativeContentSl: '.defaultselector', }, options || {}); const $TRIGGER = $(options.triggerSelector); $TRIGGER.addClass('is-open').find(options.relativeContentSl).removeClass('hide'); } function menuClose(selector) { $(selector).removeClass('is-open').find('.menu-content').addClass('hide'); } const TRIGGER_SELECTOR = '.menu-trigger'; const CONTENT_SELECTOR = '.menu-content'; $('body').on('click', '.menu-trigger:not(.is-open)', function (e) { menuOpen({ triggerSelector: this, relativeContentSl: CONTENT_SELECTOR, }); }); $('body').on('blur', TRIGGER_SELECTOR, function () { if (!$(this).is(':hover')) { menuClose(this); } }); 
 .hide { display: none; } .menu-content { border: 2px solid red; padding: 5px; } 
 <div class="menu-trigger" tabindex="1"> <div class="menu-btn"> Click Me </div> <div class="menu-content hide"> <!-- example content --> <button>Clicking this now doesn't close the menu!</button> <p>Clicking this doesn't</p> </div> </div> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM