wp/wp-content/themes/twentyseventeen/assets/js/global.js
changeset 8 c7c34916027a
parent 7 cf61fcea0001
child 9 177826044cd9
equal deleted inserted replaced
7:cf61fcea0001 8:c7c34916027a
     1 /* global twentyseventeenScreenReaderText */
       
     2 (function( $ ) {
       
     3 
       
     4 	// Variables and DOM Caching.
       
     5 	var $body = $( 'body' ),
       
     6 		$customHeader = $body.find( '.custom-header' ),
       
     7 		$branding = $customHeader.find( '.site-branding' ),
       
     8 		$navigation = $body.find( '.navigation-top' ),
       
     9 		$navWrap = $navigation.find( '.wrap' ),
       
    10 		$navMenuItem = $navigation.find( '.menu-item' ),
       
    11 		$menuToggle = $navigation.find( '.menu-toggle' ),
       
    12 		$menuScrollDown = $body.find( '.menu-scroll-down' ),
       
    13 		$sidebar = $body.find( '#secondary' ),
       
    14 		$entryContent = $body.find( '.entry-content' ),
       
    15 		$formatQuote = $body.find( '.format-quote blockquote' ),
       
    16 		isFrontPage = $body.hasClass( 'twentyseventeen-front-page' ) || $body.hasClass( 'home blog' ),
       
    17 		navigationFixedClass = 'site-navigation-fixed',
       
    18 		navigationHeight,
       
    19 		navigationOuterHeight,
       
    20 		navPadding,
       
    21 		navMenuItemHeight,
       
    22 		idealNavHeight,
       
    23 		navIsNotTooTall,
       
    24 		headerOffset,
       
    25 		menuTop = 0,
       
    26 		resizeTimer;
       
    27 
       
    28 	// Ensure the sticky navigation doesn't cover current focused links.
       
    29 	$( 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex], [contenteditable]', '.site-content-contain' ).filter( ':visible' ).focus( function() {
       
    30 		if ( $navigation.hasClass( 'site-navigation-fixed' ) ) {
       
    31 			var windowScrollTop = $( window ).scrollTop(),
       
    32 				fixedNavHeight = $navigation.height(),
       
    33 				itemScrollTop = $( this ).offset().top,
       
    34 				offsetDiff = itemScrollTop - windowScrollTop;
       
    35 
       
    36 			// Account for Admin bar.
       
    37 			if ( $( '#wpadminbar' ).length ) {
       
    38 				offsetDiff -= $( '#wpadminbar' ).height();
       
    39 			}
       
    40 
       
    41 			if ( offsetDiff < fixedNavHeight ) {
       
    42 				$( window ).scrollTo( itemScrollTop - ( fixedNavHeight + 50 ), 0 );
       
    43 			}
       
    44 		}
       
    45 	});
       
    46 
       
    47 	// Set properties of navigation.
       
    48 	function setNavProps() {
       
    49 		navigationHeight      = $navigation.height();
       
    50 		navigationOuterHeight = $navigation.outerHeight();
       
    51 		navPadding            = parseFloat( $navWrap.css( 'padding-top' ) ) * 2;
       
    52 		navMenuItemHeight     = $navMenuItem.outerHeight() * 2;
       
    53 		idealNavHeight        = navPadding + navMenuItemHeight;
       
    54 		navIsNotTooTall       = navigationHeight <= idealNavHeight;
       
    55 	}
       
    56 
       
    57 	// Make navigation 'stick'.
       
    58 	function adjustScrollClass() {
       
    59 
       
    60 		// Make sure we're not on a mobile screen.
       
    61 		if ( 'none' === $menuToggle.css( 'display' ) ) {
       
    62 
       
    63 			// Make sure the nav isn't taller than two rows.
       
    64 			if ( navIsNotTooTall ) {
       
    65 
       
    66 				// When there's a custom header image or video, the header offset includes the height of the navigation.
       
    67 				if ( isFrontPage && ( $body.hasClass( 'has-header-image' ) || $body.hasClass( 'has-header-video' ) ) ) {
       
    68 					headerOffset = $customHeader.innerHeight() - navigationOuterHeight;
       
    69 				} else {
       
    70 					headerOffset = $customHeader.innerHeight();
       
    71 				}
       
    72 
       
    73 				// If the scroll is more than the custom header, set the fixed class.
       
    74 				if ( $( window ).scrollTop() >= headerOffset ) {
       
    75 					$navigation.addClass( navigationFixedClass );
       
    76 				} else {
       
    77 					$navigation.removeClass( navigationFixedClass );
       
    78 				}
       
    79 
       
    80 			} else {
       
    81 
       
    82 				// Remove 'fixed' class if nav is taller than two rows.
       
    83 				$navigation.removeClass( navigationFixedClass );
       
    84 			}
       
    85 		}
       
    86 	}
       
    87 
       
    88 	// Set margins of branding in header.
       
    89 	function adjustHeaderHeight() {
       
    90 		if ( 'none' === $menuToggle.css( 'display' ) ) {
       
    91 
       
    92 			// The margin should be applied to different elements on front-page or home vs interior pages.
       
    93 			if ( isFrontPage ) {
       
    94 				$branding.css( 'margin-bottom', navigationOuterHeight );
       
    95 			} else {
       
    96 				$customHeader.css( 'margin-bottom', navigationOuterHeight );
       
    97 			}
       
    98 
       
    99 		} else {
       
   100 			$customHeader.css( 'margin-bottom', '0' );
       
   101 			$branding.css( 'margin-bottom', '0' );
       
   102 		}
       
   103 	}
       
   104 
       
   105 	// Set icon for quotes.
       
   106 	function setQuotesIcon() {
       
   107 		$( twentyseventeenScreenReaderText.quote ).prependTo( $formatQuote );
       
   108 	}
       
   109 
       
   110 	// Add 'below-entry-meta' class to elements.
       
   111 	function belowEntryMetaClass( param ) {
       
   112 		var sidebarPos, sidebarPosBottom;
       
   113 
       
   114 		if ( ! $body.hasClass( 'has-sidebar' ) || (
       
   115 			$body.hasClass( 'search' ) ||
       
   116 			$body.hasClass( 'single-attachment' ) ||
       
   117 			$body.hasClass( 'error404' ) ||
       
   118 			$body.hasClass( 'twentyseventeen-front-page' )
       
   119 		) ) {
       
   120 			return;
       
   121 		}
       
   122 
       
   123 		sidebarPos       = $sidebar.offset();
       
   124 		sidebarPosBottom = sidebarPos.top + ( $sidebar.height() + 28 );
       
   125 
       
   126 		$entryContent.find( param ).each( function() {
       
   127 			var $element = $( this ),
       
   128 				elementPos = $element.offset(),
       
   129 				elementPosTop = elementPos.top;
       
   130 
       
   131 			// Add 'below-entry-meta' to elements below the entry meta.
       
   132 			if ( elementPosTop > sidebarPosBottom ) {
       
   133 				$element.addClass( 'below-entry-meta' );
       
   134 			} else {
       
   135 				$element.removeClass( 'below-entry-meta' );
       
   136 			}
       
   137 		});
       
   138 	}
       
   139 
       
   140 	/*
       
   141 	 * Test if inline SVGs are supported.
       
   142 	 * @link https://github.com/Modernizr/Modernizr/
       
   143 	 */
       
   144 	function supportsInlineSVG() {
       
   145 		var div = document.createElement( 'div' );
       
   146 		div.innerHTML = '<svg/>';
       
   147 		return 'http://www.w3.org/2000/svg' === ( 'undefined' !== typeof SVGRect && div.firstChild && div.firstChild.namespaceURI );
       
   148 	}
       
   149 
       
   150 	/**
       
   151 	 * Test if an iOS device.
       
   152 	*/
       
   153 	function checkiOS() {
       
   154 		return /iPad|iPhone|iPod/.test(navigator.userAgent) && ! window.MSStream;
       
   155 	}
       
   156 
       
   157 	/*
       
   158 	 * Test if background-attachment: fixed is supported.
       
   159 	 * @link http://stackoverflow.com/questions/14115080/detect-support-for-background-attachment-fixed
       
   160 	 */
       
   161 	function supportsFixedBackground() {
       
   162 		var el = document.createElement('div'),
       
   163 			isSupported;
       
   164 
       
   165 		try {
       
   166 			if ( ! ( 'backgroundAttachment' in el.style ) || checkiOS() ) {
       
   167 				return false;
       
   168 			}
       
   169 			el.style.backgroundAttachment = 'fixed';
       
   170 			isSupported = ( 'fixed' === el.style.backgroundAttachment );
       
   171 			return isSupported;
       
   172 		}
       
   173 		catch (e) {
       
   174 			return false;
       
   175 		}
       
   176 	}
       
   177 
       
   178 	// Fire on document ready.
       
   179 	$( document ).ready( function() {
       
   180 
       
   181 		// If navigation menu is present on page, setNavProps and adjustScrollClass.
       
   182 		if ( $navigation.length ) {
       
   183 			setNavProps();
       
   184 			adjustScrollClass();
       
   185 		}
       
   186 
       
   187 		// If 'Scroll Down' arrow in present on page, calculate scroll offset and bind an event handler to the click event.
       
   188 		if ( $menuScrollDown.length ) {
       
   189 
       
   190 			if ( $( 'body' ).hasClass( 'admin-bar' ) ) {
       
   191 				menuTop -= 32;
       
   192 			}
       
   193 			if ( $( 'body' ).hasClass( 'blog' ) ) {
       
   194 				menuTop -= 30; // The div for latest posts has no space above content, add some to account for this.
       
   195 			}
       
   196 			if ( ! $navigation.length ) {
       
   197 				navigationOuterHeight = 0;
       
   198 			}
       
   199 
       
   200 			$menuScrollDown.click( function( e ) {
       
   201 				e.preventDefault();
       
   202 				$( window ).scrollTo( '#primary', {
       
   203 					duration: 600,
       
   204 					offset: { top: menuTop - navigationOuterHeight }
       
   205 				});
       
   206 			});
       
   207 		}
       
   208 
       
   209 		adjustHeaderHeight();
       
   210 		setQuotesIcon();
       
   211 		if ( true === supportsInlineSVG() ) {
       
   212 			document.documentElement.className = document.documentElement.className.replace( /(\s*)no-svg(\s*)/, '$1svg$2' );
       
   213 		}
       
   214 
       
   215 		if ( true === supportsFixedBackground() ) {
       
   216 			document.documentElement.className += ' background-fixed';
       
   217 		}
       
   218 	});
       
   219 
       
   220 	// If navigation menu is present on page, adjust it on scroll and screen resize.
       
   221 	if ( $navigation.length ) {
       
   222 
       
   223 		// On scroll, we want to stick/unstick the navigation.
       
   224 		$( window ).on( 'scroll', function() {
       
   225 			adjustScrollClass();
       
   226 			adjustHeaderHeight();
       
   227 		});
       
   228 
       
   229 		// Also want to make sure the navigation is where it should be on resize.
       
   230 		$( window ).resize( function() {
       
   231 			setNavProps();
       
   232 			setTimeout( adjustScrollClass, 500 );
       
   233 		});
       
   234 	}
       
   235 
       
   236 	$( window ).resize( function() {
       
   237 		clearTimeout( resizeTimer );
       
   238 		resizeTimer = setTimeout( function() {
       
   239 			belowEntryMetaClass( 'blockquote.alignleft, blockquote.alignright' );
       
   240 		}, 300 );
       
   241 		setTimeout( adjustHeaderHeight, 1000 );
       
   242 	});
       
   243 
       
   244 	// Add header video class after the video is loaded.
       
   245 	$( document ).on( 'wp-custom-header-video-loaded', function() {
       
   246 		$body.addClass( 'has-header-video' );
       
   247 	});
       
   248 
       
   249 })( jQuery );