1

I am writing a document reading application using Node-Webkit. A document can be hundreds of pages long and the interface allows opening the document to a specific chapter. Once the initial chapter is displayed, I want to load the rest of the book asynchronously. Since I don't know what direction the reader will scroll, my strategy is to alternately load chapters before and then after the initial chapter:

load chapter x -> load chapter x-1 -> load chapter x+1 -> load x-2 -> load x+2 ...

I am displaying the book in a containing div element with each chapter being a div within the container. I'm using jquery .before() and .after() to insert each chapter as it is fetched.

My problem is that the browser automatically scrolls up when I add chapters earlier in the book. So if I start with chapter 10, the browser scrolls up when I add chapter 9 and again with chapter 8 and so forth.

One (unsatisfactory) solution to the problem is to make an anchor tag for each chapter and store the id of the first chapter loaded. Then after each chapter is fetched, runing the code:

window.location.href = #originalChapter

keeps the initial chapter in the browser viewport. Of course the problem with that is that the reader cannot scroll while the rest of the book is being loaded.

Ideally, I would like to disable scrolling, load a chapter and then re-enable until the next chapter is fetched. I'm so far unable to figure out how to do that.

Wex
  • 14,875
  • 10
  • 56
  • 99
Jon
  • 683
  • 3
  • 15
  • 34
  • Please have a look at this [SO question](http://stackoverflow.com/questions/4770025/how-to-disable-scrolling-temporarily). I think the answer from Zougen Moriver is working. It implements a scroll stop. – AWolf Dec 19 '14 at 22:32
  • Thanks, but that seems only to handle user interface initiated scroll events - mouse, arrow keys, etc. The DOM changes that cause scrolling in my case are fired ascynchronosly once the initial chapter is loaded. What I want to do is keep the UI responsive while chapters are loaded in the background. – Jon Dec 19 '14 at 22:56
  • So it's really the only `prepend` operation that you need to solve for. – Wex Dec 19 '14 at 23:13
  • That's correct - the window doesn't scroll on .after. I'll try your solution later today. Thank you. – Jon Dec 21 '14 at 17:05
  • 1
    http://stackoverflow.com/users/522877/wex answer almost worked for me and it did put me on track. The difference is that scrollTop() didn't work for the buffer container. jquery.position() does the trick. So: $container.scrollTop(buffNewHight - buffOldHigh - $buff.position().top); – Jon Dec 24 '14 at 20:54

2 Answers2

2

The simple solution in my mind would be to not have the elements in the DOM until they are loaded. The user won't be able to scroll because there won't be content to scroll to. Then, it's just a matter of preserving the viewport when the elements are added.

Take the initial position of your scroll container and the height of the overflow container:

var scrollTop = $scroll.scrollTop(),
    height    = $container.height();

and use them to preserve the viewport when you prepend new elements. You don't have to do anything when you're doing the append operation.

var newHeight    = $container.height(),
    newScrollTop = scrollTop + newHeight - height;
$scroll.scrollTop(newScrollTop);

Here's a quick example: http://jsfiddle.net/Wexcode/tfszaocz/

Wex
  • 14,875
  • 10
  • 56
  • 99
2

If you're updating the DOM from the click handler of an anchor (<a/>) tag, make sure you return false from the callback function.

Amarghosh
  • 55,378
  • 11
  • 87
  • 119