bookiza / bookiza.js

A fun library (polyfill) to paginate and print responsive books on the web.
http://bookiza.io
Other
16 stars 5 forks source link

Impossible to handle page turn events #10

Open martinhbramwell opened 3 years ago

martinhbramwell commented 3 years ago

I have place the following JS code on each page, from the cover page through to page 13, with incrementing numbers for each respective page:

window.addEventListener('load', (event) => {
  console.log('Page 1 loaded');
});

window.addEventListener('pagehide', (event) => {
  console.log('Page 1 gone');
});

If I click on Edit Draft of my book, the Cover page opens and the browser console shows:

Page 3 loaded
Page 5 loaded
Page 6 loaded
Page 2 loaded
Page 4 loaded
Page 1 loaded

When I turn to pgs 2 & 3, the console shows:

Page 2 loaded

to pgs 4 & 5

Page 7 loaded
Page 1 gone
Page 4 loaded

to pgs 6 & 7

Page 8 loaded
Page 2 gone
Page 3 gone
Page 6 loaded
Page 9 loaded

to pgs 8 & 9

Page 11 loaded
Page 4 gone
Page 5 gone
Page 10 loaded
Page 8 loaded

to pgs 10 & 11

Page 13 loaded
Page 12 loaded
Page 6 gone
Page 7 gone
Page 10 loaded

Question: How can my JS code know that it's page is open so that it can run and closed so that it should stop?

martinhbramwell commented 3 years ago

I also tried using IntersectionObserver on page 2 and on page 4

  <!-- Draggable DIV -->
  <div id="draggable2">
    <div id="mydivheader"/>
    <button class="button">Go</button>
  </div> 
var observer = new IntersectionObserver(function(entries) {
    if(entries[0].isIntersecting === true) {
        console.log('Page 2 is visible');
  } else {
        console.log('Page 2 is not visible');
  }
}, { threshold: [1] });

observer.observe(document.querySelector("#draggable2"));

... and ...

  <div id="draggable4">
    <div id="mydivheader"/>
    <button class="button">Go</button>
  </div> 
var observer = new IntersectionObserver(function(entries) {
    if(entries[0].isIntersecting === true) {
        console.log('Page 4 is visible');
  } else {
        console.log('Page 4 is not visible');
  }
}, { threshold: [1] });

observer.observe(document.querySelector("#draggable4"));

When opening to page 1, I see in the console:

Page 2 is not visible
Page 4 is not visible

Turning to page 2, 3:

Page 2 is visible
Page 2 is not visible
Page 2 is not visible

Turning to page 4,5:

Page 4 is visible
Page 4 is not visible
Page 4 is not visible
Page 2 is visible
marvindanig commented 3 years ago

Intersection observer wouldn’t be able to keep track of the incoming or outgoing pages on the DOM. That’s useful only when the elements are scrolling and begin to intersect with the viewport when they appear above the fold.

In case of a Superbook all the pages and their sub-resources always live (and die) above the fold. So it’s always intersecting per se.

What is it that you want to do inside of a page? Does DOMContentLoaded not suffice?

martinhbramwell commented 3 years ago

Does DOMContentLoaded not suffice?

No.

I placed code like this on pages 2 through 7 of a newly created 8 page book

window.addEventListener('DOMContentLoaded', (event) => {
  console.log('Page 5 loaded');
});

When initially opening the book all six handlers fire.

When stepping forward through the book only the even numbered pages fire, except that the second to last page also fires when turning to the 4th page.

When stepping backward through the book only the odd numbered pages fire, except that the second page also fires when turning to the 5th page.

What I really need is two custom events available to both exposed pages: PageTurningBegun and PageTurningComplete.

The events should carry a detail object like this :

{
  "details":
  {
    "leftPageTitle": "The cabbage patch",
    "rightPageTitle": "The farmer"
  }
}

or some other mechanism that ensures script on each page can determine whether or not the event is pertinent, that will be unaffected by deletion or insertion of other pages.

marvindanig commented 3 years ago

How can my JS code know that its page is open so that it can run and closed so that it should stop?

The instance of bookiza.js on Bubblin will render a maximum of only six pages on the DOM at any given time. This is in landscape mode. In portrait mode, it manages with just five pages on screen.

Your page-level javascript will execute as soon as a subsequent page frame is attached into the DOM and it reifies successfully. Even when the reader cannot view the newly added pages because they are under the currentView.

What exact moment are you wanting to have the page-level custom-events fired? When the page under the current one becomes visible to the reader? if yes, then what would define differentiation between a peel-to-peek action vs. actual turn over to the left?

What are your thoughts?

martinhbramwell commented 3 years ago

My intention was to start playing a media file through an HTML5 <video> or <audio> control as soon as a user releases a turning page and to pause it as soon as they initiate a new page turn.

marvindanig commented 3 years ago

Oh you mean autoplaying the video? I am not sure you wanna do that but I'll consider this requirement in the next build of Bookiza / Bubblin. I have used an <audio> embed on an experimental greeting card before: https://bubblin.io/book/i-love-you-by-marvin-danig/1 that autoplays, but you probably want the switch to be tied to the turned event of the incoming view.

If such an event was available, how would you have handled firing the video/audio between portrait and landscape modes? The former shows only one page on a mobile whereas the latter will display two pages on the desktop simultaneously.

Merry Christmas.

martinhbramwell commented 3 years ago

"how would you have handled firing the video/audio between portrait and landscape modes? "

Yeah, that's a complication. Would there be a way to have a global media controller that mediates the state of every page and every media element?

marvindanig commented 3 years ago

Yes. Any javascript that you put inside the Layout Templates section of the book will be available on all the pages. How this javascript ties-up events within the context of a page or above at the spine_url level after being reified on the DOM (or not) is left entirely to the author. Exposing the state of every page on the book sounds like an interesting proposition, but it also assumes that the entire tome is available in memory at all times.

martinhbramwell commented 3 years ago

Are there events when pages are added/removed, unambiguously, from the DOM?

marvindanig commented 3 years ago

Cue MutationObserver!

No, events for the addition and removal of pages from the DOM aren't covered on the existing API of bookiza.js. While this discussion is really helpful in finding this type of requirement, I also feel that writing an observer to watch for DOM level changes on the spine_url isn't going to be a part of this polyfill's scope. I am undecided at this point.