How to handle the back button when changing the browser URL using HTML5 pushState

Ive created a one page website. When the user presses the menu buttons, the content is loaded using ajax. It is working fine. To improve SEO and allow the user to copy / skip the URL of other content, I use

function show_content() { // change URL in browser bar) window.history.pushState("", "Content", "/content.php"); // ajax $content.load("ajax/content.php?id="+id); } 

It works great. URLs and browser do not reload page

However, when the user clicks the back button in the browser, the URL changes and the content must be loaded.

I did this and it works:

  window.onpopstate = function(event) { if (document.location.pathname == '/4-content.php') { show_content_1(); } else if (document.location.pathname == '/1-content.php') { show_content_2(); } else if (document.location.pathname == '/6-content.php') { show_content_(); } }; 

Do you know if there is a way to improve this code?

+3
source share
1 answer

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;)

+8
source

Source: https://habr.com/ru/post/985896/


All Articles