关于javascript:如何检测window.print()完成

How to detect window.print() finish

在我的应用程序中,我尝试为用户打印出凭证页面,如下所示:

1
2
3
  var htm ="Voucher Details";
  $('#divprint').html(htm);
  window.setTimeout('window.print()',2000);

" divprint"是我页面中的div,用于存储有关凭证的信息。

它起作用,并且打印页面弹出。 但是,一旦用户在浏览器的弹出式打印对话框中单击" print"或" close",我就希望推进该应用程序。

例如,我想在弹出窗口关闭后将用户重定向到另一个页面:

1
window.application.directtoantherpage();//a function which direct user to other page

如何确定关闭弹出式打印窗口或何时完成打印?


您可以收听印后事件。

https://developer.mozilla.org/zh-CN/docs/Web/API/window.onafterprint

1
2
3
window.onafterprint = function(){
   console.log("Printing completed...");
}

可能可以使用window.matchMedia以另一种方式获得此功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
(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/


在镀铬(V.35.0.1916.153 m)上尝试以下操作:

1
2
3
4
function loadPrint() {
    window.print();
    setTimeout(function () { window.close(); }, 100);
}

对我来说很棒。用户完成打印对话框后,它将关闭窗口。


与Chrome,Firefox,Opera,Internet Explorer兼容

注意:需要jQuery。

1
2
3
4
5
6
7
8
9
10
    window.onafterprint = function(e){
        $(window).off('mousemove', window.onafterprint);
        console.log('Print Dialog Closed..');
    };

    window.print();

    setTimeout(function(){
        $(window).one('mousemove', window.onafterprint);
    }, 1);


参见https://stackoverflow.com/a/15662720/687315。解决方法是,您可以在window.mediaMatch之后在窗口(Firefox和IE)上侦听afterPrint事件,并在文档上侦听鼠标移动(指示用户已关闭打印对话框并返回到页面)。 API表示媒体不再匹配"打印"(Firefox和Chrome)。

请记住,用户可能已经或可能没有实际打印过文档。另外,如果您在Chrome中经常调用window.print(),则甚至可能不会提示用户进行打印。


window.print在chrome上的行为是同步的。在控制台中尝试

1
2
window.print();
console.log("printed");

除非用户关闭(取消/保存/打印)打印对话框,否则不会显示"已打印"。

这是有关此问题的更详细的说明。

我不确定IE或Firefox稍后是否会检查和更新


您只需将window.print()放入另一个函数中,即可检测出它何时完成

1
2
3
4
5
//function to call if you want to print
var onPrintFinished=function(printed){console.log("do something...");}

//print command
onPrintFinished(window.print());

在Firefox,Google chrome,IE中测试


考虑到您希望等待打印对话框消失,我将在窗口上使用焦点绑定。

1
2
3
4
5
6
7
8
print();

var handler = function(){
    //unbind task();
    $(window).unbind("focus",handler);
}

$(window).bind("focus",handler);

通过在处理程序函数中加入取消绑定,我们可以防止焦点事件保持与窗口的绑定。


这实际上对我来说适合Chrome。我很惊讶。

1
2
3
4
5
jQuery(document).bind("keyup keydown", function(e){
    if(e.ctrlKey && e.keyCode == 80){
         Print(); e.preventDefault();
    }
});

我写的其中Print是一个调用window.print();的函数。如果禁用Print(),它也可以用作纯阻止程序。

如用户3017502所述

window.print()将暂停,因此您可以像这样添加onPrintFinish或onPrintBegin

1
2
3
4
5
function Print(){
    onPrintBegin
    window.print();
    onPrintFinish();
}

它对我有用$(window).focus()。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var w;
var src = 'http://pagetoprint';
if (/chrom(e|ium)/.test(navigator.userAgent.toLowerCase())) {
    w = $('<iframe></iframe>');
    w.attr('src', src);
    w.css('display', 'none');
    $('body').append(w);
    w.load(function() {
        w[0].focus();
        w[0].contentWindow.print();
    });
    $(window).focus(function() {
        console.log('After print');
    });
}
else {
    w = window.open(src);
    $(w).unload(function() {
        console.log('After print');
    });
}

经过IE,FF,Chrome的测试,可以正常运行。

1
2
    setTimeout(function () { window.print(); }, 500);
    window.onfocus = function () { setTimeout(function () { window.close(); }, 500); }


使用w = window.open(url,'_blank')在新窗口中打印,然后尝试w.focus(); w.close();并检测页面何时关闭。在所有浏览器中均可使用。

1
2
3
4
5
6
7
w = window.open(url, '_blank');
w.onunload = function(){
 console.log('closed!');
}
w.focus();
w.print();
w.close();

完成打印后窗口关闭。


您真的不知道用户是否单击了cancel按钮的print,因为它们都触发了同一事件onafterprintafterprint,我认为这是非常愚蠢的,为什么不区分这两个事件?


由于打印后浏览器的行为不同,这很困难。 桌面版Chrome内部处理打印对话框,因此在打印后不会转移焦点,但是afterprint事件在这里可以正常使用(目前为81.0)。 另一方面,在打印后,移动设备和大多数其他浏览器上的Chrome会转移焦点,并且afterprint事件在此处无法始终如一地工作。 鼠标移动事件在移动设备上不起作用。

因此,检测它是否为台式机Chrome,
如果是,请使用印后事件。 如果否,请使用基于焦点的检测。 您还可以结合使用鼠标移动事件(仅适用于台式机),以涵盖更多浏览器和更多场景。


我认为窗口聚焦方法是正确的。这是我要在隐藏的iframe中打开PDF网址Blob并进行打印的示例。打印或取消后,我想删除iframe。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
 * printBlob will create if not exists an iframe to load
 * the pdf. Once the window is loaded, the PDF is printed.
 * It then creates a one-time event to remove the iframe from
 * the window.
 * @param {string} src Blob or any printable url.
 */

export const printBlob = (src) => {
  if (typeof window === 'undefined') {
    throw new Error('You cannot print url without defined window.');
  }
  const iframeId = 'pdf-print-iframe';
  let iframe = document.getElementById(iframeId);
  if (!iframe) {
    iframe = document.createElement('iframe');
    iframe.setAttribute('id', iframeId);
    iframe.setAttribute('style', 'position:absolute;left:-9999px');
    document.body.append(iframe);
  }
  iframe.setAttribute('src', src);
  iframe.addEventListener('load', () => {
    iframe.contentWindow.focus();
    iframe.contentWindow.print();
    const infanticide = () => {
      iframe.parentElement.removeChild(iframe);
      window.removeEventListener('focus', infanticide);
    }
    window.addEventListener('focus', infanticide);
  });
};


实现window.onbeforeprint和window.onafterprint

在Chrome v 78.0.3904.70中window.print()无法使用后的window.close()调用

为了解决这个问题,我使用亚当的答案进行了简单的修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
     function print() {
    (function () {
       let afterPrintCounter = !!window.chrome ? 0 : 1;
       let beforePrintCounter = !!window.chrome ? 0 : 1;
       var beforePrint = function () {
          beforePrintCounter++;
          if (beforePrintCounter === 2) {
             console.log('Functionality to run before printing.');
          }
       };
       var afterPrint = function () {
          afterPrintCounter++;
          if (afterPrintCounter === 2) {
             console.log('Functionality to run after printing.');
             //window.close();
          }
       };
       if (window.matchMedia) {
          var mediaQueryList = window.matchMedia('print');
          mediaQueryList.addListener(function (mql) {
             if (mql.matches) {
                beforePrint();
             } else {
                afterPrint();
             }
          });
       }
       window.onbeforeprint = beforePrint;
       window.onafterprint = afterPrint;
    }());
    //window.print(); //To print the page when it is loaded
 }

我在这里称呼它:

1
<body onloadx="print();">

这对我有用。
请注意,我对这两个功能都使用了计数器,以便可以在不同的浏览器中处理此事件(在Chrome中触发两次,在Mozilla中触发一次)。
要检测浏览器,您可以参考此答案