crabbly / Print.js

A tiny javascript library to help printing from the web.
MIT License
4.33k stars 674 forks source link

onPrintDialogClose not working with Chrome Version 86.0.4240.75 (Official Build) (64-bit) #495

Open varshapwalia opened 4 years ago

varshapwalia commented 4 years ago

I use the PrintJS library for pdf print and I used to call the onPrintDialogClose function to reload after I close the dialogue window. But since the latest chrome version, the function is being skipped altogether and not triggering. Although the dialogue window is opening but the onPrintDialogClose functionality is not triggering and skipping.

sample code which was working before:

window.printJS({printable:url, type:'pdf', onPrintDialogClose: function(){ window.location.href = "/"; window.location.reload(); }});

EDIT: Interesting point: If I switch screen or toggle any opened tab or open a new tab and come back. The reload function triggers then.

nelisbraems commented 4 years ago

I encounter the same issue.

crabbly commented 4 years ago

@varshapwalia The issue is probably due to the fact that you are killing the session by redirecting the user to another url. Please try adding a small timeout to your onPrintDialogClose callback fore you redirect the user.

crabbly commented 4 years ago

Actually, I misread your code, sorry. Just tested it in Chrome v86 on both MacOS and Windows. It works fine in MacOS but it seems to have stopped working in Windows, again.

varshapwalia commented 4 years ago

It stopped working in ubuntu as well.

animeshrajurkar commented 4 years ago

We have the same problem . And it is not just chrome . It is in Edge as well. Funny part is if you move to some other window and then come back then the popup appears again. Any workaround suggestion until this is fixed?

natilopesv commented 4 years ago

I have the same problem... What i do? :)

ermarkar commented 4 years ago

any solution so far?

ricmello commented 4 years ago

I had a production problem and spent almost one week looking for a solution, but I'm not satisfied with it.

I tried to edit the Print.js library to write an HTML and use the embed or the object tag inside it to embed the PDF document. I don't know why but both didn't work. I couldn't find if there is a new security rule or if is just a bug, but when the pdf is loaded inside the iframe, the print callback isn't fired correctly. It doesn't happen with custom HTML.

