Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ajax and back button. Hash changes, but where is previous page state stored?

I am trying to make ajax work with the back button and am missing something central. Where are the previous page states stored?

CASE 1:

Click "make me red". ajax event occurs and page turns red. Hash = #red

Click "make me yellow". ajax event occurs and page turns yellow. Hash = #yellow

Click back button. Hash is now back to #red. But I also want the page to be red. It's still yellow.

CASE 2:

Click "make me red". ajax event occurs and page turns red. Hash = #red

Click "Go to other site". It goes to Google.

Click back button. We're back to site, hash = #red, but I also want the page to be red!

<!DOCTYPE html>
<html>
<style>
    .red{background:red}
    .yellow{background:yellow}
</style>
<head>
    <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script type="text/javascript">
    $(function(){
        $('.ajax_thing').click(function(){
            location.hash=$(this).attr('action_type');
            return false
        })
        var originalTitle=document.title
        function hashChange(){
            var page=location.hash.slice(1)
            if (page!=""){
                $('#content').load(page+".html #sub-content")
                document.title=originalTitle+' – '+page
            }
        }
        if ("onhashchange" in window){ // cool browser
            $(window).on('hashchange',hashChange).trigger('hashchange')
        }else{ // lame browser
            var lastHash=''
            setInterval(function(){
                if (lastHash!=location.hash)
                    hashChange()
                lastHash=location.hash
            },100)
        }
    })

    </script>
</head>
<body>
<menu>
       <li><a class="ajax_thing" id = "red_action" action_type="red">Make me red</a></li>
        <li><a class="ajax_thing" id = "yellow_action" action_type="yellow">Make me yellow</a></li>
</menu>
        <li><a href = "http://www.google.com">Go to other site</a></li>
</body>
</html>
<script>

$("#red_action").click(function(e) {
  // ajax here. on success:
    $("body").removeClass("yellow");
    $("body").addClass("red");
})

$("#yellow_action").click(function(e) {
  // ajax here. on success:
    $("body").removeClass("red");
    $("body").addClass("yellow");
})

</script>
like image 671
user984003 Avatar asked Jul 21 '13 07:07

user984003


2 Answers

Rather than using your JavaScript to drive your URLs, let your URLs drive your JavaScript. Let the window.onhashchange event handler do all the work. Everything else should just change the hash.

You don't even need click handlers for links, just set the url to the right hash:

<a href="#red">Red</a>

Then, your hashchange handler takes care of the rest:

function hashChange() {
    var page = location.hash.slice(1);
    if (page) {
        $('#content').load(page+".html #sub-content");
        document.title = originalTitle + ' – ' + page;
        switch (page) {
            // page specific functionality goes here
            case "red":
            case "yellow":
                $("body").removeClass("red yellow").addClass(page);
                break;
        }
    }
}

The only reason to change the hash at all is if you want to be able to come back to the page and have it load the same state based on the URL. So, you already have the requirement to let the URL drive the JavaScript, right? Else why are you changing the hash? Moving functionality out of click handlers, and into the hashchange event only simplifies things.

like image 169
gilly3 Avatar answered Oct 10 '22 04:10

gilly3


When using AJAX it's important to update the history manually using history.pushState

Then create a function testing for an onpopstate event and updating the content as required.

https://developer.mozilla.org/en-US/docs/Web/Guide/DOM/Manipulating_the_browser_history

like image 23
j00lz Avatar answered Oct 10 '22 04:10

j00lz