Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two clicks at back button are necessary to trigger popstate/statechange event

I have a page which contains an iframe. The iframe can take user's input (via button click or menu selection) and display content accordingly. What I need is, when a user manipulates the iframe, the browser push each set of iframe parameters into history; and when the user click at back button, the iframe will reload its content using the saved parameters from the previous history entry. I have a piece of code doing the reloading as shown below.

The strange thing is, when I make multiple settings on the iframe (hence multiple state entries added to history), and then click at back, it'll work like this,

Say that I have state 4, 3, 2 in history and I'm now at state 5

  1. the first click restore to state 4 (the "----state changed----" logging message is printed
  2. the second click reloads the iframe with default content. The "----state changed----" is not printed; the reloading code is not called.
  3. the third click restore to state 3
  4. the fourth click is like the 2nd click
  5. the 5th click restore to state 2

So after each click that successfully restore the state, it takes two clicks to trigger the popstate event (I tried statechanged event, too, with same result) and restore to another previous state.

Anyone know what's going on here? Thanks in advance.

History.Adapter.bind(window, "popstate",
    function (event) {
        console.log("----state changed------", History.getState());   
        console.log("----state data------",History.getState().data.state);  

           //code to do reload an iframe to its proper state

    }); 
like image 933
Farrell Avatar asked Oct 04 '22 03:10

Farrell


1 Answers

So I stumbled on this same issue. The situation we had was using history.pushState() to update the URL and then after that changing the src attribute of an <iframe>. By changing the src of the <iframe>, we are implicitly telling the browser to add to its history that the iframe had changed. Thus...

  1. When we pressed back the first time, window.history's popstate is triggered on the <iframe>'s src attribute and is reverted back to it's previous state.
  2. Pressing back a second time triggers the popstate event for the state you originally pushed onto the stack

Our solution involved that when we decided to update the URL and push the state onto the stack, when we wanted to update the <iframe>, we used jQuery to replace the <iframe> list so...

$("#iFrameID").replaceWith(('<iframe id="iFrameID" src="' + location + '"></iframe>'

By doing this, we removed the side effect of the browser history getting polluted with our update to the <iframe> tag.

like image 148
Kevin Avatar answered Oct 13 '22 03:10

Kevin