【问题标题】:How to detect window.print() finish如何检测 window.print() 完成
【发布时间】:2013-08-21 21:53:55
【问题描述】:

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

  var htm ="<div>Voucher Details</div>";
  $('#divprint').html(htm);
  window.setTimeout('window.print()',2000);

'divprint'是我页面中的div,它存储有关凭证的信息。

它工作,并弹出打印页面。但是,一旦用户在浏览器的弹出打印对话框中单击“print”或“close”,我想推进应用程序。

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

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

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

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    你可以监听 afterprint 事件。

    https://developer.mozilla.org/en-US/docs/Web/API/window.onafterprint

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

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

    (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/

    【讨论】:

    • 请记住,媒体查询侦听器将立即触发 afterPrint()。它不会等到打印对话框关闭,这就是为什么我的答案在使用媒体查询解决方案时会监听mouseover...
    • IE 7 没有(等不及它消失了)。 onafterprint 在打印对话框打开后立即启动。至少这是我的经验。
    • 在 IE 11 上 onafterprint 在打印对话框出现之前触发(显然,没有打印)
    • 在 IE 11 matchMedia 上存在,但监听器从不触发
    • 无论用户是否确认打印,都会调用 onafterprint。如何判断用户是否确认打印?
    【解决方案2】:

    在 chrome (V.35.0.1916.153 m) 上试试这个:

    function loadPrint() {
        window.print();
        setTimeout(function () { window.close(); }, 100);
    }
    

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

    【讨论】:

    • 我认为这是最简单的解决方案。我喜欢!
    • 感谢您的回答,我找到了一个简单的解决方案:我在打印之前添加了一个新的答案 'window.open('', '_self', '');'
    • 接受的答案适用于极少数浏览器。在打印之后直接放置 window.close 会导致窗口在打印对话框之前消失。但是,使用 setTimeout 会导致关闭在事件队列中排队,100ms 超时实际上并不是计时的事情,计时器将被阻塞,直到打印对话框关闭,此时 100ms 计时器启动。一个更好的解决方案。
    • 太棒了!适用于 Firefox 51.0.1 和 Chrome 54.0.2840.90
    • 这在 Android 上的 Chrome v68 之后不再有效。您需要将超时时间延长到 500 毫秒才能出现打印对话框,然后,如果您更改打印机,窗口已经关闭,浏览器将无法再刷新。
    【解决方案3】:

    兼容 chrome、firefox、opera、Internet Explorer
    注意:需要 jQuery。

    <script>
    
        window.onafterprint = function(e){
            $(window).off('mousemove', window.onafterprint);
            console.log('Print Dialog Closed..');
        };
    
        window.print();
    
        setTimeout(function(){
            $(window).one('mousemove', window.onafterprint);
        }, 1);
    
    </script>
    

    【讨论】:

    • 这里有点错别字,$(window).one() 应该是 $(window).on()。无论如何,很好的解决方案!
    • @JayDadhania 那是not a typo
    【解决方案4】:

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

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

    【讨论】:

      【解决方案5】:

      您可以通过将 window.print() 放入另一个函数中来检测它何时完成

      //function to call if you want to print
      var onPrintFinished=function(printed){console.log("do something...");}
      
      //print command
      onPrintFinished(window.print());
      

      在 Firefox、谷歌浏览器、IE 中测试

      【讨论】:

      • 您所做的只是将 window.print() 的返回值传递给另一个函数,当您调用 onPrintFinished 时,当然 window.print() 将首先执行,但前提是浏览器提供同步 print() 方法(例如,最新的 linux 上的 firefox 提供了这个)onPrintFinished 函数将在打印对话框关闭后执行,在其他浏览器(例如最新的 Chromium)上,print() 方法是异步的,所以这是没用的。
      • 现代 Chrome、Safari、FireFox...都支持这样做。
      • 在最新版 chrome 中工作
      • 我不认为这是解决这个问题的好方法,请添加事件监听器 onafterprint 来关闭窗口。 window.onafterprint = function(){ window.close()};
      【解决方案6】:

      window.print 在 chrome 上同步运行 .. 在您的控制台中尝试此操作

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

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

      Here is a more detailed explanation about this issue.

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

      【讨论】:

      • 是的,这是 chrome 中的一个错误,它已修复。在最新的 chrome 中,这不起作用。感谢您的评论,我必须在产品中解决问题:)
      • 这仍然有效,至少在 chrome (77.0.3865.90) 和 firefox (69.0.1) 我不知道 Edge 或 Safari
      【解决方案7】:

      这实际上在 chrome 中对我有用。我很惊讶。

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

      Print 是我编写的一个函数,它调用 window.print();如果你禁用 Print(),它也可以作为一个纯粹的拦截器;

      如 user3017502 所述

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

      function Print(){
          onPrintBegin
          window.print();
          onPrintFinish(); 
      }
      

      【讨论】:

        【解决方案8】:

        鉴于您希望等待打印对话框消失,我会在窗口上使用焦点绑定。

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

        通过在处理函数中加入 unbind,我们可以防止焦点事件保持绑定到窗口。

        【讨论】:

        • 看来你忘了关闭你的"focus :)
        【解决方案9】:

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

        w = window.open(url, '_blank');
        w.onunload = function(){
         console.log('closed!');
        }
        w.focus();
        w.print();
        w.close();
        

        打印完成后关闭窗口。

        【讨论】:

        • 在 IE 11 上这对我有用,但只是第一次。以后每次我打开窗口时它都会自动关闭而不给我打印对话框
        • 是 Internet Explorer 的一个 bug。向 Microsoft 报告并等待他们获得补丁或使用其他替代方案。
        • 不只是 Internet Explorer 会失败。在 Chrome 中,这通常会打印一个空白页,因为 w.print() 是异步发生的,并且您已经使用 @987654323 将页面从其脚下拉出@ 在它真正准备好打印之前。
        【解决方案10】:

        测试过 IE, FF, Chrome 和所有的作品。

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

        【讨论】:

        • 这里缺少一些细节,但尽我所能填写,这对我仍然不起作用(在 Ubuntu 19.10 上的 Chrome 80 中)。如果您正在打印您已经关注的页面,它不会在任何时候失去焦点,因此onfocus 在您完成后不会触发。如果您正在打印iframe,您所在的页面会失去焦点,但在打印完成后不会自动重新获得焦点,因此这仍然无法正常工作。
        【解决方案11】:

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

        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');
            });
        }
        

        【讨论】:

          【解决方案12】:

          我认为窗口焦点方法是正确的。这是一个示例,我想在隐藏的 iframe 中打开 PDF url blob 并打印它。打印或取消后,我想删除 iframe。

          /**
           * 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);
            });
          };
          

          【讨论】:

          • 我遇到了问题exports is not defined
          • 这并没有直接解决所提出的问题。从字里行间看,我想如果我们希望它在打印后运行,我们可以将代码添加到 infanticide 函数。但这也不太正确。至少在我的浏览器(Ubuntu 19.10 上的 Chrome 80)中,窗口在打印后不会立即重新获得焦点 - 只有当我单击或按标签返回时。
          【解决方案13】:

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

          所以,Detect if it is Desktop Chrome, 如果,请使用afterprint event。如果,请使用focus based detection。您还可以结合使用鼠标移动事件(仅适用于桌面),以覆盖更多浏览器和更多场景。

          【讨论】:

            【解决方案14】:

            检测打印是否完成并关闭打印窗口的最简单方法:

            window.onafterprint = function(){ 
              window.onfocus = function(){  
                window.close();
              }
            };
            

            【讨论】:

              【解决方案15】:

              实现window.onbeforeprint和window.onafterprint

              window.print() 之后的 window.close() 调用在 Chrome v 78.0.3904.70 中不起作用

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

                   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
               }
              

              我在这里调用它:

              <body onload="print();">
              

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

              【讨论】:

              • 最好检查onafterprint,如果存在就使用它,否则尝试matchMedia hack。按照您的方式,您永远不会在旧版本的 Chrome 中调用您的处理程序,其中(如果可以相信 Adam 接受的答案)matchMedia 方法有效,但 onafterprint 无效,您将调用它 在 Chrome 以外的任何浏览器中两次,这两种方法都有效。
              猜你喜欢
              • 1970-01-01
              • 2012-06-30
              • 1970-01-01
              • 1970-01-01
              • 2019-07-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多