0

I am currently working on a book with page turn effect in jQuery (no plugin). The page turn effect works fine so far, as long as you click through the pages one by one. But now I want to include a dropdown selection (i.e. a select element) so the user can directly jump to the selected content. I tried to make this work with loops and with the .each() method, so that the turnRightPage/ turnLeftPage function is called repeatedly, until the page with the selected content is shown. But after quite a bit of trial and error and a lot of research, I think loops iterate too fast for my turnRightPage /turnLeftPage()-function (which are the transform functions that turn the respective page), in that the loop is done, before the function has completed. I think, what I need to do, is find a way to pause the loop until the function has finished executing and then resume with the next iteration. I think the most promising approach would be using a function with an iteration counter, like it was suggested here: Javascript: wait for function in loop to finish executing before next iteration (Thanks to jfriend00 at this point) I have also read Invoking a jQuery function after .each() has completed and wait for each jQuery among others, where similar solutions were suggested.

Below is how I tried to implement jfriend00's callback. I added a return statement to break out of that "callback loop", once the number of page turns is completed.

//determine whether to flip pages forward or back - first forward 
if(currentPagePos < foundPagePos){  // => turn right page
      //determine how many times need to turn page
      if (pageDifference > 1 && pageDifference % 2 !=0) {
          var numPageTurns = (pageDifference-1)/2;
          pageForward (numPageTurns);
      } //else if ... rest omitted for brevity
}    

function pageForward (numPageTurns){
      var i = 0;
      function next(){
          i++;
          if (i <= numPageTurns){
            turnRightPage ();
          } else {
              return;
          }
      }
      next();
  };  

The full code can be seen here: http://jsfiddle.net/snshjyxr/1/

It DOES turn the page, but only once! What am I missing?

I am still very new to javascript / jQuery so my apologies, if the problem seems all too obvious. Any pointers appreciated. Thx!

Community
  • 1
  • 1
marcor
  • 3
  • 1

1 Answers1

1

The thing is all the page turns are fired, but all at once. You have to wait until each transition is finished to start the next one.

Use a callback function in your turnRightPage and turnLeftPage functions. Example for turnRightPage :

function turnRightPage(callback) {

    [...]

    //change class AFTER transition (frm. treehouse-site)
    $page.on('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function () {
        //need to double-set z-index or else secondtime turning page open setting z-index does not work (tried in Chrome 38.0.2125.111 m)
        $page.css("z-index", turnedZindex + 1);
        $(".turned").removeClass("turned");
        $page.addClass("turned");

        if(typeof callback == "function") {
            callback();
        }
    });
};

And in your pageForward function, use turnRightPage recursively:

function pageForward(numPageTurns) {
    console.log("number of FORWARD page turns: " + numPageTurns);

    if(numPageTurns > 0) {
        turnRightPage(function(){
            pageForward(numPageTurns - 1);
        });
    }
};

Here is your updated jsfiddle. As you can see, there's a remaining bug when you make several page changes which is caused by the fact that you're adding listeners on the transition end every time a page is turned, and never removing them. So they're all executing every time.

EDIT: jsfiddle updated again without the annoying last bug. As you can see, all it took was to unbind the event listener as soon as it's fired.

Antoine Combes
  • 1,444
  • 8
  • 13
  • Great! Thank you so much, Antoine. Although I have to admit, I am still struggling to understand how the callback function here works. What exactly does the if(typeof callback == "function") { callback.call(); } -bit do here? – marcor Nov 05 '14 at 13:08
  • the `if` part just checks if the variable `callback` is indeed a function, so that we don't try to call a common variable (which would just throw an error). The `callback.call()` just calls the function contained in the `callback` variable. Now that i think of this, `callback()` would do the trick just as fine. I'll edit my answer. – Antoine Combes Nov 05 '14 at 15:23
  • Just remember that the `.call()` method can be handy when you want to pass a specific context to the function you call (i.e: if you want/need `this` to be something else than `window` inside your function) – Antoine Combes Nov 05 '14 at 15:27
  • Thanks a lot, it's a bit clearer now. I really appreciate your effort. But why doesn't turnRightPage keep endlessly repeating itself? The condition (typeof callback == "function")in the if statement here will always be true, so the callback will be called every time at the end of turnRightPage. In my noob-mind, just looking at the code, I would have expected it to run on forever, once you flip a page. – marcor Nov 06 '14 at 00:17
  • `typeof callback == "function"` is checked only once, the `transitionend` events are only fired once on a single page. The work is done inside the `pageForward` function, used recursively. That means it will call itself until it's not needed anymore. Here the obvious condition to stop the function calling itself, is when we have no more page to turn, which is why each time the function calls itself, it does so by decrementing the number of page to turn. So in the end the function is called with 0 page to turn. That's where the check `numPageTurns > 0` forbids to call the function any further. – Antoine Combes Nov 06 '14 at 01:58
  • If you're not familiar with recursive programming, you should look it up, it's always nice to have this method in mind. http://en.wikipedia.org/wiki/Recursion_(computer_science) – Antoine Combes Nov 06 '14 at 02:01
  • OK, I think I get it now. Thanks for taking the time to explain. – marcor Nov 07 '14 at 10:12