What I did was pass the literal of the pushState() object when the page loads. This way you can always get back to your first pushState created. In my case, I had to press twice before I could return. Pressing the state to load the page helped me.
HTML5 allows you to use data attributes, so for your triggers you can use them to bind HTML data.
I use try catch because I did not have time to find polyfill for old browsers. You might want to check out Modernizr if necessary in your case.
Pageload
try { window.history.pushState({ url: '', id: this.content.data("id"), // html data-id label: this.content.data("label") // html data-label }, "just content or your label variable", window.location.href); } catch (e) { console.log(e); }
EVENTS EVENTS
Object filled with default information
var obj = { url: settings.assetsPath, // this came from php lang: settings.language, // this came from php historyData: {} };
Bind the trigger to history.pushState() . In my case, the delegate, since I have dynamic elements on the page.
// click a trigger -> push state this.root.on("click", ".cssSelector", function (ev) { var path = [], urlChunk = document.location.pathname; // to follow your example // some data-attributes you need? like id or label // override obj.historyData obj.historyData.id = $(ev.currentTarget).data("id"); // create a relative path for security reasons path.push("..", obj.lang, label, urlChunk); path = path.join("/"); // attempt to push a state try { window.history.pushState(obj.historyData, label, path); this.back.fadeIn(); this.showContent(obj.historyData.id); } catch (e) { console.log(e); } });
Bind the history.back() event to a custom button, link, or something else. I used .preventDefault() since my button is a link.
// click back arrow -> history this.back.on("click", function (ev) { ev.preventDefault(); window.history.back(); });
When the story returns → check the state pressed if it was not the first attempt
$(window).on("popstate", function (ev) { var originalState = ev.originalEvent.state || obj.historyData; if (!originalState) { // no history, hide the back button or something this.back.fadeOut(); return; } else { // do something this.showContent(obj.historyData.id); } });
Using object literals as a parameter is convenient to pass your identifiers. Then you can use one showContent(id) function.
Wherever I use this this is nothing more than a jQuery object / function stored inside IIFE .
Please note that I put these scripts from my implementation, combined with some ideas from your original request. Therefore, I hope this gives you some new ideas;)