javascriptjquerygoogle-chromepushstatehtml5-history

History API pushState() creating two entries


As the title states, when I use pushState() to change the history, it adds my entry to the stack twice for some reason even though it's only clicked once. So then when I try to traverse back with the back button, I only get a popstate every other press of the button. And when I log the state to Console, any time I get a "pop" it shows "null".

This is what the history looks like:

http://example.com/foo/bar/question/8/
http://example.com/foo/bar/question/8/
http://example.com/foo/bar/question/3/
http://example.com/foo/bar/question/3/
http://example.com/foo/bar/question/27/
http://example.com/foo/bar/question/27/

What I'm trying to do is reload an iframe (and change the h1 text) on a link click without reloading the whole page, but still have the history traverseable and bookmarkable (is that a word?)... Seems like it should be simple, and I've gone through examples on MDN and other tutorials to no avail.

My code is below. I'm sure I'm doing something completely wrong, but any help/insight would be super appreciated!

$(".vidlinks a").on('click', function(e) {
    var frsrc = 'https://player.vimeo.com'+$(this).attr('data-iframe')+'?title=0&byline=0&portrait=0&badge=0&autopause=0&player_id=0&autoplay=1',
        targetUrl = $(this).attr('href'),
        pgtitle = $(this).attr('title'),
        obj = {url:targetUrl,ttl:pgtitle};
        $("iframe").attr('src', frsrc );
        $(".vidtitle h1").fadeOut("fast", function() {
            $(this).text(pgtitle);
        });
        $(".vidtitle h1").fadeIn("fast");

        window.history.pushState(obj, document.title, targetUrl);
        return false;
    });

   window.onpopstate = function(e) {
        $(".vidtitle h1").fadeOut("fast", function() {
            $(this).text(e.state.ttl);
        });
        $(".vidtitle h1").fadeIn("fast");
   }

EDIT: I also tried using replaceState() instead of pushState(). This sort of remedied the double entry issue, but using the back button doesn't change the state in the browser using this method. This has been tested on Chrome, Safari, and FF.

EDIT EDIT: Oddly enough, if I comment out the pushState() statement entirely, and click the back button, the iframe will reload to the previous video, but nothing else changes.


3(EDIT): So here is the iframe code...

<iframe src="https://player.vimeo.com/video/VIDEOID?title=0&amp;byline=0&amp;portrait=0&amp;badge=0&amp;autopause=0&amp;player_id=0&amp;autoplay=1" width="1920" height="1080" frameborder="0" title="THETITLE" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>

VIDEOID and THETITLE are just strings initially passed in from PHP.

I ran a console.log this time, and here's what it's doing. I click the link (once) that passes the new iframe src to the iframe, but this is creating two history entries. The first time the back button is clicked, the iframe reloads to the previous video and no popstate. The second time 'back' is clicked, I get the popstate with all the properties.


Solution

  • Changing an iframe's src adds two pushStates. The trick/hack/workaround is to remove the current iframe, build a new iframe fragment and insert it. Then, call your pushState.

    Source: Updating an iframe, history and URL. Then making it work with back button