Created
January 22, 2017 20:15
-
-
Save pingram3541/23b007d05cc31b3f496c39890d0df7a0 to your computer and use it in GitHub Desktop.
WordPress smoothstate implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function($){ | |
'use strict'; | |
/* | |
* jQuery htmlDoc "fixer" - v0.2pre - 8/8/2011 | |
* http://benalman.com/projects/jquery-misc-plugins/ | |
* | |
* Copyright (c) 2010 "Cowboy" Ben Alman | |
* Dual licensed under the MIT and GPL licenses. | |
* http://benalman.com/about/license/ | |
*/ | |
// RegExp that matches opening and closing browser-stripped tags. | |
// $1 = slash, $2 = tag name, $3 = attributes | |
var matchTag = /<(\/?)(html|head|body|title|base|meta)(\s+[^>]*)?>/ig; | |
// Unique id prefix for selecting placeholder elements. | |
var prefix = 'hd' + +new Date; | |
// A node under which a temporary DOM tree can be constructed. | |
var parent; | |
$.htmlDoc = function(html) { | |
// A collection of "intended" elements that can't be rendered cross-browser | |
// with .innerHTML, for which placeholders must be swapped. | |
var elems = $(); | |
// Input HTML string, parsed to include placeholder DIVs. Replace HTML, | |
// HEAD, BODY tags with DIV placeholders. | |
var htmlParsed = html.replace(matchTag, function(tag, slash, name, attrs) { | |
// Temporary object in which to hold attributes. | |
var obj = {}; | |
// If this is an opening tag... | |
if ( !slash ) { | |
// Add an element of this name into the collection of elements. Note | |
// that if a string of attributes is added at this point, it fails. | |
elems = elems.add('<' + name + '/>'); | |
// If the original tag had attributes, create a temporary div with | |
// those attributes. Then, copy each attribute from the temporary div | |
// over to the temporary object. | |
if ( attrs ) { | |
$.each($('<div' + attrs + '/>')[0].attributes, function(i, attr) { | |
obj[attr.name] = attr.value; | |
}); | |
} | |
// Set the attributes of the intended object based on the attributes | |
// copied in the previous step. | |
elems.eq(-1).attr(obj); | |
} | |
// A placeholder div with a unique id replaces the intended element's | |
// tag in the parsed HTML string. | |
return '<' + slash + 'div' | |
+ (slash ? '' : ' id="' + prefix + (elems.length - 1) + '"') + '>'; | |
}); | |
// If no placeholder elements were necessary, just return normal | |
// jQuery-parsed HTML. | |
if ( !elems.length ) { | |
return $(html); | |
} | |
// Create parent node if it hasn't been created yet. | |
if ( !parent ) { | |
parent = $('<div/>'); | |
} | |
// Create the parent node and append the parsed, place-held HTML. | |
parent.html(htmlParsed); | |
// Replace each placeholder element with its intended element. | |
$.each(elems, function(i) { | |
var elem = parent.find('#' + prefix + i).before(elems[i]); | |
elems.eq(i).html(elem.contents()); | |
elem.remove(); | |
}); | |
// Return the topmost intended element(s), sans text nodes, while removing | |
// them from the parent element with unwrap. | |
return parent.children().unwrap(); | |
}; | |
//setup our smoothstate.js | |
$(document).ready(function(){ | |
var $body = $('body'), | |
$main = $('#page'), | |
$site = $('html, body'), | |
$vpw = $(window).outerWidth(), | |
transition, | |
smoothState; | |
var options = { | |
//anchors: 'a', | |
//hrefRegex: '', | |
prefetch: true, | |
cacheLength: 4, | |
//debug: true, | |
blacklist: 'form, .no-smoothState, .hamburger, .contact, input', | |
forms: 'form', | |
//allowFormCaching: true, | |
//repeatDelay: 500, | |
prefetchOn: 'mouseover touchstart', | |
locationHeader: 'X-SmoothState-Location', | |
loadingClass: 'is-loading', | |
scroll: false, | |
// Param `request` is an `Object` that is currently set to be used | |
/*alterRequest: function(request) { | |
// Must return and `Object` that will be used to make the request | |
return request; | |
},*/ | |
// Param `state` is an `Object` that contains the container ID, by default | |
/*alterChangeState: function(state) { | |
// Must return a serializable `Object` that is associated with the history entry | |
return state; | |
},*/ | |
onBefore: function( $anchor, $container) { | |
//console.log('onBefore'); | |
var target = $anchor.attr('rel'); | |
if (target === 'next') { | |
transition = 'slideInRight'; | |
//console.log('fired next!'); | |
} else if (target === 'fade') { | |
transition = 'fadeIn'; | |
//console.log('fired fade!'); | |
} else { | |
transition = 'slideInLeft'; | |
//console.log('fired prev!'); | |
} | |
}, | |
onStart: { | |
duration: 400, | |
render: function (url, $container) { | |
//console.log('onStart'); | |
$main.addClass('is-exiting'); | |
if( transition === 'slideInRight' ){ | |
$body.find('#elementor').addClass('next'); | |
} else if( transition === 'fadeIn' ){ | |
$body.find('#elementor').addClass('fade'); | |
} else { | |
$body.find('#elementor').addClass('prev'); | |
} | |
$site.animate({scrollTop: 0}); | |
} | |
}, | |
/*onProgress: { | |
// How long this animation takes | |
duration: 0, | |
// A function that dictates the animations that take place | |
render: function ($container) {} | |
},*/ | |
onReady: { | |
duration: 0, | |
render: function ($container, $newContent) { | |
//console.log('onReady'); | |
var url = smoothState.href // <-- get the current url | |
var doc = smoothState.cache[url].doc // <-- full html response | |
var html = $.htmlDoc( doc ); | |
//find old elementor custom stylsheet and tag it | |
$(document).find("#elementor-frontend-stylesheet, [id^='elementor-post-']").addClass('marked-for-removal'); | |
//capture webform data | |
var post_id = $(document).find('input[name="post_id"]').val(); | |
var form_id = $(document).find('input[name="form_id"]').val(); | |
var _nonce = $(document).find('input[name="_nonce"]').val(); | |
var v_email = $(document).find('input[placeholder="Email"]').val(); | |
var v_msg = $(document).find('textarea[placeholder="Message"]').val(); | |
var v_name = $(document).find('input[placeholder="Name"]').val(); | |
var v_phone = $(document).find('input[placeholder="Phone"]').val(); | |
//if we have form data, create data object | |
if( v_name && v_email && v_phone ){ | |
var webform = [ | |
{ | |
"post_id" : post_id, | |
"form_id" : form_id, | |
"_nonce" : _nonce, | |
"email" : v_email, | |
"message" : v_msg, | |
"name" : v_name, | |
"phone" : v_phone | |
} | |
]; | |
//console.log( webform ); //webform object, just need to know how to post | |
} | |
//suggested by team pojo but results in Uncaught TypeError | |
//elementorFrontend.hooks.doAction( 'frontend/element_ready/form.default' ); | |
//put new elementor custom css into head | |
html.find( '#elementor-frontend-stylesheet' ).appendTo('head'); | |
html.find( '[id^="elementor-post-"]' ).appendTo('head'); | |
$('.project-button a').attr('rel','fade'); | |
setTimeout(function(){ | |
$(document).find('.marked-for-removal').remove(); //remove old elementor custom css | |
$('body').addClass('smoothState'); | |
}, 1500); | |
if( transition === 'slideInRight'){ | |
$newContent.find('.elementor').addClass('prev'); | |
} else if( transition === 'fadeIn'){ | |
$newContent.find('.elementor').addClass('fade'); | |
} else { | |
$newContent.find('.elementor').addClass('next'); | |
} | |
$container.html($newContent); | |
setTimeout(function(){ | |
$body.find('.elementor').removeClass('prev next fade'); | |
$('.page-template .col-b p').fakeScroll(); | |
}, 100); | |
$container.removeClass('is-exiting'); | |
} | |
}, | |
onAfter: function( $container ){ | |
//suggested by team pojo but results in Uncaught TypeError | |
//elementorFrontend.hooks.doAction( 'frontend/element_ready/form.default' ); | |
elementorFrontend.init(); //however this appears to work! | |
} | |
} | |
//initialize | |
smoothState = $main.smoothState( options ).data('smoothState'); | |
//swpe nav | |
$body.on({ | |
swiperight: function ( e, data ) { | |
$("a[rel='prev']")[0].click(); | |
//console.log('swiped right!'); | |
}, | |
swipeleft: function ( e, data ) { | |
$("a[rel='next']")[0].click(); | |
//console.log('swiped left!'); | |
}, | |
}, '.elementor'); | |
//toggle project information box | |
$body.on('click', '.open-text a, .close-text a', function(e){ | |
e.preventDefault(); | |
//console.log(e); | |
var container = $('.page-template .col-b'); | |
if ( $(e.target).hasClass('fa-info-circle') ) { | |
container.addClass('open'); | |
} else { | |
container.removeClass('open'); | |
} | |
}); | |
//elementor-toggle-title | |
$body.on('click', '.elementor-toggle-title', function(e){ | |
e.preventDefault(); | |
e.stopImmediatePropagation(); | |
//console.log(e); | |
var container = $(e.target); | |
if($('body').hasClass('smoothState')){ | |
if ( $(e.target).hasClass('active') ) { | |
container.removeClass('active'); | |
container.next().slideUp(); | |
} else { | |
container.addClass('active'); | |
container.next().slideDown(); | |
} | |
} | |
}); | |
$('.page-template .col-b p').fakeScroll(); | |
$("body").on("click",".hamburger", function(event){ | |
//console.log("clicked!"); | |
//console.log($(event.target)); | |
$(".hamburger.upper").toggleClass("is-active"); | |
$("#masthead").toggleClass("expanded"); | |
$("#site-navigation").toggleClass("toggled"); | |
}); | |
$("body").on("click", '.contact a', function(e){ | |
e.preventDefault(); | |
$(".contact-modal").addClass("open"); | |
//console.log("opened"); | |
}); | |
$("body").on("click", ".modal-close a", function(e){ | |
e.preventDefault(); | |
$(".contact-modal").removeClass("open"); | |
//console.log("closed"); | |
}); | |
}); | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you so much for sharing this code. I was able to use it on a current website project.