Houcem Berrayana
Houcem Berrayana

Reputation: 3080

Backbone and jqm: back button how to restore page context

I'm building an HTML5 mobile application using Backbone, require and jQuery mobile as a technology stack. The application is really smoothy with a connection to a backend web service and so on. To Change between the pages I use jQuery changePage. To instanciate Backbone views I use the following strategy:

$( document ).delegate("#card-delivery-address", "pageshow", function(){
    require(["js/views/cardDeliveryAddressViews.js" ], function(cardDeliveryAddressViews) {
        new cardDeliveryAddressViews();
    });
});
  1. $.mobile.changePage('deliveryAddress.html') => changes the current page using jquery mobile

  2. When an event called "pageshow" is fired on #card-delivery-address (which means that my page was inserted in the DOM and successfully rendered) => create the backbone view and bind the $el to an existing DOM and taking control on the DOM events using backbone views.

  3. To pass data and instances between views we use a window.tempData global variable in which we put the context data so that the new view will know what to do.

Doing one way navigation is successful, suppose that I come from view1 --> view2 (with tempData) then from view2 --> view 3 (override the same tempData). Now, and here is my problem: if we want to go back from view 3 --> view 2 we will need the tmpData content that we used to initialize and render the view 2. The same thing when we want to go back to view1.

Note: I'm not using backbone router but I can change to use it if that will solve my problem.

Any ideas guys?

Upvotes: 4

Views: 1182

Answers (5)

thibauts
thibauts

Reputation: 1648

Ok let's give it another try. We'll implement a data store keyed by pages' path.

var pagesData = {};

// Let's assume we just switched to page '/my/page/1'

// Get a reference to the stored page data if it exists, 
// or create it empty and return it.
var currentPageData = pagesData[window.location.pathname] ||  
                     (pagesData[window.location.pathname] = {});

currentPageData.foo = 'bar';

console.log(pagesData['/my/page/1'].foo); // > "bar"

Now all your pages have a "local" datastore that allows them to save their state/data throughout navigation.

NB: If you don't use pushState, you have to use window.location.hash in place of window.location.pathname as a key in PagesData.

Upvotes: 2

thibauts
thibauts

Reputation: 1648

Using a stack may solve your problem. The internal history handling of your browser uses that to handle navigation and the back button.

Stacks are implemented in Javascript using an Array and its push() and pop() methods. They allow you to save and restore a previous state.

var navigationStack = {...},
    currentState = {...};

...
// When going to a new page, you push (or save) the current state on the stack
navigationStack.push(currentState);
...

...
// When going back to the previous page you pop the previous state from the stack
currentState = navigationStack.pop();
...

Of course, this works if your navigation from view3 to view2 if akin to a "back" action. If it is a deliberate navigation to any page that may have been previously initialized, you are bound to save your pages' states in a hash, indexed by page name (or full route).

Your case should fit one of these two models. If it doesn't, either your requirements are not well defined enought, or I misunderstood your question.

Upvotes: 1

Mohit
Mohit

Reputation: 2249

thibauts' answer seems in the right direction. Do give that a read.

The way I understand your problem. at any time opening a "page3a" depends on the previous page. if it was "page2a" it will work in a certain way. if it was "page2b" it will work differently. And this information you keep in tempData for every page.

This problem will not be solved by backbone routes. As they just provides means of converting URL routes into a execution sequence. You will still have to manage tempData. Solution in the end depends on the size of tempData and how you manage it. Is there some shared data which can be taken out of tempData structure and kept in a shared structure. Is there some data which can be kept on its own, changes very rarely and can implements some kind of memento pattern.

there are three cases -

  1. tempData is relatively small and you can keep some copies of it - in this case you can keep fixed history [say last 10 pages] of tempData in a circular buffer. Keep on deleting oldest items and adding new one at every page visit. This will give you both back navigation as thibauts said and history jump along with forward navigation after back Navigation if the user haven't changed anything and specifically try forward button/nav.

    1.1 EDIT : In case you wish to retain a forward action which has already been backed, you can still keep it in the circular queue, but this way you have to distinguish between the two visits of view2 (see comments). and consider everything as a forward move and push in history (circular queue). another way will be to keep a pointer (array index. reference if you may) to the current page in the buffer and when adding the new page (on some action) to buffer move the pointer the that one. when doing a back/forward moves just move the point in buffer and render. [If it is too complex or costly to implement, you can completely ignore a view/page once user has moved back from it. simply remove it from history so user cant use fwd again. or back twice to reach it after back-new-back-back. backbone.router has a way of history replace]

  2. tempData is large enough that you can keep only few copies of it [lets assume less than 5]. In this case keep one copy for the previous page. and keep copies of specific key pages in history where there's high chance of user returning. for example in a shopping flow, the user may return back to cart more often than the address page. You will need a special data structure for this, where you can maintain priority of every page. priority is based on the time and some biasing criteria. the newest gets high time parameter and the most important gets high biasing parameter. whenever you visit a new page. remove the tempData of the lowest priority.

  3. tempData is of monstrous size - give up on the back navigation. keep few points in history which works like reset points (if possible) and where you can recreate the tempData from scratch.

If there's any other bottle neck than the tempData. Please comment.

Upvotes: 1

frequent
frequent

Reputation: 28513

Why not make windows.tempData an object?

windows.tempData = {};

To store a page data:

window.tempData["id_of_page"] = your_data;

On pagebeforeshow:

myDataForThisPage = window.tempData[this.id];  // assuming "this" being your page element

Upvotes: 1

Slim Tekaya
Slim Tekaya

Reputation: 347

During the page transition previous page is going to be removed from the DOM

To keep all previously-visited pages in the DOM you can add the attribute:

<div data-role="page" id="card-delivery-address" data-dom-cache="true">              
    <!-- [...] -->      
</div>

or by initializing global parameter:

$.mobile.page.prototype.options.domCache = true;

Upvotes: 2

Related Questions