0

There is a problem with the "back" button of the browser and my application. The webapp uses ajax and standart requests. That all happens this way:

  1. I make GET request to list.jsp page - it's the first page you see in application if you check the temp link I provided below. Now we are on Page 1 (the whole page was reloaded)

  2. I make Ajax request (click on link - i.e. page number) to page 4. Only the parth of page was reloaded - everything is OK. Thus now we are on page 4

  3. I make Ajax request (click on link - i.e. page number) to page 5. Only the parth of page was reloaded - everything is OK. Thus now we are on page 5

  4. Now I press the browser "back" button (one step back to history) - nothing happened. The browser consoles does not show any changes.

  5. This step I press the browser "back" button again. It turns out that this step executed correctly. GET request happened.

What is going on? Why does the browser not remember changes that hapaned on step 3 ? How can I instruct the browser to make step back to history to the changes that was made by ajax request?

You can check it online by temp link. Just try to go throuh the pages. The pink square is current page indicator.


update 1:

This code initialized after loader finished loading recources.

$(function() {

    $(window).on('hashchange', refreshByHash);

    refreshByHash();

    function refreshByHash() {              
        var hash = window.location.hash; 
        console.log("hash = " + hash.substring(1));

        /* $.ajax({

               url : 'paginator.action?page=' + hash, // action
               type : 'GET', //type of posting the data
                dataType : 'html',
                async: true,
                success : function(htmlData) {
                    $('#paginator').html(htmlData);
                },
                error : function(xhr, ajaxOptions, thrownError) {
                    alert('An error occurred! ' + thrownError);
                },

            }); */

       }

 });
rozero
  • 149
  • 3
  • 15

2 Answers2

1

I would suggest you to put a hash parameter in the url, that way the browser would handle the history properly, and listen to hashchange events. In most cases you can store the page state directly there, so you don't have to implement your own history handling. I've put together a little MCVE:

$(function() {

  // setup some pagination bar
  for (var i = 1; i < 11; i++) {
    $('#pages').append(
        $('<a/>').text(i).attr('href','#'+i)
    );
    $('#pages').append($('<span/>').text('.'));
  }

  // load contents of page i
  function _uiPage(i) {
      // imitate some XHR
      setTimeout(function() {
          $('#page-content').text('This is page ' + i);
      }, 200);
  }
  
  // load contents of current page based on hash
  function refreshByHash() {
      var hash = window.location.hash;
      _uiPage(hash ? +hash.substring(1) : 1);
  }
  
  // refresh on hash change
  $(window).on('hashchange', refreshByHash);
  // initial state on page load
  refreshByHash();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="pages"></div>
<div id="page-content"></div>

Note: Chrome's back button will go back in the active iframe, so after you clicked on some of the pages, you can press the back button to test the behaviour, and the outer frame, StackOverflow itself will not change.

Also take a look at thoe question: How to manage browser “back” and “forward” buttons when creating a javascript widget


Edit1

$(function() {
  $(window).on('hashchange', refreshByHash);
  refreshByHash();

  function refreshByHash() {              
    var hash = window.location.hash; 
    // ----- strip the hashmark here -----
    hash = hash ? hash.substring(1) : '';
    console.log("hash = " + hash);

    $.ajax({
      url : 'paginator.action?page=' + hash, // action
      type : 'GET', //type of posting the data
      dataType : 'html',
      async: true,
      success : function(htmlData) {
        $('#paginator').html(htmlData);
      },
      error : function(xhr, ajaxOptions, thrownError) {
        alert('An error occurred! ' + thrownError);
      },
    });
  }
});
Community
  • 1
  • 1
Tamas Hegedus
  • 28,755
  • 12
  • 63
  • 97
  • I tried to implement your solution into my code but faceted with two problems. See update 1 code script. --------------------------- 1) Unable to get ajax request from where it is comented. How to pass into ajax code the `hash value`?--------------------------- 2)That ajax request must be executed only and only if browser buttons were presed but all that code runs every time I press the links or when browser buttons were presed. – rozero Jan 09 '16 at 21:02
  • @rozero I don't really understand how do you show a page after a page number was pressed, without an ajax request. If you can show them the first time, you can show them without ajax the next time too, when the browser buttons get pressed. – Tamas Hegedus Jan 09 '16 at 21:08
  • I have another script in `pagin_scripts.js` you could try to check the `temp link`. That script was loaded by script loader. And from that code I manage the content to be updated by ajax by pressing page numbers. But the code from update 1part is intedted to manage the brouser back button for example. I understand it so. – rozero Jan 09 '16 at 21:15
  • @rozero You have three functions in there that does esentially the same. I still don't see why the first load would be different than the others. – Tamas Hegedus Jan 09 '16 at 22:27
0

When user clicks on #idPage (btw, use classes instead, now you have multiple elements with the same ID and that's not good) since href attribute is empty, the browser will load # (and will go to the top of the page).

You should prevent default behavior when user clicks on links, e.g.

$('body').on('click', '#idPage', function(e) {
   // some code goes here
   e.preventDefault();
});

Hashtag (#) has effect on back/forward button. If you append hashtag and click "back", the browser will return you to the state before hashtag was applied.

Community
  • 1
  • 1
Kristian Vitozev
  • 5,791
  • 6
  • 36
  • 56
  • What do you mean by `If you append hashtag`? If now href contains `#` then how to change it? Like `#someValue` ? Can I put the line `e.preventDefault();` just after `$('body').on('click', '#idPage', function(e) {` ? By the way is `e` refer to `element`? – rozero Jan 09 '16 at 13:40
  • You should put that line just before closing `});`. And no, `e` means event. – Kristian Vitozev Jan 09 '16 at 14:24
  • I have changed the script as you said and now the browser `back button` is unavailable after first `back` click.... You could check it by temp link. Also I've changed `div` to `class` in page links. – rozero Jan 09 '16 at 14:39
  • Also there is an error: `Uncaught ReferenceError: e is not defined(anonymous function) @ pagin_scripts.js:21x.event.dispatch @ jquery-1.10.2.min.js:5v.handle @ jquery-1.10.2.min.js:5` – rozero Jan 09 '16 at 14:48
  • The link is not available. – Kristian Vitozev Jan 09 '16 at 17:27
  • you could try it now (it is a temp link and not always available) – rozero Jan 09 '16 at 17:36
  • Your event handler function should accept event object, i.e. change `$('body').on('click', '#idPage', function()` to `$('body').on('click', '#idPage', function(e)` – Kristian Vitozev Jan 09 '16 at 17:59