18

I want to send some info back to my database when a user prints a certain web page. I can do this in IE with onbeforeprint() and onafterprint() but I would like to browser agnostic way of doing the same thing. Don't care which combination of technologies I have to use (PHP, MySQL, JavaScript, HTML) so long as it gets done. Any ideas?

EDIT:

Still having some problems with this. I tried the putting my function in my Print.css as an image, but I am messing it up some how. Then I tried just adding a event listener, but I cannot get that to work quite right either. If anyone can provide some more details on how I might call a function right before print in ANY browser I would appreciate it.

EDIT:

I am giving up on this for now, I have settled with another way of doing what I want. I look forward to the day when FireFox supports onbeforeprint() and onafterprint().

m4tx
  • 4,139
  • 5
  • 37
  • 61
ubiquibacon
  • 10,451
  • 28
  • 109
  • 179

4 Answers4

33

Many browsers now support window.matchMedia. This API allows you to detect when CSS media queries go into effect (e.g., rotating the screen or printing the document). For a cross-browser approach, combine window.matchMedia with window.onbeforeprint/window.onafterprint.

The following may result in multiple calls to beforePrint() and afterPrint() (for example, Chrome fires the listener every time the print preview is regenerated). This may or may not be desirable depending on the particular processing you're doing in response to the print.

if ('matchMedia' in window) {
    // Chrome, Firefox, and IE 10 support mediaMatch listeners
    window.matchMedia('print').addListener(function(media) {
        if (media.matches) {
            beforePrint();
        } else {
            // Fires immediately, so wait for the first mouse movement
            $(document).one('mouseover', afterPrint);
        }
    });
} else {
    // IE and Firefox fire before/after events
    $(window).on('beforeprint', beforePrint);
    $(window).on('afterprint', afterPrint);
}

More: http://tjvantoll.com/2012/06/15/detecting-print-requests-with-javascript/

Ben Vassmer
  • 194
  • 8
quietmint
  • 13,885
  • 6
  • 48
  • 73
  • 3
    Worth noting that Chrome seems to fire the print event twice. – jwl Aug 29 '13 at 18:01
  • ...actually four times -- once with media.matches=true, then media.matches=false, then media.matches=true, then media.matches=false. – jwl Aug 29 '13 at 18:47
  • This does not work when I use "Print using system dialog" in Chrome. The window closes but the printing fails. Just reporting. :) – Augiwan Feb 15 '14 at 17:51
  • 1
    Don't work for updating HTML/class with before print. Only OK for after print (with Chromium 38). See this fiddle : http://jsfiddle.net/8a71xxc2/ . Ok with FF (but only with the onbeforeprint function), not with Chrome – Denis Chenu Dec 02 '14 at 16:24
5

I m not sure other browsers will allow you to. You could of course specify an image somewhere in a print stylesheet, which probably only will be called on a print, for the onbeforeprint

Wrikken
  • 69,272
  • 8
  • 97
  • 136
  • Are you suggesting something like this? http://www.siteexperts.com/forums/viewConverse.asp?d_id=19568 – ubiquibacon Jul 27 '10 at 00:17
  • 1
    Don't know if that'll work. I would suggest calling a server-sided script as the image source which indeed returns an image, and just does the stuff you like (log a print action, possibly set a session variable other js on the page can retrieve / poll for etc.) – Wrikken Jul 27 '10 at 09:50
  • onbeforeprint is supported by Firefox since version 6, see https://developer.mozilla.org/en/DOM/window.onbeforeprint – Julien Kronegg Jun 18 '12 at 08:36
3

Try masking the native window.print() with your own...

// hide our vars from the global scope
(function(){

  // make a copy of the native window.print
  var _print = this.print;

  // create a new window.print
  this.print = function () {
    // if `onbeforeprint` exists, call it.
    if (this.onbeforeprint) onbeforeprint(this); 
    // call the original `window.print`.
    _print(); 
    // if `onafterprint` exists, call it.
    if (this.onafterprint) onafterprint(this);
  }

}())

Updated: comments.

Dagg Nabbit
  • 75,346
  • 19
  • 113
  • 141
  • Thanks @no, but I am having a hard time following your code. You say this will mask the native print function in any browser? This raises another question for me too, could I just make a JavaScript function that checked EVERY window event and then execute the function I want to execute before printing when `window.print == true`? – ubiquibacon Jul 27 '10 at 00:20
  • @typoknig: it will; because of that you may want to choose different names for `onbeforeprint` and `onafterprint`. I'm assuming you want to catch calls to `window.print` from other scripts besides your own. About the second part of your question, I think it would work, but it sounds like overkill... – Dagg Nabbit Jul 27 '10 at 00:29
  • @typoknig: I added code comments to my answer, should help explain what's going on. – Dagg Nabbit Jul 27 '10 at 00:32
  • 2
    On my page I do not provide the user with a print button, so what I really need to catch is when the user goes to `File > Print` in a non IE browser. I'll mess around with it a bit and see if I can get your code to work, if not then I might go "overkill" :) – ubiquibacon Jul 27 '10 at 00:32
  • This won't help you then. Take another look at Wrikken's answer; you can put the data you want into a query string, then add a print css rule that loads an image via a server-side script that stores the data from the query string before responding with an image. – Dagg Nabbit Jul 27 '10 at 01:05
0

I think that it's simply not possible to this properly. Or at least - not with any technology I know nor with any of the answers given previously.

Both using onafterprint and using serverside dynamic-image-generating script would tell you that the page was printed even when the visitor merely went to print preview mode and then canceled out.

However, I would like to learn how to get the proper information, so that I can be sure that page was actually printed.

userfuser
  • 1,350
  • 1
  • 18
  • 32