Instantly share code, notes, and snippets.
Created
June 25, 2020 14:16
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save amberhinds/b7b84df5a54071db7c703cf9e91d6f67 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This script adds the accessibility-ready responsive menus Genesis Framework child themes. | |
* | |
* @author StudioPress | |
* @link https://github.com/copyblogger/responsive-menus | |
* @version 1.1.3 | |
* @license GPL-3.0-or-later | |
*/ | |
( function ( document, $, undefined ) { | |
'use strict'; | |
var genesisMenuParams = typeof genesis_responsive_menu === 'undefined' ? '' : genesis_responsive_menu, | |
genesisMenusUnchecked = genesisMenuParams.menuClasses, | |
genesisMenus = {}, | |
menusToCombine = []; | |
/** | |
* Validate the menus passed by the theme with what's being loaded on the page, | |
* and pass the new and accurate information to our new data. | |
* @param {genesisMenusUnchecked} Raw data from the localized script in the theme. | |
* @return {array} genesisMenus array gets populated with updated data. | |
* @return {array} menusToCombine array gets populated with relevant data. | |
*/ | |
$.each( genesisMenusUnchecked, function( group ) { | |
// Mirror our group object to populate. | |
genesisMenus[group] = []; | |
// Loop through each instance of the specified menu on the page. | |
$.each( this, function( key, value ) { | |
var menuString = value, | |
$menu = $(value); | |
// If there is more than one instance, append the index and update array. | |
if ( $menu.length > 1 ) { | |
$.each( $menu, function( key, value ) { | |
var newString = menuString + '-' + key; | |
$(this).addClass( newString.replace( '.','' ) ); | |
genesisMenus[group].push( newString ); | |
if ( 'combine' === group ) { | |
menusToCombine.push( newString ); | |
} | |
}); | |
} else if ( $menu.length == 1 ) { | |
genesisMenus[group].push( menuString ); | |
if ( 'combine' === group ) { | |
menusToCombine.push( menuString ); | |
} | |
} | |
}); | |
}); | |
// Make sure there is something to use for the 'others' array. | |
if ( typeof genesisMenus.others == 'undefined' ) { | |
genesisMenus.others = []; | |
} | |
// If there's only one menu on the page for combining, push it to the 'others' array and nullify our 'combine' variable. | |
if ( menusToCombine.length == 1 ) { | |
genesisMenus.others.push( menusToCombine[0] ); | |
genesisMenus.combine = null; | |
menusToCombine = null; | |
} | |
var genesisMenu = {}, | |
mainMenuButtonClass = 'menu-toggle', | |
subMenuButtonClass = 'sub-menu-toggle', | |
responsiveMenuClass = 'genesis-responsive-menu'; | |
// Initialize. | |
genesisMenu.init = function() { | |
// Exit early if there are no menus to do anything. | |
if ( $( _getAllMenusArray() ).length == 0 ) { | |
return; | |
} | |
var menuIconClass = typeof genesisMenuParams.menuIconClass !== 'undefined' ? genesisMenuParams.menuIconClass : 'dashicons-before dashicons-menu', | |
subMenuIconClass = typeof genesisMenuParams.subMenuIconClass !== 'undefined' ? genesisMenuParams.subMenuIconClass : 'dashicons-before dashicons-arrow-down-alt2', | |
toggleButtons = { | |
menu : $( '<button />', { | |
'class' : mainMenuButtonClass, | |
'aria-expanded' : false, | |
'aria-pressed' : false | |
} ) | |
.append( genesisMenuParams.mainMenu ) | |
.append( $( '<span />' ) ), | |
submenu : $( '<button />', { | |
'class' : subMenuButtonClass, | |
'aria-expanded' : false, | |
'aria-pressed' : false | |
} ) | |
.append( $( '<span />', { | |
'class' : 'screen-reader-text', | |
'text' : genesisMenuParams.subMenu | |
} ) ) | |
}; | |
// Add the responsive menu class to the active menus. | |
_addResponsiveMenuClass(); | |
// Add the main nav button to the primary menu, or exit the plugin. | |
_addMenuButtons( toggleButtons ); | |
// Setup additional classes. | |
$( '.' + mainMenuButtonClass ).addClass( menuIconClass ); | |
$( '.' + subMenuButtonClass ).addClass( subMenuIconClass ); | |
$( '.' + mainMenuButtonClass ).on( 'click.genesisMenu-mainbutton', _mainmenuToggle ).each( _addClassID ); | |
$( '.' + subMenuButtonClass ).on( 'click.genesisMenu-subbutton', _submenuToggle ); | |
$( window ).on( 'resize.genesisMenu', _doResize ).triggerHandler( 'resize.genesisMenu' ); | |
}; | |
/** | |
* Add menu toggle button to appropriate menus. | |
* @param {toggleButtons} Object of menu buttons to use for toggles. | |
*/ | |
function _addMenuButtons( toggleButtons ) { | |
// Apply sub menu toggle to each sub-menu found in the menuList. | |
$( _getMenuSelectorString( genesisMenus ) ).find( '.sub-menu' ).before( toggleButtons.submenu ); | |
if ( menusToCombine !== null ) { | |
var menusToToggle = genesisMenus.others.concat( menusToCombine[0] ); | |
// Only add menu button the primary menu and navs NOT in the combine variable. | |
$( _getMenuSelectorString( menusToToggle ) ).before( toggleButtons.menu ); | |
} else { | |
// Apply the main menu toggle to all menus in the list. | |
$( _getMenuSelectorString( genesisMenus.others ) ).before( toggleButtons.menu ); | |
} | |
} | |
/** | |
* Add the responsive menu class. | |
*/ | |
function _addResponsiveMenuClass() { | |
$( _getMenuSelectorString( genesisMenus ) ).addClass( responsiveMenuClass ); | |
} | |
/** | |
* Execute our responsive menu functions on window resizing. | |
*/ | |
function _doResize() { | |
var buttons = $( 'button[id^="genesis-mobile-"]' ).attr( 'id' ); | |
if ( typeof buttons === 'undefined' ) { | |
return; | |
} | |
_maybeClose( buttons ); | |
_superfishToggle( buttons ); | |
_changeSkipLink( buttons ); | |
_combineMenus( buttons ); | |
} | |
/** | |
* Add the nav- class of the related navigation menu as | |
* an ID to associated button (helps target specific buttons outside of context). | |
*/ | |
function _addClassID() { | |
var $this = $( this ), | |
nav = $this.next( 'nav' ), | |
id = 'class'; | |
$this.attr( 'id', 'genesis-mobile-' + $( nav ).attr( id ).match( /nav-\w*\b/ ) ); | |
} | |
/** | |
* Combine our menus if the mobile menu is visible. | |
* @params buttons | |
*/ | |
function _combineMenus( buttons ){ | |
// Exit early if there are no menus to combine. | |
if ( menusToCombine == null ) { | |
return; | |
} | |
// Split up the menus to combine based on order of appearance in the array. | |
var primaryMenu = menusToCombine[0], | |
combinedMenus = $( menusToCombine ).filter( function(index) { if ( index > 0 ) { return index; } }); | |
// If the responsive menu is active, append items in 'combinedMenus' object to the 'primaryMenu' object. | |
if ( 'none' !== _getDisplayValue( buttons ) ) { | |
$.each( combinedMenus, function( key, value ) { | |
$(value).find( '.menu > li' ).addClass( 'moved-item-' + value.replace( '.','' ) ).appendTo( primaryMenu + ' ul.genesis-nav-menu' ); | |
}); | |
$( _getMenuSelectorString( combinedMenus ) ).hide(); | |
} else { | |
$( _getMenuSelectorString( combinedMenus ) ).show(); | |
$.each( combinedMenus, function( key, value ) { | |
$( '.moved-item-' + value.replace( '.','' ) ).appendTo( value + ' ul.genesis-nav-menu' ).removeClass( 'moved-item-' + value.replace( '.','' ) ); | |
}); | |
} | |
} | |
/** | |
* Action to happen when the main menu button is clicked. | |
*/ | |
function _mainmenuToggle() { | |
var $this = $( this ); | |
_toggleAria( $this, 'aria-pressed' ); | |
_toggleAria( $this, 'aria-expanded' ); | |
$this.toggleClass( 'activated' ); | |
//$this.next( 'nav' ).slideToggle( 'fast' ); | |
$this.next( 'nav' ).toggleClass( 'activated' ); | |
} | |
/** | |
* Action for submenu toggles. | |
*/ | |
function _submenuToggle() { | |
var $this = $( this ), | |
others = $this.closest( '.menu-item' ).siblings(); | |
_toggleAria( $this, 'aria-pressed' ); | |
_toggleAria( $this, 'aria-expanded' ); | |
$this.toggleClass( 'activated' ); | |
$this.next( '.sub-menu' ).slideToggle( 'fast' ); | |
others.find( '.' + subMenuButtonClass ).removeClass( 'activated' ).attr( 'aria-pressed', 'false' ); | |
others.find( '.sub-menu' ).slideUp( 'fast' ); | |
} | |
/** | |
* Activate/deactivate superfish. | |
* @params buttons | |
*/ | |
function _superfishToggle( buttons ) { | |
var _superfish = $( '.' + responsiveMenuClass + ' .js-superfish' ), | |
$args = 'destroy'; | |
if ( typeof _superfish.superfish !== 'function' ) { | |
return; | |
} | |
if ( 'none' === _getDisplayValue( buttons ) ) { | |
$args = { | |
'delay': 100, | |
'animation': {'opacity': 'show', 'height': 'show'}, | |
'dropShadows': false, | |
'speed': 'fast' | |
}; | |
} | |
_superfish.superfish( $args ); | |
} | |
/** | |
* Modify skip link to match mobile buttons. | |
* @param buttons | |
*/ | |
function _changeSkipLink( buttons ) { | |
// Start with an empty array. | |
var menuToggleList = _getAllMenusArray(); | |
// Exit out if there are no menu items to update. | |
if ( ! $( menuToggleList ).length > 0 ) { | |
return; | |
} | |
$.each( menuToggleList, function ( key, value ) { | |
var newValue = value.replace( '.', '' ), | |
startLink = 'genesis-' + newValue, | |
endLink = 'genesis-mobile-' + newValue; | |
if ( 'none' == _getDisplayValue( buttons ) ) { | |
startLink = 'genesis-mobile-' + newValue; | |
endLink = 'genesis-' + newValue; | |
} | |
var $item = $( '.genesis-skip-link a[href="#' + startLink + '"]' ); | |
if ( menusToCombine !== null && value !== menusToCombine[0] ) { | |
$item.toggleClass( 'skip-link-hidden' ); | |
} | |
if ( $item.length > 0 ) { | |
var link = $item.attr( 'href' ); | |
link = link.replace( startLink, endLink ); | |
$item.attr( 'href', link ); | |
} else { | |
return; | |
} | |
}); | |
} | |
/** | |
* Close all the menu toggles if buttons are hidden. | |
* @param buttons | |
*/ | |
function _maybeClose( buttons ) { | |
if ( 'none' !== _getDisplayValue( buttons ) ) { | |
return true; | |
} | |
$( '.' + mainMenuButtonClass + ', .' + responsiveMenuClass + ' .sub-menu-toggle' ) | |
.removeClass( 'activated' ) | |
.attr( 'aria-expanded', false ) | |
.attr( 'aria-pressed', false ); | |
$( '.' + responsiveMenuClass + ', .' + responsiveMenuClass + ' .sub-menu' ) | |
.attr( 'style', '' ); | |
} | |
/** | |
* Generic function to get the display value of an element. | |
* @param {id} $id ID to check | |
* @return {string} CSS value of display property | |
*/ | |
function _getDisplayValue( $id ) { | |
var element = document.getElementById( $id ), | |
style = window.getComputedStyle( element ); | |
return style.getPropertyValue( 'display' ); | |
} | |
/** | |
* Toggle aria attributes. | |
* @param {button} $this passed through | |
* @param {aria-xx} attribute aria attribute to toggle | |
* @return {bool} from _ariaReturn | |
*/ | |
function _toggleAria( $this, attribute ) { | |
$this.attr( attribute, function( index, value ) { | |
return 'false' === value; | |
}); | |
} | |
/** | |
* Helper function to return a comma separated string of menu selectors. | |
* @param {itemArray} Array of menu items to loop through. | |
* @param {ignoreSecondary} boolean of whether to ignore the 'secondary' menu item. | |
* @return {string} Comma-separated string. | |
*/ | |
function _getMenuSelectorString( itemArray ) { | |
var itemString = $.map( itemArray, function( value, key ) { | |
return value; | |
}); | |
return itemString.join( ',' ); | |
} | |
/** | |
* Helper function to return a group array of all the menus in | |
* both the 'others' and 'combine' arrays. | |
* @return {array} Array of all menu items as class selectors. | |
*/ | |
function _getAllMenusArray() { | |
// Start with an empty array. | |
var menuList = []; | |
// If there are menus in the 'menusToCombine' array, add them to 'menuList'. | |
if ( menusToCombine !== null ) { | |
$.each( menusToCombine, function( key, value ) { | |
menuList.push( value.valueOf() ); | |
}); | |
} | |
// Add menus in the 'others' array to 'menuList'. | |
$.each( genesisMenus.others, function( key, value ) { | |
menuList.push( value.valueOf() ); | |
}); | |
if ( menuList.length > 0 ) { | |
return menuList; | |
} else { | |
return null; | |
} | |
} | |
$(document).ready(function () { | |
if ( _getAllMenusArray() !== null ) { | |
genesisMenu.init(); | |
} | |
}); | |
})( document, jQuery ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment