检测浏览器打印事件

57

有没有可能检测到用户从其浏览器打印某些内容?

更复杂的是,如果我们在新窗口中向用户呈现PDF文档,是否可以检测到该文档的打印(假设用户从浏览器窗口打印它)?

我能找到的最接近的解决方案是,如果我们实现自定义打印功能(类似于这个),并跟踪何时调用它。

我主要关注适用于Internet Explorer(6或更高版本)的解决方案。

4个回答

122

你现在可以使用以下技术在IE 5+、Firefox 6+、Chrome 9+和Safari 5+中检测打印请求:

(function() {
    var beforePrint = function() {
        console.log('Functionality to run before printing.');
    };
    var afterPrint = function() {
        console.log('Functionality to run after printing');
    };

    if (window.matchMedia) {
        var mediaQueryList = window.matchMedia('print');
        mediaQueryList.addListener(function(mql) {
            if (mql.matches) {
                beforePrint();
            } else {
                afterPrint();
            }
        });
    }

    window.onbeforeprint = beforePrint;
    window.onafterprint = afterPrint;
}());

我会在http://tjvantoll.com/2012/06/15/detecting-print-requests-with-javascript/上详细解释这段代码的作用及其用途。


1
你太棒了。我已经搜索了几天关于onbeforeprint在Chrome/Safari上的支持,早该知道不应该离开SO这个温暖的怀抱。 - Pat
2
+1,非常好,我计划很快抄袭这个答案。 - Andy E
8
在Windows上的Chrome 38中似乎不再起作用。beforePrint事件不会触发。http://jsfiddle.net/o5oosa9o/ (右键单击结果iframe,选择“打印...”) - Michael
3
在 Chrome 中,当打印预览完成渲染后,afterPrint 事件现在会立即触发。 - Marcel Burkhard
2
抱歉打扰了,但我是从我的问题(http://stackoverflow.com/questions/28620711/extjs-4-creating-a-callback-for-an-override-function-for-printing-panel-conten)跳转到这里的。如果我想检测实际按下“打印”按钮而不仅仅是用户发出的任何打印请求,该怎么办? - Razgriz
显示剩余7条评论

7
对于Internet Explorer,有事件window.onbeforeprintwindow.onafterprint,但它们不适用于其他浏览器,因此它们通常是无用的。出于某种原因,它们似乎完全相同,都在打印窗口打开之前执行其事件处理程序。
但是,如果您尽管存在这些注意事项仍然需要使用它,请参考以下示例:
window.onbeforeprint = function() {
    alert("Printing shall commence!");
}

4
不确定"Internet Exploder"是不是打字错误,但是这太有趣了 kkkk。 - Bernardo Dal Corno
FYI https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeprint - Avatar

5

对于2020年以后阅读此文的人,addListener函数大多已被废弃,推荐使用addEventListener,但在Safari浏览器中除外:

if (window.matchMedia) {
  const media = window.matchMedia("print");
  const myFunc = mediaQueryList => {
    if (mediaQueryList.matches) {
      doStuff();
    }
  };
  try {
    media.addEventListener("change", myFunc);
  } catch (error) {
    try {
    media.addListener(myFunc);
    } catch (error) {
      console.debug('Error', error)
    }
  }
}

参考: 这个 StackOverflow 的问题


2
如果仅用于跟踪目的,也许你可以在CSS打印媒体中设置背景URL到服务器页面(.aspx、.php等),然后在服务器上执行某些操作?这个家伙声称它有效
这不如TJ的解决方案灵活,但当只需要跟踪时,可能会更少出现错误(请参阅TJ的博客文章以了解他发现的问题)。

我认为我的方法存在一些问题,例如打印预览等方面,但对于不太关键的日志记录,它对我来说还算可以。 - Adam K Dean

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接