Looks that it happens only on Windows (on Mac is fine, but I don't know about Linux), and Chromium should have the same behaviour regardless the platform. This is why I think that is a bug.

I did a workaround using Mozilla's PDF.js to print PDF files and now I'm using Print.js only for HTML templates. PDF.js creates one canvas for each PDF page, save these canvas into images and then prints the output using the viewer. Is a really heavy solution, but is the best I could do so far.

To Angular guys, there is a library that help us to work with PDF.js: ngx-extended-pdf-viewer

I'm still looking for a better solution.

kruzzze commented 4 years ago

Hey guys!

Any news about this defect?

EvaggelosWolfksin commented 3 years ago

I found a workaround. Not sure if its very good solution cause I'm really new to js and typescript language but so far the behavior is stable and I dont need to click outside the window and refocus it for onPrintDialogClose to be executed I tested only for my case printing html and only on Chrome. At my component calling printJS I add and eventListener on iframe. setTimeout(() => { const height = document.getElementById('print-section').getBoundingClientRect().height; const size = margin:4px;size: 280px ${height + 50}px; printJS({ printable: "print-section", type: 'html', targetStyle: 'font-weight: 900;line-height: 2em;font-size: 2em;', pageStyle: size }); iframe = document.getElementById('printJS'); if (iframe) { iframe.contentWindow!.addEventListener('afterprint', () => { //a function after the browser print dialog is closed }); } }, 1000)

permagne commented 3 years ago

I'm having problems with this as well - onPrintDialogClose will not fire unless I change tabs back and forth. Using print-js 1.5.0 and the latest version of Chrome - 87.0.4280.66

kruzzze commented 3 years ago

Ok, I found the problem and maybe a solution.

The thing is, in the new chrome update, the windows.focus event no longer fired after the print window appeared. While moseover got on with it. This means that for the Chrome browser it is necessary to return a reaction to mouseover. True, you need to delay the execution of the cleanUp method after contentWindow.print ()

animeshrajurkar commented 3 years ago

you mean a solution that will be fixed soon in the code or you mean a workaround that we can use ?

kruzzze commented 3 years ago

I opened a pull request.

What workround can I suggest:

After calling printJS ()

add the following code:

  const handler = () => {
    // Make sure the event only happens once.
    window.removeEventListener ('mouseover', handler)

---------- your callback function here--------------

    // Remove iframe from the DOM, by default 'printJS'
    const iframe = document.getElementById (frameId)

    if (iframe) {
      iframe.remove ()
    }
  }

  setTimeout (() => {window.addEventListener ('mouseover', handler)}, 1000)

It may still need to be checked for specific browsers, I checked it only for Chrome.

Tell me, if it doesn't work, I'll try to find something else.

ermarkar commented 3 years ago

I opened a pull request.

What workround can I suggest:

After calling printJS ()

add the following code:

  const handler = () => {
    // Make sure the event only happens once.
    window.removeEventListener ('moseover', handler)

---------- your callback function here--------------

    // Remove iframe from the DOM, by default 'printJS'
    const iframe = document.getElementById (frameId)

    if (iframe) {
      iframe.remove ()
    }
  }

  setTimeout (() => {window.addEventListener ('mouseover', handler)}, 1000)

It may still need to be checked for specific browsers, I checked it only for Chrome.

Tell me, if it doesn't work, I'll try to find something else.

this is working but there is spelling mistake for mouseover event

kruzzze commented 3 years ago

this is working but there is spelling mistake for mouseover event

Oh really you are right thank you! I will fix the error in the code

and in some cases I would advise changing the event to mousemove because there is not always an element on the form.

Ldoppea commented 3 years ago

Hi,

I just started to have this problem.

Is there a problem that prevents @kruzzze's PR from being merged?

Is there anything I can do to help?

splinecl commented 3 years ago

I am experiencing the same issue in Firefox 88.01(64 bit) running on macOS BigSur 11.4

c0dester commented 2 years ago

I opened a pull request.

What workround can I suggest:

After calling printJS ()

add the following code:

  const handler = () => {
    // Make sure the event only happens once.
    window.removeEventListener ('mouseover', handler)

---------- your callback function here--------------

    // Remove iframe from the DOM, by default 'printJS'
    const iframe = document.getElementById (frameId)

    if (iframe) {
      iframe.remove ()
    }
  }

  setTimeout (() => {window.addEventListener ('mouseover', handler)}, 1000)

It may still need to be checked for specific browsers, I checked it only for Chrome.

Tell me, if it doesn't work, I'll try to find something else.

It seems to be not deterministic, worked 2 times on many attempts, not sure what made it work in my case.

My case was to print multiple documents. I've tried using printjs recursively like that:

const print = (dataArr) => {
   if (!dataArr.length) {
      return;
   }
   printJS({
      ...dataArr[0],
      onPrintDialogClose: () => {
         if (dataArr.length > 1) {
            printJS(dataArr.slice(1, dataArr.length));
         }
      },
   });
};

but onPrintDialogClose didn't work. It's not exact my code, so may have glitches. I finally managed to make printjs display multiple print dialogs by setting dynamic frameId

const print = (dataArr) => {
   dataArr.forEach((document, index) => {
      printJS({
         ...document,
         frameId: `printJS-${index}`,
      })
   })
}

I hope it'll help someone

c2oJon commented 1 year ago

I was facing a similar issue where I wanted to trigger printing of more than one PDF file.

I opened a pull request. What workround can I suggest: After calling printJS () add the following code:

  const handler = () => {
    // Make sure the event only happens once.
    window.removeEventListener ('mouseover', handler)

---------- your callback function here--------------

    // Remove iframe from the DOM, by default 'printJS'
    const iframe = document.getElementById (frameId)

    if (iframe) {
      iframe.remove ()
    }
  }

  setTimeout (() => {window.addEventListener ('mouseover', handler)}, 1000)

It may still need to be checked for specific browsers, I checked it only for Chrome. Tell me, if it doesn't work, I'll try to find something else.

It seems to be not deterministic, worked 2 times on many attempts, not sure what made it work in my case.

My case was to print multiple documents. I've tried using printjs recursively like that:

const print = (dataArr) => {
   if (!dataArr.length) {
      return;
   }
   printJS({
      ...dataArr[0],
      onPrintDialogClose: () => {
         if (dataArr.length > 1) {
            printJS(dataArr.slice(1, dataArr.length));
         }
      },
   });
};

but onPrintDialogClose didn't work. It's not exact my code, so may have glitches. I finally managed to make printjs display multiple print dialogs by setting dynamic frameId

const print = (dataArr) => {
   dataArr.forEach((document, index) => {
      printJS({
         ...document,
         frameId: `printJS-${index}`,
      })
   })
}

I hope it'll help someone

This was the answer for me. I needed to add:

frameId: `printJS-${index}`,

Then multiple print dialogues open at the same time.

Thanks!

xiaoxu9156 commented 1 year ago

I was facing a similar issue where I wanted to trigger printing of more than one PDF file.

I opened a pull request. What workround can I suggest: After calling printJS () add the following code:

  const handler = () => {
    // Make sure the event only happens once.
    window.removeEventListener ('mouseover', handler)

---------- your callback function here--------------

    // Remove iframe from the DOM, by default 'printJS'
    const iframe = document.getElementById (frameId)

    if (iframe) {
      iframe.remove ()
    }
  }

  setTimeout (() => {window.addEventListener ('mouseover', handler)}, 1000)

It may still need to be checked for specific browsers, I checked it only for Chrome. Tell me, if it doesn't work, I'll try to find something else.

It seems to be not deterministic, worked 2 times on many attempts, not sure what made it work in my case. My case was to print multiple documents. I've tried using printjs recursively like that:

const print = (dataArr) => {
   if (!dataArr.length) {
      return;
   }
   printJS({
      ...dataArr[0],
      onPrintDialogClose: () => {
         if (dataArr.length > 1) {
            printJS(dataArr.slice(1, dataArr.length));
         }
      },
   });
};

but onPrintDialogClose didn't work. It's not exact my code, so may have glitches. I finally managed to make printjs display multiple print dialogs by setting dynamic frameId

const print = (dataArr) => {
   dataArr.forEach((document, index) => {
      printJS({
         ...document,
         frameId: `printJS-${index}`,
      })
   })
}

I hope it'll help someone

This was the answer for me. I needed to add:

frameId: `printJS-${index}`,

Then multiple print dialogues open at the same time.

Thanks!

it works for me,Thanks!