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.
- var $wrap = $( "#wrap" );
- // 2.
- $wrap.on( "click", ".page-link", function( event ) {
- // 3.
- event.preventDefault();
- // 4.
- if ( window.location === this.href ) {
- return;
- }
- // 5.
- var pageTitle = ( this.title ) ? this.title : this.textContent;
- pageTitle = ( this.getAttribute( "rel" ) === "home" ) ? pageTitle : pageTitle + " รข€” Acme";
- // 6.
- History.pushState( null, pageTitle, this.href );
- } );
- 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.
The page title and the URL are changed |
Content
We need to add the following lines of code to replace the actual page content.
- // 1.
- History.Adapter.bind( window, "statechange", function() {
- // 2.
- var state = History.getState();
- // 3.
- $.get( state.url, function( res ) {
- // 4.
- $.each( $( res ), function( index, elem ) {
- if ( $wrap.selector !== "#" + elem.id ) {
- return;
- }
- $wrap.html( $( elem ).html() );
- } );
- } );
- } );
- 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.
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:
- @keyframes slideInUp {
- from {
- transform: translate3d(0, 10px, 0);
- opacity: 0;
- }
- to {
- transform: translate3d(0, 0, 0);
- opacity: 1;
- }
- }
- .section {
- animation-duration: .38s;
- animation-fill-mode: both;
- animation-name: slideInUp;
- }
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:
- <script>
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
- ga('create', 'UA-XXXXXX-XX', 'auto');
- ga('send', 'pageview');
- </script>
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:
- $wrap.html( $( elem ).html() )
- .promise()
- .done( function( res ) {
- // Make sure the new content is added, and the 'ga()' method is available.
- if ( typeof ga === "function" && res.length !== 0 ) {
- ga('set', {
- page: window.location.pathname,
- title: state.title
- });
- ga('send', 'pageview');
- }
- });
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