navigation.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /* global shoreditchScreenReaderText */
  2. ( function( $ ) {
  3. var body, masthead, menuToggle, siteMenu, siteNavigation;
  4. function initMainNavigation( container ) {
  5. // Add dropdown toggle that displays child menu items.
  6. var dropdownToggle = $( '<button />', {
  7. 'class': 'dropdown-toggle',
  8. 'aria-expanded': false
  9. } ).append( $( '<span />', {
  10. 'class': 'screen-reader-text',
  11. text: shoreditchScreenReaderText.expand
  12. } ) );
  13. container.find( '.menu-item-has-children > a' ).after( dropdownToggle );
  14. // Toggle buttons and submenu items with active children menu items.
  15. container.find( '.current-menu-ancestor > button' ).addClass( 'toggled-on' );
  16. container.find( '.current-menu-ancestor > .sub-menu' ).addClass( 'toggled-on' );
  17. // Add menu items with submenus to aria-haspopup="true".
  18. container.find( '.menu-item-has-children' ).attr( 'aria-haspopup', 'true' );
  19. container.find( '.dropdown-toggle' ).click( function( e ) {
  20. var _this = $( this ),
  21. screenReaderSpan = _this.find( '.screen-reader-text' );
  22. e.preventDefault();
  23. _this.toggleClass( 'toggled-on' );
  24. _this.next( '.children, .sub-menu' ).toggleClass( 'toggled-on' );
  25. // jscs:disable
  26. _this.attr( 'aria-expanded', _this.attr( 'aria-expanded' ) === 'false' ? 'true' : 'false' );
  27. // jscs:enable
  28. screenReaderSpan.text( screenReaderSpan.text() === shoreditchScreenReaderText.expand ? shoreditchScreenReaderText.collapse : shoreditchScreenReaderText.expand );
  29. } );
  30. //Ensure submenus do not fall outside the left side of the window, rendering them unusable.
  31. var submenus = container.find( '.children, .sub-menu' );
  32. //Return early if no submenus exist
  33. if ( ! submenus.length ) {
  34. return;
  35. } else {
  36. submenus.each( function() {
  37. var parent = $( this ).parent( 'li' );
  38. parent.hover(
  39. function() {
  40. var submenu = $( this ).find( '> .sub-menu, > .children' );
  41. if ( $( submenu ) ) {
  42. if ( $( submenu ).offset().left < 0 ) {
  43. $( submenu ).addClass( 'offscreen' );
  44. }
  45. }
  46. },
  47. function() {
  48. $( this ).find( '> .sub-menu, > .children' ).removeClass( 'offscreen' );
  49. }
  50. );
  51. } );
  52. }
  53. }
  54. initMainNavigation( $( '.main-navigation' ) );
  55. masthead = $( '#masthead' );
  56. menuToggle = masthead.find( '#menu-toggle' );
  57. siteMenu = masthead.find( '#site-menu' );
  58. siteNavigation = masthead.find( '#site-navigation' );
  59. // Enable menuToggle.
  60. ( function() {
  61. // Return early if menuToggle is missing.
  62. if ( ! menuToggle.length ) {
  63. return;
  64. }
  65. // Add an initial values for the attribute.
  66. menuToggle.add( siteNavigation ).attr( 'aria-expanded', 'false' );
  67. menuToggle.on( 'click.shoreditch', function() {
  68. $( this ).add( siteMenu ).add( siteNavigation ).toggleClass( 'toggled-on' );
  69. // jscs:disable
  70. $( this ).add( siteMenu ).add( siteNavigation ).attr( 'aria-expanded', $( this ).add( siteNavigation ).attr( 'aria-expanded' ) === 'false' ? 'true' : 'false' );
  71. // jscs:enable
  72. } );
  73. } )();
  74. // Fix sub-menus for touch devices and better focus for hidden submenu items for accessibility.
  75. ( function() {
  76. if ( ! siteNavigation.length || ! siteNavigation.children().length ) {
  77. return;
  78. }
  79. // Toggle `focus` class to allow submenu access on tablets.
  80. function toggleFocusClassTouchScreen() {
  81. if ( window.innerWidth >= 896 ) {
  82. $( document.body ).on( 'touchstart.shoreditch', function( e ) {
  83. if ( ! $( e.target ).closest( '.main-navigation li' ).length ) {
  84. $( '.main-navigation li' ).removeClass( 'focus' );
  85. }
  86. } );
  87. siteNavigation.find( '.menu-item-has-children > a' ).on( 'touchstart.shoreditch', function( e ) {
  88. var el = $( this ).parent( 'li' );
  89. if ( ! el.hasClass( 'focus' ) ) {
  90. e.preventDefault();
  91. el.toggleClass( 'focus' );
  92. el.siblings( '.focus' ).removeClass( 'focus' );
  93. }
  94. } );
  95. } else {
  96. siteNavigation.find( '.menu-item-has-children > a' ).unbind( 'touchstart.shoreditch' );
  97. }
  98. }
  99. if ( 'ontouchstart' in window ) {
  100. $( window ).on( 'resize.shoreditch', toggleFocusClassTouchScreen );
  101. toggleFocusClassTouchScreen();
  102. }
  103. siteNavigation.find( 'a' ).on( 'focus.shoreditch blur.shoreditch', function() {
  104. $( this ).parents( '.menu-item' ).toggleClass( 'focus' );
  105. } );
  106. } )();
  107. // Add the default ARIA attributes for the menu toggle and the navigations.
  108. function onResizeARIA() {
  109. if ( window.innerWidth < 896 ) {
  110. if ( menuToggle.hasClass( 'toggled-on' ) ) {
  111. menuToggle.attr( 'aria-expanded', 'true' );
  112. siteMenu.attr( 'aria-expanded', 'true' );
  113. siteNavigation.attr( 'aria-expanded', 'true' );
  114. } else {
  115. menuToggle.attr( 'aria-expanded', 'false' );
  116. siteMenu.attr( 'aria-expanded', 'false' );
  117. siteNavigation.attr( 'aria-expanded', 'false' );
  118. }
  119. } else {
  120. menuToggle.removeAttr( 'aria-expanded' );
  121. siteMenu.removeAttr( 'aria-expanded' );
  122. siteNavigation.removeAttr( 'aria-expanded' );
  123. }
  124. }
  125. $( document ).ready( function() {
  126. body = $( document.body );
  127. $( window )
  128. .on( 'load.shoreditch', onResizeARIA )
  129. .on( 'resize.shoreditch', onResizeARIA );
  130. } );
  131. } )( jQuery );