Tuesday, August 16, 2016

Lovely, Smooth Page Transitions With the History Web API_part 2 (end)

Applying the History Web API

Before we begin writing any code, we need to create a new file to hold our JavaScript; we’ll name it script.js and load the file in the document before the body closing tag.

Let’s add our first piece of code to change the document title and the URL upon clicking the menu navigation:
  1. // 1.
  2. var $wrap = $( "#wrap" );
  3.  
  4. // 2.
  5. $wrap.on( "click", ".page-link", function( event ) {
  6.      
  7.     // 3.
  8.     event.preventDefault();
  9.      
  10.     // 4.
  11.     if ( window.location === this.href ) {
  12.         return;
  13.     }
  14.      
  15.     // 5.
  16.     var pageTitle = ( this.title ) ? this.title : this.textContent;
  17.         pageTitle = ( this.getAttribute( "rel" ) === "home" ) ? pageTitle : pageTitle + " — Acme";
  18.      
  19.     // 6.
  20.     History.pushState( null, pageTitle, this.href );
  21. } );
I’ve split the code apart into several numbered sections. These will make it easier for you to pinpoint the code with the following reference:
  • On the first line, we select the element, <div id="wrap"></div>, that wraps all of our website content.
  • We attach the click event. But, as you can see above, we attach it to the #wrap element instead of attaching the event directly on every menu navigation. This practice is known as event delegation. In other words, our #wrap element is responsible for listening to click events on behalf of .page-link.
  • We’ve also added event.preventDefault() so that the users will not be directed to the page in question.
  • If the clicked menu URL is the same as the current window we do not need to proceed to the next operation, simply because it is not necessary.
  • The pageTitle variable contains the title format, derived from the link title attribute or the link text. Each page title follows {Page Title} — Acme convention, except for the home page. “Acme” is our fictitious company name.
  • Lastly, we pass the pageTitle and the page URL to the History.js pushState() method.
At this point, when we click on the menu navigation, the title as well as the URL should change accordingly as shown below:
The page title and the URL are changed
Yet the page content remains the same! It is not updated to match the new title and the new URL.

Content

We need to add the following lines of code to replace the actual page content.
  1. // 1.
  2. History.Adapter.bind( window, "statechange", function() {
  3.      
  4.     // 2.
  5.     var state = History.getState();
  6.      
  7.     // 3.
  8.     $.get( state.url, function( res ) {
  9.  
  10.         // 4.
  11.         $.each( $( res ), function( index, elem ) {
  12.             if ( $wrap.selector !== "#" + elem.id ) {
  13.                 return;
  14.             }
  15.             $wrap.html( $( elem ).html() );
  16.         } );
  17.  
  18.     } );
  19. } );
Again, the code here is split into several numbered sections.
  • The first line of the code listens to the History change performed via the History.js pushState() method and runs the attached function.
  • We retrieve the state changes, containing various data like a URL, title, and id.
  • Through the jQuery .get() method we retrieve the content from the given URL.
  • Lastly, we sort out the element with an id named wrap from the retrieved content, and eventually replace the current page content with it.
Once it’s added, the content should now be updated when we click on the menu navigation. As mentioned, we are also able to access visited pages back and forth through the browser Back and Forward buttons.


Our website is presentable at this point. However, we would like to step further by adding a little animation to bring the page to life and, finally, our website feels more compelling.

Adding Animation and Transitions

Animation in this situation need only be simple, so we’ll write everything fro scratch, instead of loading animations through a library like Animate.css, Motion UI of ZURB, or Effeckt.css. We’ll name the animation slideInUp, as follows:
  1. @keyframes slideInUp {
  2.     from {
  3.         transform: translate3d(0, 10px, 0);
  4.         opacity: 0;
  5.     }
  6.     to {
  7.         transform: translate3d(0, 0, 0);
  8.         opacity: 1;
  9.     }
  10. }
As the name implies, the animation will slide the page content from bottom to top along with the element opacity. Apply the animation to the element that wraps the page main content, as follows.
  1. .section {
  2.     animation-duration: .38s;
  3.     animation-fill-mode: both;
  4.     animation-name: slideInUp;
  5. }
The transition from one page to another one should now feel smoother once the animation is applied. Here, you may stop and call it a day! Our website is done and we are ready to deploy it for the world to see.

However, there is one more thing that you may need to consider adding, especially for those who want to monitor the number of visits and the visitors’ behavior on your website.

We need to add Google Analytics to track each page view.

Google Analytics

Since our pages will be loaded asynchronously (except for the initial page loaded) tracking the page view number should also be done asynchronously.

To begin with, make sure you have the standard Google Analytics added within the document head. The code usually looks something as follows:
  1. <script>
  2.         (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  3.             (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  4.             m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  5.         })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
  6.  
  7.         ga('create', 'UA-XXXXXX-XX', 'auto');
  8.         ga('send', 'pageview');
  9.  
  10.     </script>
Then we need to adjust our JavaScript code to include the Google Analytics tracking code so that every page loaded asynchronously will also be measured as a page view.

We have several options. First, we can start counting when the user clicks a navigation link, or when changing the page title and URL, or when the content of the page has been fully loaded.

We’ll opt for the latter, which is arguably the most authentic, and in doing so we leverage the jQuery promise() method after we change the page content, as follows:
  1. $wrap.html( $( elem ).html() )
  2.         .promise()
  3.             .done( function( res ) {
  4.  
  5.             // Make sure the new content is added, and the 'ga()' method is available.
  6.             if ( typeof ga === "function" && res.length !== 0 ) {
  7.                 ga('set', {
  8.                     page: window.location.pathname,
  9.                     title: state.title
  10.                 });
  11.                 ga('send', 'pageview');
  12.         }
  13.     });
That’s all it is, we will now have the page view recorded in Google Analytics.

Wrapping Up

In this tutorial we have improved a simple static website with Web History API to make the page transition smoother, the load faster, and overall deliver a better experience to our users. At the end of this tutorial, we also implemented Google Analytics to record user page view asynchronously. Additionally, our website is perfectly crawl-able by search engine bots since it is, as mentioned, just a simple HTML website.
Written by Thoriq Firdaus

If you found this post interesting, follow and support us.
Suggest for you:

Ultimate JavaScript Strings

Ultimate HTML5,CSS3 & JAVASCRIPT To Create Your Own Interractive Websites

Vue.JS Tutorials: Zero to Hero with VueJS JavaScript Framework

Learning ECMAScript 6: Moving to the New JavaScript

Closure Library: Build Complex JavaScript Applications

1 comment: