How to determine the difference between onpopstate "real" and "virtual" events

I am creating a tool that uses AJAX and pushState / replaceState on top of a non-javascript backup ( http://biologos.org/resources/find ). Basically, this is a search tool that returns a list of real HTML links (clicking on the link takes you out of the tool).

I use onpopstate so that the user can navigate through the request history created by pushState . This event also fires when a pushState on a real link (one NOT created using pushState , but using the actual browser navigation). I do not want him to shoot here.

So here is my question: how can I tell the difference between the onpopstate event emanating from the pushState history element compared to what comes from the real navigation?

I want to do something like this:

 window.onpopstate = function(event){ if(event.realClick) return; // otherwise do something } 

I tried the onpopstate handler - ajax back button , but no luck :(

Thanks in advance!

EDIT: The problem is how different browsers handle the onpopstate event. Here is what seems to be happening:

Chromium

  • onpopstate fires onpopstate both real and virtual events
  • Actually re-runs javascript (so setting loaded=false will actually check for false)
  • The solution in the link provided really works!

Firefox

  • Only fire onpopstate for virtual events
  • Actually re-runs javascript (so setting loaded=false will actually check for false)
  • In order for the related solution to work, loaded must be set to true when the page loads, which violates Chrome!

Safari

  • onpopstate fires onpopstate both real and virtual events
  • It seems NOT to re-run javascript before the event (so loaded will be true if previously set to true!)

Hope I just missed something ...

+4
source share
1 answer

You might be able to use history.js . It should give you an API that will behave consistently on all major platforms (although it is possible that it does not address this particular problem, you will have to try to find it out).

However, in my opinion, the best way to deal with this (and other related problems) is to develop your application in such a way that these problems do not matter. Watch your expression, and not rely solely on the state object in the story stack.

Track which page your app is showing. Track it in a variable - separate from window.location . When a navigation event (including popstate) occurs, compare your known current page with the next page request. Start by figuring out if a page change is really needed. If so, render the requested page and call pushState if necessary (only to call pushState for "normal" navigation - never in response to the popstate event).

The same code that popstate handles should also handle your normal navigation. As far as your application is concerned, there should be no difference (besides the fact that regular nav includes a pushState call, while navstate-nav does not work).

Here is the main idea in the code (see live example in jsBin )

 // keep track of the current page. var currentPage = null; // This function will be called every time a navigation // is requested, whether the navigation request is due to // back/forward button, or whether it comes from calling // the `goTo` function in response to a user click... // either way, this function will be called. // // The argument `pathToShow` will indicate the pathname of // the page that is being requested. The var `currentPage` // will contain the pathname of the currently visible page. // `currentPage` will be `null` if we're coming in from // some other site. // // Don't call `_renderPage(path)` directly. Instead call // `goTo(path)` (eg. in response to the user clicking a link // in your app). // function _renderPage(pathToShow) { if (currentPage === pathToShow) { // if we're already on the proper page, then do nothing. // return false to indicate that no actual navigation // happened. // return false; } // ... // your data fetching and page-rendering // logic goes here // ... console.log("renderPage"); console.log(" prev page : " + currentPage); console.log(" next page : " + pathToShow); // be sure to update `currentPage` currentPage = pathToShow; // return true to indicate that a real navigation // happened, and should be stored in history stack // (eg. via pushState - see `function goTo()` below). return true; } // listen for popstate events, so we can handle // fwd/back buttons... // window.addEventListener('popstate', function(evt) { // ask the app to show the requested page // this will be a no-op if we're already on the // proper page. _renderPage(window.location.pathname); }); // call this function directly whenever you want to perform // a navigation (eg. when the user clicks a link or button). // function goTo(path) { // turn `path` into an absolute path, so it will compare // with `window.location.pathname`. (you probably want // something a bit more robust here... but this is just // an example). // var basePath, absPath; if (path[0] === '/') { absPath = path; } else { basePath = window.location.pathname.split('/'); basePath.pop(); basePath = basePath.join('/'); absPath = basePath + '/' + path; } // now show that page, and push it onto the history stack. var changedPages = _renderPage(absPath); if (changedPages) { // if renderPage says that a navigation happened, then // store it on the history stack, so the back/fwd buttons // will work. history.pushState({}, document.title, absPath); } } // whenever the javascript is executed (or "re-executed"), // just render whatever page is indicated in the browser // address-bar at this time. // _renderPage(window.location.pathname); 

If you look at the jsBin example, you will see that the _renderPage function _renderPage called every time the application asks for a transition to a new page - be it because of a popstate (for example, the back / fwd button) or because of a call to goTo(page) (for example , user actions of any kind). It is even called when the page loads.

Your logic in the _renderPage function can use the currentPage value to determine "where the request goes." If we exit the external site, then currentPage will be null , otherwise it will contain the path to the page currently being displayed.

+3
source

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


All Articles