How to boost your site using jQuery + AJAX
Top

The issue I came across in day-to-day work seemed plain and straightforward. The goal was to switch pages using AJAX, without page reload. Including animations: before AJAX request and after AJAX response. All these things I’ve done before separately, but the routing part was new to me so I had to do some research where I found out I needed the:

  • history.pushState to add urls to browser history without refreshing pages;
  • window.onpopstate to listen to back/forward browser button click events.

Instead of writing my own scripts I was pretty sure that the internet already had swarms of ready solutions. The first plugin that I got my hands on was jQuery-Pjax. It was pretty clear on how to make use of it, so I proceeded.

jQuery + AJAX with history.pushState and popstate event = Pjax

It allows you to change page content and page url without reloading the page. The Pjax example is simple to understand and fast to start working with:

	$(document).pjax('a', '#pjax-container');

This will enable Pjax on all links on the page and replace #pjax-container content with the data retrieved from the link target. It will also prevent all links on the page from their default behavior. The HTML code for this example could be something like this:

index.html:

	nav menu: 
    <a href="./content.html">content</a> | 
    <a href="./main.html">home</a>

<div id="pjax-container">
    Hello Pjax!
</div>

some outer content
<!-- scripts load -->

content.html can contain any html structure that will be imported to #pjax-container, I’m using plain text for this example:

Hello pjax! This is content.html.

main.html:

Hello pjax! This is main.html.

Pretty neat and fast. Back/forward browser buttons work as expected. But that’s not exactly the behavior I was looking for. If I type /content.html or /main.html manually to the browser’s address bar, the browser will only show plain text content from these files. I should make code adjustments to make it possible to enter my web-site from any page. At first I need to make sure all HTML pages contain full HTML, the difference will only be inside <div id=”pjax-container”> containers. I can also add data-pjax attributes to distinguish Pjax links from default ones like so:

<a data-pjax href="./content.html">content</a> 

My new script:

$('a[data-pjax]').click(function(event) {
    $.pjax({
        url: event.target.href,
        container: '#pjax-container',
        fragment: '#pjax-container'
    });

    return false;
});

Here I use jQuery to add a click event listener to links with the data-pjax attribute and prevent their default behavior by returning false.

  • URL option tells Pjax to use my link’s href attribute to supply address bar with a new URL;
  • container marks which element’s content will be replaced;
  • fragment tells Pjax that it should only fetch a fragment to replace, here we should define its selector.

You can see the full Pjax options list here:
https://github.com/defunkt/jquery-pjax#pjax-options

Now that it works as expected, the next thing I need to do is add animations between page transitions. So my modified code looked similar to this:

	$('a[data-pjax]').click(function(event) {
    $('#pjax-container').fadeOut(500, function() {
        $.pjax({
          url: event.target.href,
          container: '#pjax-container',
          fragment: '#pjax-container'
        })
    })

    return false;
});

Here I trigger Pjax transition when the fade out animation finishes. Pjax replaces the content. Now I need to trigger the fade in animation, so i use the pjax:success hook. Behold the code:

	$(document).on('pjax:success', function() {
    $('#pjax-container').fadeIn(500);
});

It works fine, but there is an issue hard to spot at first sight. When you press the back/forward buttons, the page’s navigation is valid, but animations are missing. I tried using different Pjax hooks like pjax:start and pjax:end, and also tried attaching animations to the window.onpopstate event handler.

Eventually the animations became triggered with back/forward buttons but Pjax persisted with “no delay” between page transitions. The content of the previous/next pages appears in specified containers before the intro animation. This is a known issue, the developer of Pjax says there will be no animation support:

Animations are a punt.
Sorry, ?
(c) Joshua Peek

Smoothstate Js Leaves No Stitches

The next plugin was smoothState.js, which effectively works out the back/forward animation issue. I like this demo of the plugin:
https://rawgit.com/miguel-perez/smoothState.js/master/demos/sidebar/page-two.html
You can also check out the rest of the demos on the following GitHub page:
https://github.com/miguel-perez/smoothState.js?files=1#contributor-demos

How it works: You have several pages linked together. When you hover over the link, it triggers AJAX request and starts fetching page content. So when you start the page transition animation it’s content should already be accessible, making a smooth intro/outro animation shift. It fetches the page only once meaning if you hover page-2 and then move to page-3 – hovering on page-2 again wouldn’t trigger the AJAX request. You’ve already fetched the page!

What I need for my project is smoothState js without page reload.

Naming conflicts

There is another MoOx/pjax plugin that uses vanilla JavaScript. It shares the name with jquery-pjax, so it was difficult to search the right code samples with examples. At first glance this other Pjax plugin assures it can handle the back/forward animation issue, but it turned out that the plugin was not usable for several reasons:

  • irrelevant documentation;
  • difficult to use from the box;
  • needs additional plugins installed manually;
  • the demo code from the plugin partly erases content on replacement.

And finally, you can tie animations only to CSS classes, but in my project I need to trigger custom JavaScript animations instead of CSS animations.

Back To School

So I came back to where I started and made my own solution. The code:
https://plnkr.co/edit/0VHcyucUDfa9dBnv9ebz

P.S. – don’t forget to re-initialize your scripts after transition to keep the replaced content interactive!

  • Muhammad Nur Kholis

    Good

up

Please turn your device