nathananderson nathananderson - 2 months ago 10
CSS Question

Page transition causing mobile nav to be unclickable

I've got two main jQuery elements here. One is a page transition that's replacing the content of the page with another page, the other is a smart nav (mobile nav on mobile and page scrolling).

The transition and navigation work perfectly on desktop devices. The problem is when you jump to the mobile nav it becomes un-clickable.

It's only un-clickable after having done a page transition so I'm convinced they're conflicting somehow.

The live page is here https://nathanworking.github.io/page-transition-smart-nav/

The two scripts are below.
Note: what I've done to combine these pieces is simple have "Animated Page transitions" 1st then "Smart Navigation" 2nd in my .js file.

If I'm simply combining these two wrong, anyone have thoughts on how to merge these?

Thanks for any help!

Animated Page transitions

/*-----------------------------------

----- Animated Page transitions ------

--------------------------------------*/
jQuery(document).ready(function(event){
var isAnimating = false,
newLocation = '';
firstLoad = false;

//trigger smooth transition from the actual page to the new one
$('body').on('click', '[data-type="page-transition"]', function(event){
event.preventDefault();
//detect which page has been selected
var newPage = $(this).attr('href');
//if the page is not already being animated - trigger animation
if( !isAnimating ) changePage(newPage, true);
firstLoad = true;
});

//detect the 'popstate' event - e.g. user clicking the back button
$(window).on('popstate', function() {
if( firstLoad ) {
/*
Safari emits a popstate event on page load - check if firstLoad is true before animating
if it's false - the page has just been loaded
*/
var newPageArray = location.pathname.split('/'),
//this is the url of the page to be loaded
newPage = newPageArray[newPageArray.length - 1];

if( !isAnimating && newLocation != newPage ) changePage(newPage, false);
}
firstLoad = true;
});

function changePage(url, bool) {
isAnimating = true;
// trigger page animation
$('body').addClass('page-is-changing');
$('.cd-loading-bar').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){
loadNewContent(url, bool);
newLocation = url;
$('.cd-loading-bar').off('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
});
//if browser doesn't support CSS transitions
if( !transitionsSupported() ) {
loadNewContent(url, bool);
newLocation = url;
}
}

function loadNewContent(url, bool) {
url = ('' == url) ? 'index.html' : url;
var newSection = 'cd-'+url.replace('.html', '');
var section = $('<div class="cd-main-content '+newSection+'"></div>');

section.load(url+' .cd-main-content > *', function(event){
// load new content and replace <main> content with the new one
$('main').html(section);
//if browser doesn't support CSS transitions - dont wait for the end of transitions
var delay = ( transitionsSupported() ) ? 1200 : 0;
setTimeout(function(){
//wait for the end of the transition on the loading bar before revealing the new content
( section.hasClass('cd-about') ) ? $('body').addClass('cd-about') : $('body').removeClass('cd-about');
$('body').removeClass('page-is-changing');
$('.cd-loading-bar').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){
isAnimating = false;
$('.cd-loading-bar').off('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
});

if( !transitionsSupported() ) isAnimating = false;
}, delay);

if(url!=window.location && bool){
//add the new page to the window.history
//if the new page was triggered by a 'popstate' event, don't add it
window.history.pushState({path: url},'',url);
}

});
}

function transitionsSupported() {
return $('html').hasClass('csstransitions');
}
});


Smart Navigation

/*-----------------------------------

----- Smart Navigation ------

--------------------------------------*/
jQuery(document).ready(function($){
// browser window scroll (in pixels) after which the "menu" link is shown
var offset = 300;

var navigationContainer = $('#cd-nav'),
mainNavigation = navigationContainer.find('#cd-main-nav ul');

//hide or show the "menu" link
checkMenu();
$(window).scroll(function(){
checkMenu();
});

//open or close the menu clicking on the bottom "menu" link
$('.cd-nav-trigger').on('click', function(){
$(this).toggleClass('menu-is-open');
//we need to remove the transitionEnd event handler (we add it when scolling up with the menu open)
mainNavigation.off('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend').toggleClass('is-visible');

});

function checkMenu() {
if( $(window).scrollTop() > offset && !navigationContainer.hasClass('is-fixed')) {
navigationContainer.addClass('is-fixed').find('.cd-nav-trigger').one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function(){
mainNavigation.addClass('has-transitions');
});
} else if ($(window).scrollTop() <= offset) {
//check if the menu is open when scrolling up
if( mainNavigation.hasClass('is-visible') && !$('html').hasClass('no-csstransitions') ) {
//close the menu with animation
mainNavigation.addClass('is-hidden').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){
//wait for the menu to be closed and do the rest
mainNavigation.removeClass('is-visible is-hidden has-transitions');
navigationContainer.removeClass('is-fixed');
$('.cd-nav-trigger').removeClass('menu-is-open');
});
//check if the menu is open when scrolling up - fallback if transitions are not supported
} else if( mainNavigation.hasClass('is-visible') && $('html').hasClass('no-csstransitions') ) {
mainNavigation.removeClass('is-visible has-transitions');
navigationContainer.removeClass('is-fixed');
$('.cd-nav-trigger').removeClass('menu-is-open');
//scrolling up with menu closed
} else {
navigationContainer.removeClass('is-fixed');
mainNavigation.removeClass('has-transitions');
}
}
}
});


