Getting Backbutton to work in single page website and implementing "speaking" URLs
Asked Answered
P

3

18

I have a single page website and would like to achieve the following:

  1. back button working as if it was a normal website

  2. and instead of say,

www.mysite.com/index.php?p=#this-is-a-great-product

I'd like to have this url

www.mysite.com/this-is-a-great-product

while still having back button working properly.

Regarding 1.) I use the following code ive found which works great:

<!-- Getting BackButton to  work properly -->
<script type="text/javascript">
var times = 0;
function doclick() {
    times++;
}
function doclick() {
    times++;
    location.hash = times;
}
window.onhashchange = function() {     
    if (location.hash.length > 0) {        
        times = parseInt(location.hash.replace('#',''),10);     
    } else {
        times = 0;
    }
}
</script>

…but of course it just changes any anchors to /#1, then /#2 and so forth ro get the backbutton to work. But as I'm not a programmer I don't know how to change it… :(

Regarding 2.) i can add in htaccess this:

>RewriteEngine On
>RewriteRule ^([^/.]+)/?$ /index.php?page=$1

and this changes /index.php?p=products to /products.

So how do I change the above code (under 1.) so it doesn't change all anchors to #1, #2, etc. but instead references / uses the urls I achieved under 2, like

www.mysite.com/this-is-a-great-product

And (probably a very dumb question, but a very important one) -given I use only the new url links on my site- is there any danger that this still might result in duplicate content in any way?

Regarding this, should I (for that reason or any other) sefreferential my single page index.php to itself using rel canonical link=index.php?

Thanks so much in advance!

Patti answered 29/1, 2014 at 8:50 Comment(0)
M
3

As mentioned, you will want to use the HTML5 History API. Please note, this API is relatively new and therefore browser support is a concern. At the time of writing, approximately 71% of global Internet users have support for it (see http://caniuse.com/#feat=history for browser support information). Therefore, you will want to ensure you have a fall-back solution for this. You will likely want to use the older #! solution that was popular before the HTML 5 History API was adopted.

If you use the history API to replace, for example, example.com/#!settings with example.com/settings and a user bookmarks that nicer URL, then when they go to visit it, their browser will make a request to the server for /settings (which doesn't actually exist in the web server's context). Therefore, you will need to make sure your web server has some redirection rules (i.e. RewriteEngine) such that it can take the pretty URLs and redirect them to the #! version (and then if the user's browser supports the history API it can replace that with the nice URL).

If you aren't very comfortable programming yourself, I'd recommend using a JavaScript library that does a lot of the work for you. I did some quick searching and discovered the following, though there might be better ones out there: https://github.com/browserstate/history.js

Metallic answered 1/2, 2014 at 16:12 Comment(0)
L
1

Basically i have created a small prototype on jsfiddle which tracks all the urls accessed via ajax calls.

Also contains navigation to access links back and forth .

How It Actually Works:

  • I have created a global array called history, which keeps track of all urls accessed via ajax in sequence.
  • also there a global index defined to keep track of the url being accessed when navigating back and forth the links in history array.
  • There is History section at the bottom of the jsfiddle, which shows the sequence in which the links are accessed by capturing the link names and posting them in the order in which they were accessed.

JS Code:

$(function () {
var history = [];
var index = 0;
$('.links').on('click', function () {
    $('#history').append($(this).text());
    var address = $(this).attr('data-ref');
    index += 1;
    history[index] = address;

    $('.links').attr('disabled', 'disabled');
    loadExternalPage(address);
    console.log('list:' + history);
});

$('#back').on('click', function () {
    console.log(index);
    index -= 1;
    console.log(index);
    console.log(history[index]);
    loadExternalPage(history[index]);
});

$('#forward').on('click', function () {
    console.log(index);
    index += 1;
    console.log(index);
    console.log(history[index]);
    loadExternalPage(history[index]);
});

var loadExternalPage = function (address) {
    console.log(history[index]);
    $('#result-section').load(address, function () {
        console.log('data-loaded');
        $('.links').removeAttr('disabled');
    });
};
});

Live Demo @ JSFiddle:http://jsfiddle.net/dreamweiver/dpwmcu0b/8/

Note: This solution is far from being perfect, so dont consider it as final solution but rather use it as a base to build upon

Le answered 22/7, 2015 at 14:34 Comment(2)
Fiddle not available anymore :(Mccay
@JackMiller Existing jsfiddle link was corrupted, now it's been updated, Happy Coding :)Le
F
1
  1. On using BACK and FORWARD functions in the browser top-left button:

In principle, there is no great problem with this as long as you work with the existing storage object (a stack) for previously visited web pages on your browser. This object is the history object and you can see what is in it anytime by right-clicking and selecting "Inspect", then selecting the "Console" tab, then enter window.history and enter. Check out the Browser Object Model (BOM) section of Pro Java For Web Developers (Frisbee) for the background to the history object. (Just a few pages, an easy read, don't worry.) Just remember that in this process you are storing the new page that you move to, not the old page that you are leaving !

For a simple SPA example, look at this example - codepen.io/tamjk/pen/NWxWOxL

  1. In regard to the URL, the method that the history object uses to load a new page state into the history stack, i.e. pushState(...), has an optional third parameter for associating a dummy URL for each web page that is stored. Personally, when I first sorted out the BACK & FORWARD functions, I did not use dummy URLs as the browser was being confused by them and I had enough to do sorting out the history sequence using just the first two parameters, i.e.
  • the state object - a JSON holding enough data to recreate the page stored
  • a title for the page I expect that you could also use a dummy URL but I will leave that to the student as an exercise, as they say.

But you can add the URL of the new page if you want to.

In the example above, for the state object I just used the IDs of the page's nav link and its content element. For the title, I programmatically changed the HTML's page title element with each change of page. I did this after noticing that the browser listed the previous pages according to the title element in the HTML code. Unfortunately, this title does not show up on CodePen when you right-click on the browser BACK and FORWARD buttons due to CodePen's system not allowing it. But it will show on your own sites.

It's important that whatever method you use to store current web page states when using the navbar links to navigate, you DO NOT ADD page states to the browser history when you arrive at them using BACK or FORWARD buttons. Otherwise your history stack will have repetitions of entries going back and deletion of entries going forward.
In the CodePen, this was achieved by having the addToHistory(..) function separate to and outside the scope of the switchPage(...) function. This allows you use of the switchPage function in both normal navbar navigation and browser BACK/FORWARD navigation. The third parameter of switchPage(...) is a boolean indicating if the page is to be stored in history or not.

Anyway, this is just something to get you started.

Flung answered 3/6, 2020 at 23:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.