Skip to content

Instantly share code, notes, and snippets.

@pingram3541
Created January 22, 2017 20:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save pingram3541/23b007d05cc31b3f496c39890d0df7a0 to your computer and use it in GitHub Desktop.
Save pingram3541/23b007d05cc31b3f496c39890d0df7a0 to your computer and use it in GitHub Desktop.
WordPress smoothstate implementation
(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);
@tarik916
Copy link

Thank you so much for sharing this code. I was able to use it on a current website project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment