SmoothState.js & WordPress

15th August 2014

This tutorial will be a quick run through of how to include the very nice looking SmoothState within your wordpress theme.

Required Items

The code below should be able to be added to any wordpress theme with minor tweaking but is based off the wordpress “twentyfourteen” theme.

Step 1 – Include SmoothState

Include the SmoothState js file using the wp_enqueue_scripts within the wordpress functions.php file of your theme, if your theme does not already have a functions.php file then you will need to create one.

if (!is_admin()) add_action("wp_enqueue_scripts", "my_jquery_enqueue", 11);
function my_jquery_enqueue() {
	wp_register_script('smoothState', get_template_directory_uri() . "/js/vendor/jquery.smoothState.js", array('jquery'), null, true);
	wp_enqueue_script('smoothState');
}

If you functions.php file already includes the wp_enqueue_scripts which the “twentyfourteen” theme does and can be searched for, then you will only need to add the below two lines:

wp_register_script('smoothState', get_template_directory_uri() . "/js/vendor/jquery.smoothState.js", array('jquery'), null, true);
wp_enqueue_script('smoothState');

Step 2 – Wrap Your Content

In order for SmootState to work correctly you will need to wrap the content with an ID so that SmoothState can swap out the content using Ajax in order for this to work correctly within a wordpress theme we will do the following.

Go into your header.php create two extra divs after the body tag the first one we will add our unique ID too for SmoothState to target in this case we will be calling it “main” this should now look similar to the below:

<body <?php body_class(''); ?>>
 <!-- Start #main -->
 <div id="main" class="m-scene">
 <div>

On the second div we will be taking the body_class from the body and adding it to this div the reason behind this is that we still want the classes to change dependent on which part of the site we are looking at on the frontend. If your theme does not have the body_class on the body then you can still include it. This will make the HTML look like the below:

<body>
 <!-- Start #main -->
 <div id="main" class="m-scene">
 <!-- Start body_class -->
 <div <?php body_class(''); ?>>

Once you have done that you will want to go into your footer.php file and close the two div’s we just created in our header.php file, this is placed just before any script tags and the php snippet <?php wp_footer(); ?> your code should now look similar to the below.

 </div>
 <!-- End body_class -->
 </div>
 <!-- End #main -->

 <?php wp_footer(); ?>

 </body>
</html>

Step 3 – Writing the Jquery

Within your js folder if you do not have a custom js file then you should create one and include it the same way we did for SmoothState in Step 1.

This file is called functions.js within the “twentyfourteen” theme and will already be included.

The script you will need to add is below:

$(function() {
	var $body = $('html, body'),
	content = $('#main').smoothState({
		prefetch: true,
        pageCacheSize: 4,
        // blacklist anything you dont want targeted
		blacklist : '',
		development : false,
		// Runs when a link has been activated
		onStart: {
	  		duration: 250, // Duration of our animation
	  		render: function (url, $container) {
		    	// toggleAnimationClass() is a public method
		    	// for restarting css animations with a class
		    	content.toggleAnimationClass('is-exiting');
		    	// Scroll user to the top
		    	$body.animate({
		      		scrollTop: 0
		    	});
	  		}
	  	},
	  	onEnd : {
		    duration: 0, // Duration of the animations, if any.
		    render: function (url, $container, $content) {
		        $body.css('cursor', 'auto');
		        $body.find('a').css('cursor', 'auto');
		        $container.html($content);
		        // Trigger document.ready and window.load
		        $(document).ready();
		        $(window).trigger('load');
		    }
		},
	  	onAfter : function(url, $container, $content) {

		}
	}).data('smoothState');
	//.data('smoothState') makes public methods available
});

In order for any plugins that are running of jquery.ready we will need to add the below code to the same file:

(function($, undefined) {
    var isFired = false;
    var oldReady = jQuery.fn.ready;
    $(function() {
        isFired = true;
        $(document).ready();
    });
    jQuery.fn.ready = function(fn) {
        if(fn === undefined) {
            $(document).trigger('_is_ready');
            return;
        }
        if(isFired) {
            window.setTimeout(fn, 1);
        }
        $(document).bind('_is_ready', fn);
    };
})(jQuery);

This will get SmoothState working on your wordpress theme, you can add animations following the documentation on SmoothState I will add another post explaining how to do this on your index.php and page.php files.

Final Thoughts

If you run into any issues adding this to your wordpress site please leave a comment below or send me a message using the contact form.

This should be easy enough to build as a wordpress plugin too and might be something I look into doing at a later stage.

*NOTE*

28/04/2015 At the moment I do not currently have smoothstate installed on this website as I really want to get the time to delve into the code and get it working smoothly with wordpress without having to hack bits in, making sure it plays well with other wordpress plugins.

Category: jQuery, Wordpress Tags: , , , , |

  • http://departmentdesign.co/ Reide Iredale

    Been hanging to include this in theme development lately. Thanks for the write up Alan.

    • http://www.parsonsprojects.co.uk/ ParsonsProjects

      No problem, hope it helps :)
      I may have an update coming for a better way of firing off the jQuery events.

      • http://www.mecanographik.fr/ Mecanographik

        Hi,
        Thanks for your post, it works with my wordpress theme, based on Sage (www.roots.io)
        I still have an important issue related to a particular plugin : Mmenu
        http://mmenu.frebsite.nl/wordpress-plugin.html

        This awesome plugin injects a menu just after the body tag (because it have to push all the canvas to the right because it’s a sliding panel)
        so with your technic, the links placed in this menu are not put in place by smooth state, because the menu bloc will always be placed before the smooth sate main bloc :

        How can i apply smoothstate ajax to the link placed in ‘.wpmm-menu’ ?

        see my code below :

        Accueil


        Menu

        Menu

        Accueil
        Blog
        Contact
        Groupes
        Membres
        Activités du site

        You are using an outdated browser. Please upgrade your browser to improve your experience.

        MENU

        Accueil

        Blog
        Contact
        Groupes
        Membres
        Activités du site

        How can i apply smoothstate ajax to the link placed in ‘.wpmm-menu’ ?
        Thanks for your help!

  • Trevor Robertson

    Just wondering how you managed to get your plugin scripts (i.e. Contact Form 7) to load in combo with SmoothState. As folks are chatting about here: https://github.com/weblinc/jquery.smoothState.js/issues/64 there are difficulties making this happen.

    I have the same issue in that I can’t get any plugins that load scripts in the footer to work since the script is not being loaded unless you refresh the page. However it seems like you have found a way around this. Any insights would be hugely appreciated. Thanks!

    • http://www.parsonsprojects.co.uk/ ParsonsProjects

      Hi Trevor,
      I have mentioned above the way that I used:

      $(document).ready();
      $(window).trigger('load');

      inside the smoothstate call and the extra bit of code mentioned above.

      This relies on the jquery files being available at all times, which might require you to include it manually and not rely on the plugin. I’m afraid its not as easy as plug and play.

      I am also currently looking at a better way of making the ready functions publicly viewable with a script that Miguel has provided me, will update after I have looked into this.

      • Trevor Robertson

        Right o, gotcha on the doc.ready stuff, though that’s awesome there may be a better way to handle this. And thanks for the VERY quick reply!!

        The part I’m unsure of is manually including plugin scripts. What I would want to avoid is the script loading twice, which is what would happen if you refresh (F5) a page, as it would then load the plugin script and the manually injected one, if that makes sense.

        I guess to ensure this doesn’t happen one would have to go into each plugin and find the wp_enqueue_script() details so you can properly use wp_deregister_script(). After that you can then safely manually load the script right, knowing you won’t end up loading it twice? Certainly I bit of a pain but likely worth it for the awesomeness that is SmoothState. :)

        • http://www.parsonsprojects.co.uk/ ParsonsProjects

          No problem.

          Yes that is what I would do go into the plugin find the registered scripts then de-register and register them back a bit of a pain but at the moment I dont think there is another way of doing this.

          An ideal solution would be to write something that finds all the registered scripts and loads them all in without duplicating them. Having done a quick google this was one of the first answers I found http://wordpress.org/ideas/topic/function-to-display-an-array-of-all-enqueued-scriptsstyles might be worth digging around there.

          I will look into this when I have some free time as it would be useful to integrate as a SmoothState plugin for wordpress.

  • myol

    IMHO after spending hours on this (to my own fault) you should add a small section for the css, rather than just linking to the git. I never realised that nearly EVERY bit of css needed a prefix to get working in any sensible way (skipped @-webkit-keyframes). Add that, and you have an A+ article.

    • http://www.parsonsprojects.co.uk/ ParsonsProjects

      Hello myol,
      Yea I will be writing up how to include the CSS animations at some point just need to find some spare time :)

  • Deni

    Hi,

    Thanks for this tutorial.

    I’m getting problems with loading the social buttons like (facebook, twitter like buttons) and I’m using one plugin (https://wpjobmanager.com/) that is based on ajax. I know you’ve mentioned $(document).ready()… and $(window).trigger(‘load’); however those work only when the page has been refreshed.

    Thanks again,
    Deni

    • Alan Parsons

      Hi Deni,

      This is all to do with the way that the jQuery events get fired on page refresh or page load but as we are not technically re-loading the page when using smoothstate they never get fired. I do keep meaning to look into this and find a good solution to integrate with wordpress, it is just finding those spare few hours to do so.

      If you look at the bottom of this thread https://github.com/weblinc/jquery.smoothState.js/issues/64#issuecomment-54657406 you might be able to use the solution suggested by miguel-perez.

      Hope this helps.

  • Eric Biboso

    Hi, thanks for the tutorial!

    I have been able to get this working on my wp site to where i have pages loading via ajax, however, I have two issues.

    1) I have a function that changes the body class depending on which page or page template you are on. (i.e. .page-template-page-home-php when on the home page). The class does not change when it loads the page requested since there is no reloading of the page.

    2) My jQuery functions don’t seem to be firing after the page requested is loaded. This might be a similar issue that other people have been experiencing where plugins are not loading/working but at this point in my project I haven’t installed any wp plugins. So i’m thinking my issue and its solution may be different. How can I get my functions to fire on document.ready?

    Also, should this part of the js, pasted below, a solution to my second issue? Sorry, js semi-noob here.
    (function($, undefined) {
    var isFired = false;
    var oldReady = jQuery.fn.ready;
    $(function() {
    isFired = true;
    $(document).ready();
    });
    jQuery.fn.ready = function(fn) {
    if(fn === undefined) {
    $(document).trigger(‘_is_ready’);
    return;
    }
    if(isFired) {
    window.setTimeout(fn, 1);
    }
    $(document).bind(‘_is_ready’, fn);
    };
    })(jQuery);

  • Eric Biboso

    Hi it’s me again

    I got my jQuery functions to fire by using the solution provided miguel perez here – https://github.com/weblinc/jquery.smoothState.js/issues/64#issuecomment-54657406. I thought that was going to fix both of my issues but it did not.

    My first issue as I stated before was that body_class() was not changing/working when the new page loads. However, I am starting to believe that since the page is not reloading the wordpress functions are not working at all. Where they should be loading the new page template and change the body class when the new page content is loaded. I hope this makes sense, i’m also starting to wonder if it’s even possible to achieve this. When using ajax to load content am I stuck with having to use the same page template throughout the entire site? When I request a new page I want to be able to load the new page template and fire the wp hooks etc. is this at all possible?

    • http://ww.parsonsprojects.co.uk Alan Parsons

      Hello Eric,

      Glad you managed to find a solution to your functions issue, I think there might be another way of doing this to fire off plugins but haven’t had any-time to look into this as yet.

      As for your second issue, my first thought would be to move the body_class() off from the actual body tag as I think this can be placed anywhere within the markup and it will generate the classes for that page so I would place it on a div tag that gets replaced by smoothstate but exists on every page, then target that with the function instead of the body. Hopefully that made sense.
      The hooks etc should always be fired as you are requesting the page that has generated by the PHP. The reason the body_class() isn’t working is because it is outside the HTML that is being grabbed by the ajax request.

  • Oli

    All I get is “TypeError: html.replace is not a function” errors all the time in the console. Any ideas what might be causing that ?

    • http://ww.parsonsprojects.co.uk Alan Parsons

      Hello Oli,

      Without seeing the whole code and other scripts you may be running it is difficult to say why this error is being thrown it looks like you are trying to call a function that doesn’t exist. Do you have a link to look at?

Get in touch

Need some work done or just a friendly chat.