TiddlyWiki / TiddlyWiki5

A self-contained JavaScript wiki for the browser, Node.js, AWS Lambda etc.
https://tiddlywiki.com/
Other
7.98k stars 1.18k forks source link

[Print Tiddler Button] print dialogue fires too early #3268

Closed BurningTreeC closed 5 years ago

BurningTreeC commented 6 years ago

To replicate: print a tiddler with some heavier content that doesn't render instantly (more images, something that takes a bit to load) when the new window opens. The print dialogue doesn't show the content then. Closing the dialogue causes the window to finish rendering and afterwards one can print the content

sukima commented 6 years ago

Not sure how to fix this but to reproduce this in development you can use this Node script:

const fs = require('fs');
const http = require('http');
const TEST_IMAGE = "./editions/tw5.com/tiddlers/images/Blurry Lawn.jpg";

let server = http.createServer(function(req, res) {
  setTimeout(function() {
    res.writeHead(200, {
      "Pragma": "no-cache",
      "Cache-Control": "no-store, no-cache, must-revalidate, max-age=0; post-check=0, pre-check=0",
      "Content-Type": "image/jpg"
    });
    fs.createReadStream(TEST_IMAGE).pipe(res);
  }, 5000);
});

server.listen(8888);
  1. Place the above Node script in the root TiddlyWiki5 folder. (test.js)
  2. Run the test Node server: node test.js
  3. Run the tiddlywiki server in a seperate terminal: ./tiddlywiki.js editions/tw5.com --server
  4. Open the browser to http://localhost:8080
  5. Create a new tiddler with the following in it: <img src="http://localhost:8888/">
  6. Attempt to print in new window
BurningTreeC commented 6 years ago

for me a setTimeout of 1.5s works - cannot figure out how to wait until the tiddler content is loaded especially with lazy loading images I guess it's not a simple eventListener('load'... that does it (?)

so I did:

if (print) {
    setTimeout(function(){
        srcWindow.print();
    }, 1500);
}

... which covers my case and more cases than before but surely not all

sukima commented 6 years ago

A setTimeout won't be the best solution because (like the original) it assumes all content will load within the specified time (1500ms). This is not always the case. If you look at the above reproductions code it has a delay of five seconds which when using your setTimeout would still not work as expected.

What needs to happen is a hook when things are completed. Unfortunately I tried tapping into onLoad and DOMContentLoaded neither of which fired when I experimented with it. This is likely because we are attempting to manipulate a different window. Could use some advice from some JavaScript Gurus here.

BurningTreeC commented 6 years ago

Hm. How does this work in your test?

line 65 in windows.js

                widgetNode.render(srcDocument.body,srcDocument.body.firstChild,function(){
                // Print the window if required
                if(print) {
                                srcWindow.print();
                }
                });
BurningTreeC commented 6 years ago

-.- I thought that worked but testing it now after restarting node I've seen that I was still using the setTimeout method :+1:

Jermolene commented 6 years ago

Thanks @BurningTreeC @sukima. I wondered if we could find a good example tiddler for testing? My current thinking is that we should push the feature back to v5.1.18 if we can't fix this overnight.

sukima commented 6 years ago

@Jermolene We can't really have a test tiddler because the bug only presents itself if the content of such tiddler is remote and the remote takes forever to respond. Since most all of the tiddlers in the current repository are built-in we would not see this happen.

The reason I posted the test Node server above was to artificially introduce a large delay to the act of serving a remote image. It used an image in the repo but has nothing to do with the tiddlywiki server. Once a tiddler that references that slow image is created (by means of a <img src="http://localhost:8888/"> in the tiddler body) the bug will present itself.

BurningTreeC commented 6 years ago

@sukima in my case the bug presents itself just by printing a tiddler with many different served images

this problem seems to be chrome-only (chromium, tiddlydesktop) - because of the print dialogue not reloading what's still trying to render below firefox does it differently, the print dialogue shows in a new window - it prints the whole thing

BurningTreeC commented 6 years ago

what I'm experiencing is probably related to https://bugs.chromium.org/p/chromium/issues/detail?id=437230

on chrome/chromium javascript execution gets stopped when the print dialogue opens, that's why it prints only content that's already rendered at the moment the dialogue opens. The main wiki page on chrome/chromium also is unresponsive while the dialogue is open. That won't be fixable with waiting-til-tiddler-content-is-rendered

Jermolene commented 6 years ago

Hmm @BurningTreeC if it works on all other browsers, and the problem is just Chrome, then perhaps there's a case for retaining the feature? We'd just make a note in the release note about the issues with Chrome

BurningTreeC commented 6 years ago

yes @Jermolene , seems this is a WontFix from the chromium-side

only thing that would improve printing in those cases would be waiting until I-don't-know

Because I don't know it's ok as it is. I'll modify my windows.js with a setTimeout of around 1.5s because I'll have served images often and it's the only fix working for me atm (TiddlyDesktop has that kind of trouble, too)