JavaScript print blocked by Chrome, Workaround?

11,688

Solution 1

You could conditionally replace the window.print() function:

// detect if browser is Chrome
if(navigator.userAgent.toLowerCase().indexOf("chrome") >  -1) {
    // wrap private vars in a closure
    (function() {
        var realPrintFunc = window.print;
        var interval = 2500; // 2.5 secs
        var nextAvailableTime = +new Date(); // when we can safely print again

        // overwrite window.print function
        window.print = function() {
            var now = +new Date();
            // if the next available time is in the past, print now
            if(now > nextAvailableTime) {
                realPrintFunc();
                nextAvailableTime = now + interval;
            } else {
                // print when next available
                setTimeout(realPrintFunc, nextAvailableTime - now);
                nextAvailableTime += interval;
            }
        }
    })();
}

Instead of using an external safety timer/wrapper, you can use an internal one. Just add this and window.print behaves safely in Chrome and normally everywhere else. (Plus, the closure means realPrintFunc, interval and nextAvailableTime are private to the new window.print

If you need to coordinate calls to window.print between multiple framed pages, you could set nextAvailableTime in the parent page, rather than in the closure, so that all the frames could access a shared value using window.parent.nextAvailableTime.

Solution 2

I've been bumping up against the same issue, and the most direct solution for me was to just create a new window, write what I need to it, close it, and print it. I haven't had to deal with Chrome's limit since I changed it to work this way, and I don't need to do any tracking.

print_window= window.open();
print_window.document.write(print_css + divToPrint[0].outerHTML+"</html>");
print_window.document.close();
print_window.focus();
print_window.print();
print_window.close();

Solution 3

If all your printers are network-compatible, you could change what happens when clicking on the print button. Instead of printing the page, your application could send a request to a server with the URL of the page to print and with an information on which printer to print.

The server then launches the print process manually and there will be no browser in between, which could stop you from doing so.

Solution 4

My solution would be to call the window.print() less frequently. You could try wrapping window.print() into a method of your own and put a minimum time interval that has to pass before the window.print() is executed again. You can have some kind of change/animation in UI to indicate that work is being done.

"Working"

Unless you think it really think pressing print-button more than once a second/every few seconds helps? I mean if the window.print() operation takes that long it's not your codes fault and there should be a "wait and be patient" -indicator in UI anyway.

Solution 5

Everywhere I see mentioning this issue suggests using timers. However they do not solve the issue and I feel like Kamyar is the only person who actually read the source and understands the problem, so I do wonder why he accepted the answer he did.

The main problem is that the length of the delay in Chrome is exponential, so for these timers to work their delay has to also be increased on every usage which of course would get very annoying very quickly. Chrome actually only applies the delay after cancelled print requests but we can't detect whether a print is successful or not anyway.

Abathur's solution actually works much better than you might expect. I'm not sure if I'll use it but it does work.

The good news:

1) The delay is actually reduced in more recent versions of Chrome. It now goes: [2, 2, 2, 4, 8, 16, 32, 32, ...].

2) Someone took up the issue on August 28th: http://code.google.com/p/chromium/issues/detail?id=50186 If you want this issue resolved then please go star it.

Share:
11,688
Kamyar Nazeri
Author by

Kamyar Nazeri

Coder for life with expertise in C++, C#, Python, JavaScript, TypeScript, and most recently with a focus on Cloud, Deep Learning in Computer Vision, and Generative Models. Homepage: knazeri.github.io Twitter: @knazeri LinkedIn: kamyar nazeri GitHub: github.com/knazeri

Updated on June 14, 2022

Comments

  • Kamyar Nazeri
    Kamyar Nazeri about 2 years

    I know it has been discussed here before, yet I found no practical solution/workaround for this, I'm hoping if someone has any idea how to resolve this problem!

    Here's it is:

    If you try to call window.print() method frequently within a single page(as if a user clicks on a print button) in google Chrome, the browser throws a warning message in the console, stating:

    Ignoring too frequent calls to print()

    And nothing happens! After several seconds, things go back to normal and print dialog appears the moment you call window.print() command again! To make matters worse, the good Chrome folks use exponential wait time for a page that calls print command, meaning the more user clicks on a button to print, the more he has to wait for the print dialog to appear!

    This issue has been in chrome for quite some time (14 subsequent versions) and it is confirmed as being an Area-UI bug, I posted it again for google team yesterday hoping if someone from Chrome team can verify when this incredible annoying feature is going to be fixed!

    However, what I'm looking for here is a workaround for this problem, is there anything I can do be able to get this working? My company is developing a highly transactional financial system with lots of reports that needs printing, and for just this one little glitch, the whole project is at risk of running in my favorite google Chrome browser!

    Update:

    Here's the code in Chrome browser that causes this feature and it looks like that at least 2 seconds is needed before someone calls print command again, so a timer of 2 seconds interval in UI could possibly prevent getting into an infinite wait callback! any other thoughts?

  • Kamyar Nazeri
    Kamyar Nazeri about 12 years
    Yes, that's what I've done so far, a 2 seconds interval is the minimum wait time before sending another print command
  • Kamyar Nazeri
    Kamyar Nazeri about 12 years
    Neat solution, I'll do that when the program is installed in a local network, but unfortunately the software is targeted on both local and wide area networks!
  • Kamyar Nazeri
    Kamyar Nazeri about 12 years
    This snippet actually works, however you need to take into account that frequent calls to print are only blocked when someone cancels the print dialog, so the timer needs to be started only when dialog is disappeared, I guess this is well accomplished by storing a reference of setTimeout and clearing it whenever you create a new one, OR you can set a busy flag whenever setTimeout starts and DO NOT start a new one when the flag is set. Thanks for your time thought
  • Weston C
    Weston C over 11 years
    Does this snippet still work for some people? I'm finding that I'm still seeing the ignoring too frequent calls to print error while using both the code as given verbatim, and some variations which watch for a flag/timeout so's not to set further timeout functions. Using Chrome 22.0.1229.94.
  • Frank B
    Frank B over 11 years
    I have 23 and it's still a problem.