johnfactotum / foliate

Read e-books in style
https://johnfactotum.github.io/foliate/
GNU General Public License v3.0
5.93k stars 273 forks source link

Foliate doesn't support some javascript "elemental" properties #1143

Closed RbnJrg closed 9 months ago

RbnJrg commented 9 months ago

I am an epubs developer and I'm currently writing a script that makes use of "document.documentElement.clientHeight"; Since Foliate doesn't seem to support it (it returns 0), I tried using "window.innerHeight" and "VisualViewport.height" (also without success because in both cases it returns 0). So it is impossible to know the interior height of the Foliate window by means of javascript.

I'm using Foliate 2.6.4 from Arch Linux oficial repo (Arch Linux 6.1.62-1-lts).

johnfactotum commented 9 months ago
RbnJrg commented 9 months ago
  • As of Foliate 3.0, it does not support JavaScript anymore. This might change in the future but it's not a priority.

OK.

* When are you getting those properties? I'm not aware of anything that would make those properties not work except that you might need to wait until the page is layouted on screen.

Of course, the script starts working only after the the page has been totally load. In fact, "document.body.clientHeight" works, "document.body.scrollHeight" works, "document.documentElement.scrollHeight" works, but I only receive 0 when I use the properties named in my previous post.

* Why are you trying to get those properties? Generally, getting the window height is not really useful because the concept simply does not work well with pagination. 

Yes, I am aware of that. But I needed to know the innerHeight of the Foliate window :-) It's not easy to explain here how the script works but in a few words, according to the position of the last paragraph of text (in a chapter) regarding the app window, inserts (or does not) a fleuron, so there is not a large blank space at the end of a chapter. The script works fine in others ereaders (for example Thorium, Koodo Reader, all ereaders based on the Readium engine, etc.) Yours is a very good ereader (one of the best I tested) and I wanted to see how the script worked there.

See e.g. the following note from the spec (emphasis mine):

  > Reading system-induced pagination can interact poorly with style sheets as reading systems sometimes paginate using columns. **This may result in incorrect values for viewport sizes.** Fixed and absolute positioning are particularly problematic.
  And
  > Reading systems may render scripted content documents in a manner that disables other EPUB capabilities and/or provides a different rendering and user experience (e.g., by disabling pagination).

That's right. But practically in all ereader with plenty support for epub3 I tested (for Windows, Linux, Android) doesn't show any issue with pagination. HOWEVER, in Bibi Reader, sometimes the script generates a blank page at the end of the chapter. The script reacts to changes in font-size and window resize, and because of that, it can happen -after the change (for example) in the font-size- that some fleurons are "deleted". And in those cases (not always) a blank page can be generated. To "delete" the fleuron (in fact, there is none deletion), the script applies the css property "display: none" to the paragraph with the fleuron image, and for a reason I can't understand yet. the fleuron is not displayed, but still ocuppies place (is like if instead of applying "display: none" I had applied "vissibility: hidden"). I tried by removing the paragraph (a real deletion) but evem so blank pages can be generated. Probably a bug in Bibi, because after the "deletion" of a fleuron, the value of "documen.body.clientHeight" is updated but "document.documentElement.scrollHeight" doesn't.

Anyway, many thanks for answering my question.

johnfactotum commented 9 months ago

Of course, the script starts working only after the the page has been totally load.

If you're using window's load event or something similar, that might not be enough. The most reliable way to check for resizes would probably be to use a resize observer on the body, which is what Foliate uses internally to observe the page for resizes.

In v3.0 at least, foliate-js doesn't start rendering the page after it's been loaded. Initially the whole iframe is set to display: none, at which point innerHeight would be 0. That's the only reason I can think of that could cause the value to be 0.

For v2.x, I'm not entirely sure how Epub.js works in this regard, but presumably it would be a similar problem.

In fact, "document.body.clientHeight" works, "document.body.scrollHeight" works, "document.documentElement.scrollHeight" works, but I only receive 0 when I use the properties named in my previous post.

Using WebKit's Inspector, getting window.innerHeight etc. works as expected for me in the console when the context is set to the iframe.

Probably a bug in Bibi, because after the "deletion" of a fleuron, the value of "documen.body.clientHeight" is updated but "document.documentElement.scrollHeight" doesn't.

Updating the size of the page can be tricky for reading systems. Prior to resize observers, I think the only way was polling. And then there is a Firefox bug where resize observers are broken in multicolumn: https://bugzilla.mozilla.org/show_bug.cgi?id=1832939

RbnJrg commented 9 months ago

Of course, the script starts working only after the the page has been totally load.

If you're using window's load event or something similar, that might not be enough. The most reliable way to check for resizes would probably be to use a resize observer on the body, which is what Foliate uses internally to observe the page for resizes.

I have the script at the end of every .xhtml page of an epub, something like:

 ....
 ....
<script type="text/javascript" src="../Misc/Detector.js"></script>

</body> </html>

And in the script, I had at the starting:

window.addEventListener("load", Detector);

That worked for every app I had tested so far. But I decided to follow your tip, and I added at the starting (of the script): window.addEventListener("resize", Detector);

(internally, to detect changes in font-size and resizing, the script employs "ResizeObserver ") and Foliate recognized "window.innerHeight" !!! :-) And also the script works beautifully in your program, no issue at all! A real pity that with Foliate 3.0 JS is not more available.

Probably a bug in Bibi, because after the "deletion" of a fleuron, the value of "documen.body.clientHeight" is updated but "document.documentElement.scrollHeight" doesn't.

Updating the size of the page can be tricky for reading systems. Prior to resize observers, I think the only way was polling. And then there is a Firefox bug where resize observers are broken in multicolumn: https://bugzilla.mozilla.org/show_bug.cgi?id=1832939

Maybe can be that bug. So far I couldn't find a workaround to suppress those generates blank pages. Many thanks for your help John; to me the report of this "bug" can be considered as solved and closed; thanks again!

johnfactotum commented 9 months ago

Thanks. The main problem with JavaScript support is that it needs to use a separate origin for each book, which I'm not sure how to do. Maybe it's as simple as setting the base URI to something different for each book, though I'm not sure how it's going to work with custom URI schemes. But I'll look into it.

Another thing is that currently it cannot sandbox the iframe properly due to a WebKit bug: https://bugs.webkit.org/show_bug.cgi?id=218086. I think perhaps one can work around this by wrapping it in one additional layer of iframe, and then set it to a different origin somehow.