wp/wp-content/themes/twentysixteen/js/functions.js
changeset 7 cf61fcea0001
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
       
     1 /* global screenReaderText */
       
     2 /**
       
     3  * Theme functions file.
       
     4  *
       
     5  * Contains handlers for navigation and widget area.
       
     6  */
       
     7 
       
     8 ( function( $ ) {
       
     9 	var body, masthead, menuToggle, siteNavigation, socialNavigation, siteHeaderMenu, resizeTimer;
       
    10 
       
    11 	function initMainNavigation( container ) {
       
    12 
       
    13 		// Add dropdown toggle that displays child menu items.
       
    14 		var dropdownToggle = $( '<button />', {
       
    15 			'class': 'dropdown-toggle',
       
    16 			'aria-expanded': false
       
    17 		} ).append( $( '<span />', {
       
    18 			'class': 'screen-reader-text',
       
    19 			text: screenReaderText.expand
       
    20 		} ) );
       
    21 
       
    22 		container.find( '.menu-item-has-children > a' ).after( dropdownToggle );
       
    23 
       
    24 		// Toggle buttons and submenu items with active children menu items.
       
    25 		container.find( '.current-menu-ancestor > button' ).addClass( 'toggled-on' );
       
    26 		container.find( '.current-menu-ancestor > .sub-menu' ).addClass( 'toggled-on' );
       
    27 
       
    28 		// Add menu items with submenus to aria-haspopup="true".
       
    29 		container.find( '.menu-item-has-children' ).attr( 'aria-haspopup', 'true' );
       
    30 
       
    31 		container.find( '.dropdown-toggle' ).click( function( e ) {
       
    32 			var _this            = $( this ),
       
    33 				screenReaderSpan = _this.find( '.screen-reader-text' );
       
    34 
       
    35 			e.preventDefault();
       
    36 			_this.toggleClass( 'toggled-on' );
       
    37 			_this.next( '.children, .sub-menu' ).toggleClass( 'toggled-on' );
       
    38 
       
    39 			// jscs:disable
       
    40 			_this.attr( 'aria-expanded', _this.attr( 'aria-expanded' ) === 'false' ? 'true' : 'false' );
       
    41 			// jscs:enable
       
    42 			screenReaderSpan.text( screenReaderSpan.text() === screenReaderText.expand ? screenReaderText.collapse : screenReaderText.expand );
       
    43 		} );
       
    44 	}
       
    45 	initMainNavigation( $( '.main-navigation' ) );
       
    46 
       
    47 	masthead         = $( '#masthead' );
       
    48 	menuToggle       = masthead.find( '#menu-toggle' );
       
    49 	siteHeaderMenu   = masthead.find( '#site-header-menu' );
       
    50 	siteNavigation   = masthead.find( '#site-navigation' );
       
    51 	socialNavigation = masthead.find( '#social-navigation' );
       
    52 
       
    53 	// Enable menuToggle.
       
    54 	( function() {
       
    55 
       
    56 		// Return early if menuToggle is missing.
       
    57 		if ( ! menuToggle.length ) {
       
    58 			return;
       
    59 		}
       
    60 
       
    61 		// Add an initial values for the attribute.
       
    62 		menuToggle.add( siteNavigation ).add( socialNavigation ).attr( 'aria-expanded', 'false' );
       
    63 
       
    64 		menuToggle.on( 'click.twentysixteen', function() {
       
    65 			$( this ).add( siteHeaderMenu ).toggleClass( 'toggled-on' );
       
    66 
       
    67 			// jscs:disable
       
    68 			$( this ).add( siteNavigation ).add( socialNavigation ).attr( 'aria-expanded', $( this ).add( siteNavigation ).add( socialNavigation ).attr( 'aria-expanded' ) === 'false' ? 'true' : 'false' );
       
    69 			// jscs:enable
       
    70 		} );
       
    71 	} )();
       
    72 
       
    73 	// Fix sub-menus for touch devices and better focus for hidden submenu items for accessibility.
       
    74 	( function() {
       
    75 		if ( ! siteNavigation.length || ! siteNavigation.children().length ) {
       
    76 			return;
       
    77 		}
       
    78 
       
    79 		// Toggle `focus` class to allow submenu access on tablets.
       
    80 		function toggleFocusClassTouchScreen() {
       
    81 			if ( window.innerWidth >= 910 ) {
       
    82 				$( document.body ).on( 'touchstart.twentysixteen', 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.twentysixteen', function( e ) {
       
    88 					var el = $( this ).parent( 'li' );
       
    89 
       
    90 					if ( ! el.hasClass( 'focus' ) ) {
       
    91 						e.preventDefault();
       
    92 						el.toggleClass( 'focus' );
       
    93 						el.siblings( '.focus' ).removeClass( 'focus' );
       
    94 					}
       
    95 				} );
       
    96 			} else {
       
    97 				siteNavigation.find( '.menu-item-has-children > a' ).unbind( 'touchstart.twentysixteen' );
       
    98 			}
       
    99 		}
       
   100 
       
   101 		if ( 'ontouchstart' in window ) {
       
   102 			$( window ).on( 'resize.twentysixteen', toggleFocusClassTouchScreen );
       
   103 			toggleFocusClassTouchScreen();
       
   104 		}
       
   105 
       
   106 		siteNavigation.find( 'a' ).on( 'focus.twentysixteen blur.twentysixteen', function() {
       
   107 			$( this ).parents( '.menu-item' ).toggleClass( 'focus' );
       
   108 		} );
       
   109 	} )();
       
   110 
       
   111 	// Add the default ARIA attributes for the menu toggle and the navigations.
       
   112 	function onResizeARIA() {
       
   113 		if ( window.innerWidth < 910 ) {
       
   114 			if ( menuToggle.hasClass( 'toggled-on' ) ) {
       
   115 				menuToggle.attr( 'aria-expanded', 'true' );
       
   116 			} else {
       
   117 				menuToggle.attr( 'aria-expanded', 'false' );
       
   118 			}
       
   119 
       
   120 			if ( siteHeaderMenu.hasClass( 'toggled-on' ) ) {
       
   121 				siteNavigation.attr( 'aria-expanded', 'true' );
       
   122 				socialNavigation.attr( 'aria-expanded', 'true' );
       
   123 			} else {
       
   124 				siteNavigation.attr( 'aria-expanded', 'false' );
       
   125 				socialNavigation.attr( 'aria-expanded', 'false' );
       
   126 			}
       
   127 
       
   128 			menuToggle.attr( 'aria-controls', 'site-navigation social-navigation' );
       
   129 		} else {
       
   130 			menuToggle.removeAttr( 'aria-expanded' );
       
   131 			siteNavigation.removeAttr( 'aria-expanded' );
       
   132 			socialNavigation.removeAttr( 'aria-expanded' );
       
   133 			menuToggle.removeAttr( 'aria-controls' );
       
   134 		}
       
   135 	}
       
   136 
       
   137 	// Add 'below-entry-meta' class to elements.
       
   138 	function belowEntryMetaClass( param ) {
       
   139 		if ( body.hasClass( 'page' ) || body.hasClass( 'search' ) || body.hasClass( 'single-attachment' ) || body.hasClass( 'error404' ) ) {
       
   140 			return;
       
   141 		}
       
   142 
       
   143 		$( '.entry-content' ).find( param ).each( function() {
       
   144 			var element              = $( this ),
       
   145 				elementPos           = element.offset(),
       
   146 				elementPosTop        = elementPos.top,
       
   147 				entryFooter          = element.closest( 'article' ).find( '.entry-footer' ),
       
   148 				entryFooterPos       = entryFooter.offset(),
       
   149 				entryFooterPosBottom = entryFooterPos.top + ( entryFooter.height() + 28 ),
       
   150 				caption              = element.closest( 'figure' ),
       
   151 				newImg;
       
   152 
       
   153 			// Add 'below-entry-meta' to elements below the entry meta.
       
   154 			if ( elementPosTop > entryFooterPosBottom ) {
       
   155 
       
   156 				// Check if full-size images and captions are larger than or equal to 840px.
       
   157 				if ( 'img.size-full' === param ) {
       
   158 
       
   159 					// Create an image to find native image width of resized images (i.e. max-width: 100%).
       
   160 					newImg = new Image();
       
   161 					newImg.src = element.attr( 'src' );
       
   162 
       
   163 					$( newImg ).on( 'load.twentysixteen', function() {
       
   164 						if ( newImg.width >= 840  ) {
       
   165 							element.addClass( 'below-entry-meta' );
       
   166 
       
   167 							if ( caption.hasClass( 'wp-caption' ) ) {
       
   168 								caption.addClass( 'below-entry-meta' );
       
   169 								caption.removeAttr( 'style' );
       
   170 							}
       
   171 						}
       
   172 					} );
       
   173 				} else {
       
   174 					element.addClass( 'below-entry-meta' );
       
   175 				}
       
   176 			} else {
       
   177 				element.removeClass( 'below-entry-meta' );
       
   178 				caption.removeClass( 'below-entry-meta' );
       
   179 			}
       
   180 		} );
       
   181 	}
       
   182 
       
   183 	$( document ).ready( function() {
       
   184 		body = $( document.body );
       
   185 
       
   186 		$( window )
       
   187 			.on( 'load.twentysixteen', onResizeARIA )
       
   188 			.on( 'resize.twentysixteen', function() {
       
   189 				clearTimeout( resizeTimer );
       
   190 				resizeTimer = setTimeout( function() {
       
   191 					belowEntryMetaClass( 'img.size-full' );
       
   192 					belowEntryMetaClass( 'blockquote.alignleft, blockquote.alignright' );
       
   193 				}, 300 );
       
   194 				onResizeARIA();
       
   195 			} );
       
   196 
       
   197 		belowEntryMetaClass( 'img.size-full' );
       
   198 		belowEntryMetaClass( 'blockquote.alignleft, blockquote.alignright' );
       
   199 	} );
       
   200 } )( jQuery );