3

I have single page application. All data is retrieved by ajax and rendered on client. I have the next workflow:

  1. User opens list of items. List has infinity scroll
  2. User scrolls and clicks on item
  3. System makes ajax request, generates new html and replaces previous content
  4. User clicks on browser's back button
  5. System changes url (historyjs) and router loads items and renders list. But the position of scroll is LOST ! So user needs to scroll to go to the previous position on the list.

How to preserve this position during back / next actions and implement generic solution for all project ?

Oleg Dats
  • 3,933
  • 9
  • 38
  • 61

4 Answers4

1

Going back on Browser button returns you to a "Cached" page more often then not. If not cached, then it will re-render the page. Obviously given the nature of HTTP state is lost. My suggestion would be to store the number of the item in the list, or the items value in "Session" variable or "Cache" object and access it from there before Page Load.

If the Session["lastSelectedItem"] != null, then get the value/number, and use jQuery or whatever to set the "Selector" on the right place.

Dane Balia
  • 5,271
  • 5
  • 32
  • 57
  • good, you have a position. But the issue is how to understand is it BACK or normal opening the page. It becomes very tricky if you have more then one list and links from one item to another. – Oleg Dats Jul 19 '12 at 12:44
1

Just add to list id and scroll to this id

<div id="item_1002">content of 1002</div>
<div id="item_1003">content of 1003</div>
<div id="item_1004">
    <span>content of 1004</span>
    <a href="#item_1002">goto 1002</a>
</div>

this will work even wo js :)

User click on link, go to post with id (if it avaliable on current page) and have location like http://site.com/#item_1002. And when user click back browser change url to http://site.com/#item_1004 and scroll to <div id="item_1004">...


EDIT

I'm sure this not work but just as concept its better than my bad English

<script type="text/javascript">
    // scroll to id
    // http://stackoverflow.com/questions/68165/javascript-to-scroll-long-page-to-div

    // need to use this
    // History.Adapter.bind(element,event,callback);
    // but I'm stuck how it works
    // so jQ
    $(document).ready(function(){
        $('a').click(function(){
            // document.getElementById('youridhere').scrollIntoView();
            $(this).scrollIntoView();
            History.pushState({}, 'title', '#item_ID');
        })


        // Bind to StateChange Event
        // Note: We are using statechange instead of popstate
        History.Adapter.bind(window,'statechange',function(){
            // Note: We are using History.getState() instead of event.state
            var State = History.getState();

            $(State.url).scrollIntoView();
        });
    })



</script>

<div id="item_1002">content of 1002</div>
<div id="item_1003">content of 1003</div>
<div id="item_1004">
    <span>content of 1004</span>
    <a href="javascript:">goto 1002</a>
</div>
b1_
  • 2,069
  • 1
  • 27
  • 39
  • there is infinity scroll so some items will not be loaded so it's not possible to scroll to them. But it's not the main problem. The issue is how to pass id when you click back – Oleg Dats Jul 19 '12 at 12:10
  • On 2 position change location to `http://site.com/#item_ID` and my idea will work. – b1_ Jul 19 '12 at 12:17
  • Base url should be always be base url `http://site.com/` Sharing such url is much more easy – Oleg Dats Jul 19 '12 at 12:22
  • Hmmm. But how with this rule user can share link to current item? I think if site ajax based it must use hash based navigation but its you site :) – b1_ Jul 19 '12 at 12:33
  • yes, it uses. But there is default url '/' to the list and '/u/{id}' to item – Oleg Dats Jul 19 '12 at 12:39
  • in this example you pass "#item_ID" when you click on link. But how will you pass "#item_ID" when you click on browser's back / next buttons ? – Oleg Dats Jul 19 '12 at 14:46
  • @OlegDats lets talk about details in chat tomorrow. Near 11.00 CET – b1_ Jul 19 '12 at 17:47
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/14172/discussion-between-b1-and-oleg-dats) – b1_ Jul 20 '12 at 10:16
  • It's at the bottom of this topic. "You can accept your own answer in 24 hours" ) – Oleg Dats Jul 20 '12 at 14:16
1

Here is my solution (coffeescript):

class window.Explore
  cached_pages = {}

  preserve: (url)=>
    current_position = window.pageYOffset || document.documentElement.scollTop || 0

    cached_pages[url] = 
      position: current_position

  clean: =>
    cached_pages = {}

  scroll_back: (url)=>    
    if cached_pages[url]
      $('body').scrollTop cached_pages[url].position


window.cached_explore = new Explore()

window.prev_state = undefined
window.current_state = undefined

$ ->
  History = window.History
  if !History.enabled
    return false

  History.Adapter.bind window, "statechange", =>
      # store previous history state
      window.prev_state = window.current_state
      window.current_state = History.getState()
      # preserve each page position before leaving
      if window.prev_state and window.prev_state.hash
        window.cached_explore.preserve(window.prev_state.hash)    

      place_match = location.pathname.match(/\/place\/(.*)/)    

      # place page
      if place_match
        # retrieve place      
        window.retrieve_place place_match[1], window.search_query, (err, place_dto) ->        
          # render place page
          window.show_place_popup place_dto        

      # explore places page
      else if location.pathname is '' or location.pathname is '/'
        # check if a page was already opened
        window.renred_explore_page()

        if window.prev_state
          window.cached_explore.scroll_back location.pathname
Oleg Dats
  • 3,933
  • 9
  • 38
  • 61
0

If you don't want to or not be able to use a session, try to use the History.replaceState() .

If the user loads new list items in your infinity scroll, replace the history state History.replaceState() and append the item count or the last item ID.

If the user clicks the back button, evaluate the item count, load the list and scroll down.

Sascha
  • 937
  • 6
  • 14