jQuery & history.js example
Asked Answered
A

2

13

I'm having a little trouble using history.js with jQuery. I just wanted to make a navigation set work with the back button (which they do seem to be doing quite nicely). However. When I click the back button the url changes to the old (which again is good and what I want) but the content does not replace as it should.

To make this a little more understandable here's some code.

    <ul class="content_links">
        <li><a href="/historyapi/pages/content_page_1.html">Content page 1</a></li>
        <li><a href="/historyapi/pages/content_page_2.html">Content page 2</a></li>
        <li><a href="/historyapi/pages/content_page_3.html">Content page 3</a></li>
        <li><a href="/historyapi/pages/content_page_4.html">Content page 4</a></li>
        <li><a href="/historyapi/pages/content_page_5.html">Content page 5</a></li>
    </ul>
    <div id="content">
        <p>Content within this box is replaced with content from supporting pages using javascript and AJAX.
    </div>

Obviously what I want is the content of the pages load into content which is done nice and easily with .load() and then I want the back button to move backwards through them if the user uses it. At the moment the URLs change but the content in the box does not. How would I go about changing or fixing that?

Alcala answered 25/11, 2012 at 16:36 Comment(0)
V
37

Try the following:

<ul class="content_links">
    <li><a href="/historyapi/pages/content_page_1.html">Content page 1</a></li>
    <li><a href="/historyapi/pages/content_page_2.html">Content page 2</a></li>
    <li><a href="/historyapi/pages/content_page_3.html">Content page 3</a></li>
    <li><a href="/historyapi/pages/content_page_4.html">Content page 4</a></li>
    <li><a href="/historyapi/pages/content_page_5.html">Content page 5</a></li>
</ul>
<div id="content">
    <p>Content within this box is replaced with content from supporting pages using javascript and AJAX.
</div>

<script>
$(function() {

    // Prepare
    var History = window.History; // Note: We are using a capital H instead of a lower h
    if ( !History.enabled ) {
         // History.js is disabled for this browser.
         // This is because we can optionally choose to support HTML4 browsers or not.
        return false;
    }

    // Bind to StateChange Event
    History.Adapter.bind(window,'statechange',function() { // Note: We are using statechange instead of popstate
        var State = History.getState();
        $('#content').load(State.url);
        /* Instead of the line above, you could run the code below if the url returns the whole page instead of just the content (assuming it has a `#content`):
        $.get(State.url, function(response) {
            $('#content').html($(response).find('#content').html()); });
        */
        });


    // Capture all the links to push their url to the history stack and trigger the StateChange Event
    $('a').click(function(evt) {
        evt.preventDefault();
        History.pushState(null, $(this).text(), $(this).attr('href'));
    });
});
</script>
Voodoo answered 25/11, 2012 at 16:44 Comment(10)
Love your work man, worked a treat. Presumably I could wrap some say History.pushState(null, $(this).text(), $(this).attr('href')); in if(!History.enabled) to make sure it degrades gracefully or would the above suffice?Alcala
Also I would need to ensure cross domain links and https links we're checked properly, I guess?Alcala
The return false will make it degrade gracefully. And yes, you should check for external links within the $('a').click().Voodoo
Yep, would also need to check for https links I guess. Come across anything good before?Alcala
Although I could just fine tune the ajax selector from $('a') to $('. content_links a') then it wouldn't really be an issue.Alcala
I would provide every link with a classname so you'd get something like $('a.ajax'). Changing it to $('.content_links a') would also do the trick.Voodoo
@Voodoo i know this is an old post, but i just found out about history.js and am trying to figure things out. i copied your example and it works fine. but when i add history.js and you jquery code on my site, it don't seem to work. do all linked pages have to be just content being passed? instead of headers and footers?Windgall
@user2035819 yes, ideally only the content within #content should be returned in case of an ajax request (you can check this server side). If you don't have control over what's returned, you can change $('#content').load(State.url); to $.get(State.url, function(response) { $('#content').html($(response).find('#content').html()); });Voodoo
wow, that's alot of code to change then. ALL my href's must be changed to return just contentWindgall
@user2035819 No, all you're a's clicks are being handled by the statechange event, so that code is only being replaced in that eventVoodoo
Z
2

it seems the following bit doesn't work:

$.get(State.url, function(response) {
  $('#content').html($(response).find('#content').html());
});

You have to convert the 'response' into a dom element before you can use 'find' on it. Like so:

$.get(State.url, function(response) {
    var d = document.createElement('div');
    d.innerHTML = response;
    $('#content').html($(d).find('#content').html());
});
Zenobia answered 15/12, 2014 at 13:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.