- What a developer needs to know about history API for its effective use?
It is no secret that with the emergence of history API in HTML5, it became possible to easily operate browser history (without reboots or location.hash hacks). In this article we will consider all its possibilities and probable difficulties.
First, let’s take a look at browsers’ support.

[Is taken from [caniuse]
The statistics show that all up-to-date browsers support history API, which means that it can be safely used in projects.
What is it capable of?
To check the current state of an open tab session history you can simply address the history
object in the browser console via global object window
(window.history). Firefox browser console input will result in the following:

In this screenshot you can see history API general methods.
Methods explanation:
1. .length
- returns the amount of visited pages in given tab and session;
2. .state
- returns a current object of a history state (which can be rewritten);
3. .back
- goes one step back history, if possible;
4. .forward
- goes one step forward, if possible;
5. .go(step)
: a method, which allows to move within history depending on a passed argument (step)
Example:
window.history.go(1)
- identical to method.forward()
and will also go one step forward in history, if possible;
window.history.go(7)
- goes one step argument forward, also if possible;
window.history.go(-1)
- identical to method.back()
- correspondingly goes one step back in history, if possible;
window.history.go(-7)
- correspondingly, goes back in tab history according to a passed argument;
window.history.go(0)
0 if you pass argument0 (null)
, the browser will reboot a current page.
6. .pushState(data, title, url)
and .replaceState(data, title, url)
are the most important historyAPI methods, which add and replace information from the arguments a in history object.
The first argument (data) allows to record the necessary information for a current page, which is stored in object window.history.state.
The second argument (title) serves for storing tab names, but is not supported by many browsers.
The third argument (url) serves for recording the necessary URL on history API.
There also exists an event, which works at any tab history change - onpopstate
.
The screenshot below shows examples of methods use and events:
<body>
<button id="back">back</button>
<button id="forward">forward</button>
<button id="new_link">New Link</button>
<form action="" id="form">
<input type="number" step="1">
<input type="submit">
</form>
<script>
var back = document.getElementById('back');
var forward = document.getElementById('forward');
var new_link = document.getElementById('new_link');
var form = document.getElementById('form');
var input = document.querySelector('[type="number"]');
var i = 0;
new_link.addEventListener('click', function() {
window.history.pushState(i, '', window.location.origin + '/' + i + '_page');
i++;
}, false);
back.addEventListener('click', function() {
window.history.back()
}, false);
forward.addEventListener('click', function() {
window.history.forward()
}, false);
form.addEventListener('submit', function(e) {
e.preventDefault();
window.history.go(input.value);
});
window.addEventListener('popstate', function() {
alert('Change!')
}, false);
</script>
</body>
About difficulties.
When I used history API in our project Cubwise for switching chat dialogues, I faced the problem of Http and AJAX requests incorrect. When the page is loading, AJAX request for messages history is sent to the same URL as well as the first request for page rendering. AJAX request is also sent for dialogs switching ( all required data is stored in history object). Problems appeared at history navigation.
The reason for this is that the first action that the browser performs after scripts loading is AJAX request to get JSON with a dialogs, which browser remembers afterwards. And if we go to messages page from any other page using history switching buttons - a browser will sends you AJAX request instead of Http, and shows JSON instead of designing HTML layout and loading styles and scripts. A decision was logical - URLs must be changed! But since it was problematic for back-end, we had to find the way out in front-end. That is why we decided to send an empty argument in AJAX requests (it has no effect on server work), which made URLs different.
$(window).on('popstate', function() {
if (window.history.state) {
ajaxSwitchDialogOnHistory();
}
});
function ajaxSwitchDialogOnHistory() {
$.ajax({
url: window.location,
//** this block with "data" need for correct work history api **//
data: {
data: ''
},
//***//
type: 'GET',
success: function(data) {
var currentSelectedDialog = $('[dataidconversation=' + window.history.state.current + ']');
conversationPage.attr('data-current', window.history.state.current);
//Other code
//...
//..
//.
}
});
}

Sometimes you need to implement the support of old browsers. For such cases a number of libraries were created (up to IE6).