Skip to content

Making pages dynamically with Ajax

blasten edited this page Jul 4, 2012 · 17 revisions

The first release of turn.js introduced a pretty simple way for adding new pages. In fact, the only thing you had to do was to add as many elements as pages you needed for your book or magazine. Quickly, this scheme brought up a problem in cases where the book contained a large amount of pages. The solution was to provide a way for creating pages on the fly. Therefore, the 3rd release of turn.js allows you to create pages dynamically.The API is also simple and consistent with the way you are familiar for setting event listeners. This new feature is the foundation in which any kind of e-reader app will be achievable.

In order to create pages dynamically, turn.js includes the ability to set an arbitrary number of pages during runtime.

It also comes with an internal garbage collection system that removes objects from memory that are not longer necessary for the reader. Therefore, turn.js is now keeping in DOM and references for only 6 pages. Let’s take an example:

If our reader is currently in the page 6, the view for that page will be 6,7. From 6-7, turn.js wants to keep in memory 4 more pages. Therefore, our DOM and JavaScript cache will have the pages [4, 5, 6, 7, 8, 9]. For instance, if our reader is in page 1, the pages to keep in DOM are [1, 2, 3, 4, 5, 6].

In context, these pages in DOM are called range. That is, our range will be an array of two values where the first one is the first page and the second one the last page.

Let’s code

We are going to use the sample called ‘bible’, which comes with turn.js

Firstly, we create a book with 1000 pages.

$('#book').turn({pages: 1000});

We can also call the method pages in order to set the amount of pages. Notice the difference between pages and the other event called page.

$('#book').turn(‘pages’, 1000);

Secondly, to create pages dynamically, we have to add a listener to the ‘turning’ event and there we want to read the range of pages that the reader will need. We also need a loop to inspect every page independently and for each page ask if that page is already in the reader, if not we need to add that page.

$('#book').bind('turning', function(e, page) {
  var range = $(this).turn('range', page);
  for (page = range[0]; page<=range[1]; page++)
    addPage(page, $(this));
});

Then define the addPage function:

function addPage(page, book) {
   // Check if the page is not in the book
  if (!book.turn('hasPage', page)) {
    // Create an element for this page
    var element = $('<div />').html('Loading…');
    // Add the page
    book.turn('addPage', element, page);
    // Get the data for this page	
    $.ajax({url: "app?method=get-page-content&page="+page)
     .done(function(data) {
       element.html(data);
     });
   }
}

As you see, it is pretty simple and flexible for any implementation. For example, if you are loading data from the server with XHR, you can consider just one request per range.

What is going on the memory

In order to inspect the data in memory, you can explore $('#book').data()

Clone this wiki locally