Reputation: 1
I'm working on customizing the WordPress admin menu to have a smooth, expandable/collapsible behavior on click by adding the CSS and JavaScript.
Goal: Implement a click-to-toggle menu where:
The current code almost works, but there's a noticeable flicker (a brief collapse and re-expansion) when clicking a submenu item, and sometimes when repeatedly clicking the same top-level menu item. This appears to be caused by the JavaScript code re-evaluating the entire menu structure on every click within the menu, even when it's not necessary to change the menu's open/closed state.
I've tried numerous variations of JavaScript/jQuery code to manage the menu's state and handle clicks.
Here's the code which if you use on any wordpress menu you will be able to reporduce the issue.
(function($) {
$(document).ready(function() {
$('#adminmenu .wp-submenu').hide();
$('#adminmenu > li.wp-has-submenu > a').off();
$('#adminmenu > li.wp-has-submenu > a').on('click', function(e) {
e.preventDefault();
var $menuItem = $(this).parent();
var $submenu = $menuItem.find('.wp-submenu').first();
if ($submenu.is(':visible')) {
$submenu.slideUp(150, function() {
$menuItem.removeClass('opensub');
});
} else {
$('#adminmenu .wp-submenu:visible').slideUp(150, function() {
$(this).parent().removeClass('opensub');
});
$submenu.slideDown(150, function() {
$menuItem.addClass('opensub');
});
}
});
var $currentMenuItem = $('#adminmenu li.current');
if ($currentMenuItem.length) {
var $parentMenu = $currentMenuItem.closest('li.wp-has-submenu');
$parentMenu.addClass('opensub');
$parentMenu.find('.wp-submenu').show();
}
});
})(jQuery);
#adminmenu li.wp-has-submenu .wp-submenu {
position: static !important;
display: none;
box-shadow: none !important;
}
#adminmenu .wp-not-current-submenu .wp-submenu,
.folded #adminmenu .wp-has-current-submenu .wp-submenu {
border-left-width: 0 !important;
border: 0 !important;
}
#adminmenu .wp-has-current-submenu ul>li>a, .folded #adminmenu li.menu-top .wp-submenu>li>a {
padding: 5px 14px !important;
}
Upvotes: 0
Views: 34
Reputation: 857
The flickering is because you are first hiding all the submenus with $('#adminmenu .wp-submenu').hide();
including the active one. Then you target the active one and show it with $parentMenu.find('.wp-submenu').show();
.
Javascript runs on the client after the page is rendered and no matter how fast your code is, even miliseconds will be noticeable.
Luckily, you can achieve the same result with pure CSS, because WordPress has classes already in place, to identify menu items with active items or not.
Change your jQuery code to this:
(function ($) {
$(document).ready(function () {
const $adminMenu = $('#adminmenu');
const $currentSubmenu = $adminMenu.find('li.wp-has-current-submenu');
$currentSubmenu.addClass('opensub');
$adminMenu.on('click', '> li.wp-has-submenu > a', function (e) {
e.preventDefault();
const $menuItem = $(this).parent();
const $submenu = $menuItem.find('.wp-submenu').first();
$submenu.stop(true, true);
$adminMenu.find('.wp-submenu:visible').not($submenu).slideUp(150, function () {
$(this).parent().removeClass('opensub');
});
$submenu.slideToggle(150, function () {
$menuItem.toggleClass('opensub', $submenu.is(':visible'));
});
});
});
})(jQuery);
And your CSS to this:
#adminmenu li.wp-has-submenu .wp-submenu {
position: static !important;
box-shadow: none !important;
}
#adminmenu li.wp-not-current-submenu .wp-submenu {
display: none;
}
#adminmenu .wp-not-current-submenu .wp-submenu,
.folded #adminmenu .wp-has-current-submenu .wp-submenu {
border: 0 !important;
border-left-width: 0 !important;
}
#adminmenu .wp-has-current-submenu ul>li>a,
.folded #adminmenu li.menu-top .wp-submenu>li>a {
padding: 5px 14px !important;
}
.wp-has-current-submenu.wp-menu-open .wp-submenu {
display: block;
}
Upvotes: 0