With the comment from ryancdotnet - this is the correct jQuery:

/*-----------------------------------

----- Animated Page transitions ------

--------------------------------------*/
jQuery(document).ready(function(event){
var isAnimating = false,
newLocation = '';
firstLoad = false;

//trigger smooth transition from the actual page to the new one
$('body').on('click', '[data-type="page-transition"]', function(event){
event.preventDefault();
//detect which page has been selected
var newPage = $(this).attr('href');
//if the page is not already being animated - trigger animation
if( !isAnimating ) changePage(newPage, true);
firstLoad = true;
});

//detect the 'popstate' event - e.g. user clicking the back button
$(window).on('popstate', function() {
if( firstLoad ) {
/*
Safari emits a popstate event on page load - check if firstLoad is true before animating
if it's false - the page has just been loaded
*/
var newPageArray = location.pathname.split('/'),
//this is the url of the page to be loaded
newPage = newPageArray[newPageArray.length - 1];

if( !isAnimating && newLocation != newPage ) changePage(newPage, false);
}
firstLoad = true;
});

function changePage(url, bool) {
isAnimating = true;
// trigger page animation
$('body').addClass('page-is-changing');
$('.cd-loading-bar').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){
loadNewContent(url, bool);
newLocation = url;
$('.cd-loading-bar').off('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
});
//if browser doesn't support CSS transitions
if( !transitionsSupported() ) {
loadNewContent(url, bool);
newLocation = url;
}
}

function loadNewContent(url, bool) {
url = ('' == url) ? 'index.html' : url;
var newSection = 'cd-'+url.replace('.html', '');
var section = $('<div class="cd-main-content '+newSection+'"></div>');

section.load(url+' .cd-main-content > *', function(event){
// load new content and replace <main> content with the new one
$('main').html(section);
//if browser doesn't support CSS transitions - dont wait for the end of transitions
var delay = ( transitionsSupported() ) ? 1200 : 0;
setTimeout(function(){
//wait for the end of the transition on the loading bar before revealing the new content
( section.hasClass('cd-about') ) ? $('body').addClass('cd-about') : $('body').removeClass('cd-about');
$('body').removeClass('page-is-changing');
$('.cd-loading-bar').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){
isAnimating = false;
$('.cd-loading-bar').off('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
});

// ----- Animated Page transitions ------
//open or close the menu clicking on the bottom "menu" link
jQuery(document).ready(function($){
// browser window scroll (in pixels) after which the "menu" link is shown
var offset = 300;

var navigationContainer = $('#cd-nav'),
mainNavigation = navigationContainer.find('#cd-main-nav ul');

//hide or show the "menu" link
checkMenu();
$(window).scroll(function(){
checkMenu();
});

//open or close the menu clicking on the bottom "menu" link
$('.cd-nav-trigger').on('click', function(){
$(this).toggleClass('menu-is-open');
//we need to remove the transitionEnd event handler (we add it when scolling up with the menu open)
mainNavigation.off('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend').toggleClass('is-visible');

});

function checkMenu() {
if( $(window).scrollTop() > offset && !navigationContainer.hasClass('is-fixed')) {
navigationContainer.addClass('is-fixed').find('.cd-nav-trigger').one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function(){
mainNavigation.addClass('has-transitions');
});
} else if ($(window).scrollTop() <= offset) {
//check if the menu is open when scrolling up
if( mainNavigation.hasClass('is-visible') && !$('html').hasClass('no-csstransitions') ) {
//close the menu with animation
mainNavigation.addClass('is-hidden').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){
//wait for the menu to be closed and do the rest
mainNavigation.removeClass('is-visible is-hidden has-transitions');
navigationContainer.removeClass('is-fixed');
$('.cd-nav-trigger').removeClass('menu-is-open');
});
//check if the menu is open when scrolling up - fallback if transitions are not supported
} else if( mainNavigation.hasClass('is-visible') && $('html').hasClass('no-csstransitions') ) {
mainNavigation.removeClass('is-visible has-transitions');
navigationContainer.removeClass('is-fixed');
$('.cd-nav-trigger').removeClass('menu-is-open');
//scrolling up with menu closed
} else {
navigationContainer.removeClass('is-fixed');
mainNavigation.removeClass('has-transitions');
}
}
}
});
// ----- Animated Page transitions ------

if( !transitionsSupported() ) isAnimating = false;
}, delay);

if(url!=window.location && bool){
//add the new page to the window.history
//if the new page was triggered by a 'popstate' event, don't add it
window.history.pushState({path: url},'',url);
}

});
}

function transitionsSupported() {
return $('html').hasClass('csstransitions');
}
});

Answer

The mobile nav always seems to fail after the first click. Upon debugging, it appears that you are removing the menu and re-adding it, but the click events are not being wired up after.

Specifically, this part does not seem to be getting fired again:

$('.cd-nav-trigger').on('click',......