Skip to content

Instantly share code, notes, and snippets.

@mattwiebe
Created October 25, 2012 20:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mattwiebe/3955140 to your computer and use it in GitHub Desktop.
Save mattwiebe/3955140 to your computer and use it in GitHub Desktop.
jQuery( document ).ready( function( $ ) {
// Local vars.
var $masthead = $( '#masthead' ),
timeout = false,
$siteInfoClone,
$headerImageClone,
$socialLinksClone,
ajaxRequest = false,
$clickedModule;
// Toggle function.
function menuToggle( e ) {
$( '#mobile-masthead-inner' ).stop().slideToggle( 300 );
e.preventDefault();
}
// Construct mobile header.
function kyotoMobileHeader() {
// Check if the toggler exists. If not add it.
if ( ! $( '#mobile-menu-toggle').length )
$( '<a id="mobile-menu-toggle" href="#mobile-masthead-inner" />' ).prependTo( $masthead );
// Clone and detach .site-info for use later.
$siteInfoClone = $masthead.find( '.site-info' ).detach(),
// Clone and detach .social-links for use later.
$socialLinksClone = $masthead.find( '.social-links' ).detach(),
// Clone and detach #header-image for use later.
$headerImageClone = $masthead.find( '#header-image' ).detach(),
// Add 'mobile-masthead-inner' to the header inner for mobile and hide it as default.
$masthead.find( '.masthead-inner' ).attr( 'id', 'mobile-masthead-inner' ).hide();
// Swap classes for the navigation.
$masthead.find( '.site-navigation' ).removeClass( 'main-navigation' ).addClass( 'mobile-navigation' );
// Insert .site-info after #mobile-masthead-inner.
$siteInfoClone.insertAfter( '#mobile-masthead-inner' );
// Insert #header-image after .site-info.
$headerImageClone.insertAfter( $siteInfoClone );
// Insert .social-links after #mobile-menu-toggle.
$socialLinksClone.insertAfter( '#mobile-menu-toggle' ).attr( 'id', 'mobile-social-links' );
// Remove the click event first and bind it after to make sure it's invoked once.
$( '#mobile-menu-toggle' ).off( 'click', menuToggle ).click( menuToggle );
}
// Deconstruct mobile header.
function kyotoNormalHeader() {
// Check if the toggler exists. If it does remove it.
if ( $( '#mobile-menu-toggle').length )
$( '#mobile-menu-toggle' ).remove();
// Clone and detach .site-info for use later
$siteInfoClone = $masthead.find( '.site-info' ).detach(),
// Clone and detach .social-links for use later
$socialLinksClone = $masthead.find( '#mobile-social-links' ).detach(),
// Clone and detach #header-image for use later.
$headerImageClone = $masthead.find( '#header-image' ).detach(),
// Remove 'mobile-masthead-inner' to the header inner for mobile and show it as default.
$masthead.find( '.masthead-inner' ).removeAttr( 'id' ).show();
// Swap classes for the navigation
$masthead.find( '.site-navigation' ).removeClass( 'mobile-navigation' ).addClass( 'main-navigation' );
// Insert .site-info inside .masthead-top as the first item.
$siteInfoClone.prependTo( '.masthead-top' );
// Insert #header-image after .masthead-top.
$headerImageClone.insertAfter( '.masthead-top' );
// Insert .social-links-holder after #mobile-menu-toggle.
$socialLinksClone.insertAfter( '.site-info' ).removeAttr( 'id' );
}
// Check viewport width when user resizes the browser window.
$( window ).resize( function() {
if ( false !== timeout )
clearTimeout( timeout );
timeout = setTimeout( function() {
if ( $( window ).width() < 796 ) {
kyotoMobileHeader();
} else {
kyotoNormalHeader();
}
}, 100 );
} ).resize();
// Module hover effect
$( '.hide' ).hide();
$( '.module .module-inner' ).hover( function() {
$( this ).find( '.hide' ).show();
$( this ).find( '.attachment-featured-thumbnail, .attachment-featured-thumbnail-placeholder' ).stop( true, true ).fadeTo( 150, 0.3 );
},function() {
$( this ).find( '.hide' ).hide();
$( this ).find( '.attachment-featured-thumbnail, .attachment-featured-thumbnail-placeholder' ).stop( true, true ).fadeTo( 150, 1.0 );
} );
// Masonry
var $container = $( '.grid' );
$container.imagesLoaded( function(){
$container.masonry( {
columnWidth: 232,
itemSelector: '.module',
isFitWidth: true,
isAnimated: true,
gutterWidth: 20,
onResize: function ( e, width ) {
$( '#masthead' ).css( 'width', width ),
$( '.paging-navigation' ).css( 'width', width ),
$( '#colophon' ).css( 'width', width )
},
animationOptions: {
duration: 300
}
} );
} );
// Display Ajax post and expanding the clicked module.
function expandModule( element ) {
// Disable cache.
$.ajaxSetup( {
cache: false
} );
// Local vars.
var $el = $( element ),
postId = $el.attr( 'rel' ),
$ajaxUrl = kyotoAjax.ajaxUrl + '=' + postId,
$module = $el.closest( '.module' ),
$moduleInner = $module.find( '.module-inner' ),
$entrySummary = $module.find( '.entry-summary' ),
$entryFull = $module.find( '.entry-full' ),
contentWidth = $( '#content' ).width(),
newWidth;
if ( $.isFunction( ajaxRequest.abort ) ) {
// abort a currently running ajax request
ajaxRequest.abort();
// remove spinner
if ( $.isFunction( $clickedModule.fadeTo ) ) {
$clickedModule.fadeTo( 0, 0.25 );
}
}
// assign our element to the "global" $clickedModule var for easy ajax-loader removal
$clickedModule = $el;
// Change newWidth depending on the width of #content
if ( 988 <= contentWidth ) {
newWidth = 988;
} else if ( 988 > contentWidth && 736 <= contentWidth ) {
newWidth = 736;
} else if ( 736 > contentWidth && 484 <= contentWidth ) {
newWidth = 484;
} else if ( 484 > contentWidth ) {
newWidth = 232;
}
// Save original module size
$module.data( 'size', [ $module.width(), $module.height() ] );
// Remove ajax content
$entryFull.html('');
// Hide .entry-full until ready to show
$entryFull.fadeTo( 0, 0 );
// Show ajax loader
$entrySummary.find( '.ajax-loader' ).fadeTo( 0, 0.5 );
// Animation begins
// Expand the width first to get accurate height of the content
$module.animate( { width: $newWidth }, function() {
// Ajax ready
ajaxRequest = $.ajax( {
type: 'POST',
url: $ajaxUrl,
done: function( result ) {
// Hide its .entry-summary
$entrySummary.fadeTo( 400, 0 ).hide();
// Hide ajax loader
$entrySummary.find( '.ajax-loader' ).fadeTo( 0, 0 );
// Inject ajax content
$entryFull.html( result );
// Wait until all images are loaded and animate the height.
$moduleInner.imagesLoaded( function() {
// Now we can expand height
$module.animate( { height: $moduleInner.height() }, function() {
// Masonry with a bit of hack to make a callback work.
// https://github.com/desandro/masonry/pull/174#issuecomment-3834696
var $container = $( '.grid' );
$container.masonry( {
animationOptions: { duration: 300, complete: function() {
if ( this == $container[0] ) {
// Scroll window to ajax loaded content
$.scrollTo( '.expanded', 400, { offset: { top:-48 } } );
// Final show the content
$entryFull.fadeTo( 200, 1 );
}
} }
} );
} );
} );
}
} );
} );
}
// Restore module.
function restoreModule() {
var $len = $( '.expanded' ).length - 1;
$( '.expanded' ).each( function( i ) {
// Remove ajax content
$( this ).find( '.entry-full' ).html('');
// Put .entry-summary back.
$( this ).find( '.entry-summary' ).fadeTo( 200, 1 ).show();
// Shrink expanded module to normal
var $moduleSize = $( this ).data( 'size' );
$( this ).animate( {
// Default module width is 232px
width: ( $moduleSize[0] || 232 ),
height: ( $moduleSize[1] || 'auto' )
}, function() {
// Make sure there is at least 1 expanded module
if ( i >= $len ) {
var $container = $( '.grid' );
$container.masonry( {
animationOptions: {
duration: 300,
}
} );
}
} ).removeClass( 'expanded' ); // callback to remove class expanded
} );
}
$( '.module' ).on( 'click', '.trigger', function( e ) {
e.preventDefault();
if ( $( this ).closest( '.module' ).hasClass( 'expanded' ) ) {
restoreModule();
} else {
expandModule( this );
restoreModule();
$( this ).closest( '.module' ).addClass( 'expanded' );
}
} );
} );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment