Linda
Linda

Reputation: 2405

history.pushtState / back button / Navigation in a single page app

I'm building a small single page app with a navigation. the pages are position in div-container which are display by clicking on a link. The code for the page changig

        // show the given page, hide the rest
        function show(elementID) {
            history.pushState({ 
                plate_id: 1, 
                plate: elementID 
            }, null, elementID);
            goTo(elementID);
        }
        function goTo(elementID) {
            var ele = document.getElementById(elementID);
            if (!ele) {
                console.log("fail");
                return;
            }
            // get all pages, loop through them and hide them
            var pages = document.getElementsByClassName('page');

            for(var i = 0; i < pages.length; i++) {
                pages[i].style.display = 'none';
            }
            // then show the requested page
            ele.style.display = 'block';
        }
        window.onpopstate = function (event) {  
              var content = "";
              if(event.state) {
                content = event.state.plate;
              }
              if (content != '') goTo(content);
        }

the links looks like

<a href="#" onclick="show('Page_1');" id="1">page 1</a>

and the divs

<div id="Page_1" class="page" style="">

now when i'm using a link the url changes to .../Page_1# or .../Page_2# and the page is display directly. Now if i use a back button (own or browser doesn't matter) some magic happens which i don't understand.

for example

  1. clicking on first link -> go to ../Page_1# (directly, everythinks fine)
  2. clicking on secound link -> go to ../Page_2# (directly, everythinks fine)
  3. using back button -> go to ../Page_2 (without # and nothing happens but should go to Page_1???!!)
  4. using back button again -> go to ../Page_1# (nothing happen)
  5. using back button again -> go to ../Page_1 (page 1 is loading)

i don't understand why the thinks in step 3 and 4 happens! it will be nice if someone could help me

Upvotes: 1

Views: 1606

Answers (2)

AWolf
AWolf

Reputation: 8980

I would do this with AngularJS, because there you don't have to care about history.js. It's working out of the box.

Please check the following demo to get you started. You can also find the same code at jsFiddle here.

At the links the active class are not set properly, but that's not difficult to do. That's described at some examples at AngularJS and here at SO. See this SO question

'use strict';

var pageTemplate = "<div>{{page.title}}<div>";
var pageTitles = ['Page1', 'Page2'];

var app = angular.module('routingDemo', ['ngRoute']);

app.config(['$routeProvider', '$locationProvider',

function ($routeProvider, $locationProvider) {
    //$locationProvider.html5Mode(true);

    $routeProvider.
    when('/', {
        //templateUrl: 'partials/phone-list.html',
        template: "<div>main page</div>",
        //controller: 'MainCtrl'
    }).
    when('/pages/:pageId', {
        //templateUrl: 'partials/phone-detail.html',
        template: pageTemplate,
        controller: 'PagesCtrl'
    }).
    otherwise({
        redirectTo: '/'
    });
}]);

app.controller('PagesCtrl', ['$scope', '$routeParams', function ($scope, $routeParams) {
    $scope.page = {
        'title': pageTitles[$routeParams.pageId - 1]
    };
}]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.3/angular.js"></script>
<script src="https://code.angularjs.org/1.2.6/angular-route.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"/>

<div ng-app="routingDemo">
    <nav class="navbar navbar-default" role="navigation">
        <div class="navbar-header"> 
            <a class="navbar-brand" href="#/">Static pages demo</a>
        </div>
        <div>
            <ul class="nav navbar-nav">
                <li class="active"><a href="#/pages/1">Page 1</a></li>
                <li><a href="#/pages/2">Page 2</a></li>
            </ul>
        </div>
    </nav>
    <div class="container" ng-view></div>
</div>

Upvotes: 0

evilham
evilham

Reputation: 336

Maybe you want your link's onclick to be: onclick="show('Page_1'); return false;" or onclick="return show('Page_1');" and your show function to finish with return false;.

By returning false, the browser won't actually follow the href="#" but just execute your JavaScript instead.

Upvotes: 1

Related Questions