You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
5.2 KiB
216 lines
5.2 KiB
(function() { |
|
|
|
/** |
|
* Debounce |
|
* |
|
* @param {Function} func |
|
* @param {number} wait |
|
* @param {boolean} immediate |
|
*/ |
|
function debounce(func, wait, immediate) { |
|
'use strict'; |
|
|
|
var timeout; |
|
wait = (typeof wait !== 'undefined') ? wait : 20; |
|
immediate = (typeof immediate !== 'undefined') ? immediate : true; |
|
|
|
return function() { |
|
|
|
var context = this, args = arguments; |
|
var later = function() { |
|
timeout = null; |
|
|
|
if (!immediate) { |
|
func.apply(context, args); |
|
} |
|
}; |
|
|
|
var callNow = immediate && !timeout; |
|
|
|
clearTimeout(timeout); |
|
timeout = setTimeout(later, wait); |
|
|
|
if (callNow) { |
|
func.apply(context, args); |
|
} |
|
}; |
|
} |
|
|
|
/** |
|
* Prepends an element to a container. |
|
* |
|
* @param {Element} container |
|
* @param {Element} element |
|
*/ |
|
function prependElement(container, element) { |
|
if (container.firstChild.nextSibling) { |
|
return container.insertBefore(element, container.firstChild.nextSibling); |
|
} else { |
|
return container.appendChild(element); |
|
} |
|
} |
|
|
|
/** |
|
* Shows an element by adding a hidden className. |
|
* |
|
* @param {Element} element |
|
*/ |
|
function showButton(element) { |
|
// classList.remove is not supported in IE11 |
|
element.className = element.className.replace('is-empty', ''); |
|
} |
|
|
|
/** |
|
* Hides an element by removing the hidden className. |
|
* |
|
* @param {Element} element |
|
*/ |
|
function hideButton(element) { |
|
// classList.add is not supported in IE11 |
|
if (!element.classList.contains('is-empty')) { |
|
element.className += ' is-empty'; |
|
} |
|
} |
|
|
|
/** |
|
* Returns the currently available space in the menu container. |
|
* |
|
* @returns {number} Available space |
|
*/ |
|
function getAvailableSpace( button, container ) { |
|
return container.offsetWidth - button.offsetWidth - 22; |
|
} |
|
|
|
/** |
|
* Returns whether the current menu is overflowing or not. |
|
* |
|
* @returns {boolean} Is overflowing |
|
*/ |
|
function isOverflowingNavivation( list, button, container ) { |
|
return list.offsetWidth > getAvailableSpace( button, container ); |
|
} |
|
|
|
/** |
|
* Set menu container variable |
|
*/ |
|
var navContainer = document.querySelector('.main-navigation'); |
|
var breaks = []; |
|
|
|
/** |
|
* Let’s bail if we our menu doesn't exist |
|
*/ |
|
if ( ! navContainer ) { |
|
return; |
|
} |
|
|
|
/** |
|
* Refreshes the list item from the menu depending on the menu size |
|
*/ |
|
function updateNavigationMenu( container ) { |
|
|
|
/** |
|
* Let’s bail if our menu is empty |
|
*/ |
|
if ( ! container.parentNode.querySelector('.main-menu[id]') ) { |
|
return; |
|
} |
|
|
|
// Adds the necessary UI to operate the menu. |
|
var visibleList = container.parentNode.querySelector('.main-menu[id]'); |
|
var hiddenList = visibleList.parentNode.nextElementSibling.querySelector('.hidden-links'); |
|
var toggleButton = visibleList.parentNode.nextElementSibling.querySelector('.main-menu-more-toggle'); |
|
|
|
if ( isOverflowingNavivation( visibleList, toggleButton, container ) ) { |
|
|
|
// Record the width of the list |
|
breaks.push( visibleList.offsetWidth ); |
|
// Move last item to the hidden list |
|
prependElement( hiddenList, ! visibleList.lastChild || null === visibleList.lastChild ? visibleList.previousElementSibling : visibleList.lastChild ); |
|
// Show the toggle button |
|
showButton( toggleButton ); |
|
|
|
} else { |
|
|
|
// There is space for another item in the nav |
|
if ( getAvailableSpace( toggleButton, container ) > breaks[breaks.length - 1] ) { |
|
// Move the item to the visible list |
|
visibleList.appendChild( hiddenList.firstChild.nextSibling ); |
|
breaks.pop(); |
|
} |
|
|
|
// Hide the dropdown btn if hidden list is empty |
|
if (breaks.length < 2) { |
|
hideButton( toggleButton ); |
|
} |
|
} |
|
|
|
// Recur if the visible list is still overflowing the nav |
|
if ( isOverflowingNavivation( visibleList, toggleButton, container ) ) { |
|
updateNavigationMenu( container ); |
|
} |
|
} |
|
|
|
/** |
|
* Run our priority+ function as soon as the document is `ready` |
|
*/ |
|
document.addEventListener( 'DOMContentLoaded', function() { |
|
|
|
updateNavigationMenu( navContainer ); |
|
|
|
// Also, run our priority+ function on selective refresh in the customizer |
|
var hasSelectiveRefresh = ( |
|
'undefined' !== typeof wp && |
|
wp.customize && |
|
wp.customize.selectiveRefresh && |
|
wp.customize.navMenusPreview.NavMenuInstancePartial |
|
); |
|
|
|
if ( hasSelectiveRefresh ) { |
|
// Re-run our priority+ function on Nav Menu partial refreshes |
|
wp.customize.selectiveRefresh.bind( 'partial-content-rendered', function ( placement ) { |
|
|
|
var isNewNavMenu = ( |
|
placement && |
|
placement.partial.id.includes( 'nav_menu_instance' ) && |
|
'null' !== placement.container[0].parentNode && |
|
placement.container[0].parentNode.classList.contains( 'main-navigation' ) |
|
); |
|
|
|
if ( isNewNavMenu ) { |
|
updateNavigationMenu( placement.container[0].parentNode ); |
|
} |
|
}); |
|
} |
|
}); |
|
|
|
/** |
|
* Run our priority+ function on load |
|
*/ |
|
window.addEventListener( 'load', function() { |
|
updateNavigationMenu( navContainer ); |
|
}); |
|
|
|
/** |
|
* Run our priority+ function every time the window resizes |
|
*/ |
|
var isResizing = false; |
|
window.addEventListener( 'resize', |
|
debounce( function() { |
|
if ( isResizing ) { |
|
return; |
|
} |
|
|
|
isResizing = true; |
|
setTimeout( function() { |
|
updateNavigationMenu( navContainer ); |
|
isResizing = false; |
|
}, 150 ); |
|
} ) |
|
); |
|
|
|
/** |
|
* Run our priority+ function |
|
*/ |
|
updateNavigationMenu( navContainer ); |
|
|
|
})();
|
|
|