2

I am using this code to open and print image on new html page:

printView(dataUri:string){

  var win = window.open();
  win.document.write( '<img src="' + dataUri + '">');

  win.print();
  win.close();

}

When used like that and image is larger than few kB, print preview opens a blank page, because document is not rendered when print is invoked.

I solved that (temporarily) by introducing setTimeout with ~200ms delay before printing, like this:

setTimeout( () => {
     win.print();
     win.close();
}, 200);

And this works, but I am aware that I should use some DOM/window event to wait until content is loaded. But which one?

What I tried so far:

win.document.onload = ()=>{
    console.log('event fired'); // never fired
    win.print();
    win.close();
}

and

win.addEventListener('load', ()=>{
    console.log('event fired'); // never fired
    win.print();
    win.close();
}

I would like to keep this Vanilla JS, so please do not refer me to jQuery window.ready.

bocko
  • 388
  • 3
  • 7
  • 18
  • What do you mean by "wait for HTML document to load"? As soon as you do window.open(), a new document is created and automatically loaded, because it's initially empty – Daniel Aug 21 '17 at 10:58
  • I believe your win.document.onload events are not being fired because you're defining them after that window.open(), by the time you bind the event handler, the event as already been called – Daniel Aug 21 '17 at 10:59
  • And your main problem here is that you want the page to load only after certain conditions! In the example you specified here in this question, you only have 1 condition, which is (load after the image being loaded) – Daniel Aug 21 '17 at 11:01
  • Taking these facts into account, we can conclude that no DOM methods nor event handlers can help you with that! – Daniel Aug 21 '17 at 11:02
  • I can suggest you a solution, but since your loading is not actually the document's one, you'll have to update it whenever you change or add something that should be ready after that load! – Daniel Aug 21 '17 at 11:04
  • Let me also ask you, Why do you want to wait for that loading? Is it some sort of pre-loader our loading spinner you want to hide, or something else? What is it? – Daniel Aug 21 '17 at 11:12
  • If I don't wait, all I get from print () method is blank screen. – bocko Aug 21 '17 at 11:34
  • I wasn't putting the wait into question, you would have to wait in some sort of manner, I just wanted to make a point that the `onload` DOM event handler would not help you in this situation, and I was trying to understand why do you wanted to wait, since in this example was obviously because of the print, but in your real situation it could be other thing, just for the sake of contextualizing the solution! – Daniel Aug 21 '17 at 11:37
  • You are right. What is actually needed is **object** event, like img.onload(). I thought that DOM event also fires when img source changes, but it is not the case. Cheers. – bocko Aug 21 '17 at 16:20

5 Answers5

3

add an onload attribute to your image

 win.document.write( '<img src="' + dataUri + '" onload="print()">');

remove win.print() and win.close() from printView()

and add them into another function print()

print() will be fired when the image is finished loading.

this time Hope It Works

  • Works just as I wanted it! Thank you. – bocko Aug 21 '17 at 11:35
  • feeling happy cause i could help you :D :D – Imtiaz Chowdhury Aug 21 '17 at 11:37
  • I think that your edited answer is not as good as the original. In case of slow loading of an image, there is a possibility of call stack overflow - two functions call each other zillions of times until condition is met. And what if image is loading from external source and connection breaks? – bocko Aug 21 '17 at 16:15
  • ooh! thanks. actually i didn't think form that point of view. You know thtere are always bugs in programs. I have edited it to the original. – Imtiaz Chowdhury Aug 21 '17 at 16:18
3

I know it's already answered, but I needed to print a new window with a lot of html content and used something like this:

win.document.addEventListener('DOMContentLoaded', this.print());
Marco
  • 1,279
  • 1
  • 15
  • 26
0

including the script tag at the bottom of your page should work. because the browser reads the html page from top to bottom, it will fire the event after the page is loaded when the script is located at the bottom of the page.

  • Thanks for your quick answer. It should work, but it doesn't. When I add `win.document.write( '');` at the end, script executes just the same as in my example: with image not being loaded yet. Even if I add `defer` attribute to the script, result is the same… – bocko Aug 21 '17 at 11:05
  • there is another way you can try, but i am not sure. i am posting another answer – Imtiaz Chowdhury Aug 21 '17 at 11:10
0

Copy from What is the non-jQuery equivalent of '$(document).ready()'? domready.js

(function(exports, d) {
  function domReady(fn, context) {

    function onReady(event) {
      d.removeEventListener("DOMContentLoaded", onReady);
      fn.call(context || exports, event);
    }

    function onReadyIe(event) {
      if (d.readyState === "complete") {
        d.detachEvent("onreadystatechange", onReadyIe);
        fn.call(context || exports, event);
      }
    }

    d.addEventListener && d.addEventListener("DOMContentLoaded", onReady) ||
    d.attachEvent      && d.attachEvent("onreadystatechange", onReadyIe);
  }

  exports.domReady = domReady;
})(window, document);

How to use it

<script src="domready.js"></script>
<script>
  domReady(function(event) {
    alert("dom is ready!");
  });
</script>
  • Thank you. If I am correct, it is essentially adding EventListener for "DOMContentLoaded" event, right? On my second try from original question, I also tried to `addEventListener` for DOMContentLoaded, but it never fired, too... – bocko Aug 21 '17 at 11:24
0

Here it is, based mostly on Imtiaz's idea:

var win = window.open();
var img = win.document.createElement("img");
img.onload = function(){
    win.print();
    win.close();
}
img.src = dataUri;
win.document.body.appendChild(img);

I just thought that it's cleaner to do in script, instead of using a script to write another script to html…

bocko
  • 388
  • 3
  • 7
  • 18