chrome中的Javascript window.print(),关闭新窗口或选项卡而不是取消打印会在父窗口中阻止Ja

Javascript window.print() in chrome, closing new window or tab instead of cancelling print leaves javascript blocked in parent window

本文关键字:窗口 打印 取消 Ja print window Javascript 中的 选项 chrome 新窗口      更新时间:2023-09-26

在我工作的应用程序中,用户可以从几个不同的地方进行打印。在所有这些情况下,我们都使用相同的工作流程,打开一个新窗口(或选项卡),将需要打印的内容写入新窗口的文档,然后我们称之为

    $(w.document).ready(function () {
        w.focus();
        w.print();
        w.close();
    });  

我看到的问题是,在Chrome中,如果我关闭为打印预览打开的选项卡或窗口,而不是单击取消按钮,Chrome仍然会阻止我的父窗口上的javascript。

它与此处描述的问题类似:

当在子窗口上打开打印预览时,Google Chrome会阻止ajax请求

我们也遇到了这个问题,但我相信这是我们如何在新窗口中实现打印以及Chrome打印预览工作方式的结果。在IE和Firefox中,打印窗口显示模式对话框,在关闭打印窗口之前,您无法在父窗口中执行任何操作。类似地,chrome会阻止使用父窗口,直到取消打印预览。但是,我希望关闭该选项卡或窗口的工作方式与取消打印的工作方式相同。
其他人有没有遇到过这个问题,或者知道一个好的解决方案?

谢谢!

看起来问题已经通过最新的Chrome更新得到解决。。。我正在运行Chrome版本36.0.1964.4 dev-m。

我也受到了限制,通过以下操作警告用户关闭打印预览窗口:

if(navigator.userAgent.toLowerCase().indexOf('chrome') > -1){   // Chrome Browser Detected?
    window.PPClose = false;                                     // Clear Close Flag
    window.onbeforeunload = function(){                         // Before Window Close Event
        if(window.PPClose === false){                           // Close not OK?
            return 'Leaving this page will block the parent window!'nPlease select "Stay on this Page option" and use the'nCancel button instead to close the Print Preview Window.'n';
        }
    }                   
    window.print();                                             // Print preview
    window.PPClose = true;                                      // Set Close Flag to OK.
}

现在,Chrome更新后,警告不再出现。

问题是弹出窗口中存在浏览器内打印对话框。如果立即调用window.close(),则用户看不到对话。用户需要点击对话框中的"打印"。这与其他浏览器不同,在其他浏览器中,打印对话框是操作系统的一部分,并阻止window.close()直到被驳回——在Chrome上,它是Chrome的一部分而不是操作系统。

这是我在一个由父窗口创建的小弹出窗口中使用的代码:

var is_chrome = function () { return Boolean(window.chrome); }
window.onload = function() {
    if(is_chrome){
        /*
         * These 2 lines are here because as usual, for other browsers,
         * the window is a tiny 100x100 box that the user will barely see.
         * On Chrome, it needs to be big enough for the dialogue to be read
         * (NB, it also includes a page preview).
        */
        window.moveTo(0,0);
        window.resizeTo(640, 480);
        // This line causes the print dialogue to appear, as usual:
        window.print();
        /*
         * This setTimeout isn't fired until after .print() has finished
         * or the dialogue is closed/cancelled.
         * It doesn't need to be a big pause, 500ms seems OK.
        */
        setTimeout(function(){
            window.close();
        }, 500);
    } else {
        // For other browsers we can do things more briefly:
        window.print();
        window.close();
    }
}

为了解决这个问题,我不得不将打印过程从一个新窗口切换到一个隐藏的iframe。iframe保留在DOM中,并可用于其他打印(在我们的例子中是收据)。

灵感来自Daybreaks的答案https://stackoverflow.com/a/39099832/373521

function printHtml(html) {
    try {
        var iframe = document.getElementById("printingFrame");
        if (!iframe) {
            iframe = document.createElement('iframe');
            iframe.id = "printingFrame";
            iframe.name = "printingFrame";
            iframe.width = '0';
            iframe.height = '0';
            iframe.style = 'position: absolute;top: 0;left: 0;width: 0;height: 0;';
            document.body.appendChild(iframe);
        }
        iframe.contentWindow.document.open();
        iframe.contentWindow.document.write('<!DOCTYPE html');
        iframe.contentWindow.document.write('<html><head>');
        iframe.contentWindow.document.write(
            '<style type="text/css">' +
            'body{font-family:Verdana, Arial;font-size:12px;}' +
            '@media all {.page-break { display: none; }}' +
            '@media print {.page-break { display: block; page-break-before: always; }}' +
            '</style>');
        iframe.contentWindow.document.write('</head><body>');
        iframe.contentWindow.document.write(html);
        iframe.contentWindow.document.write('</body></html>');
        iframe.contentWindow.document.close();
        window.frames["printingFrame"].focus();
        window.frames["printingFrame"].print();
    } catch (ex) {
        console.error("Error printing: " + ex.message);
    }
}

如果setTimeout函数也不适用,请执行以下操作:

//Create an iframe
iframe = $('body').append($('<iframe id="documentToPrint" name="documentToPrint" src="about:blank"/>'));
iframeElement = $('#documentToPrint')[0].contentWindow.document;
//Open the iframe
iframeElement.open();
//Write your content to the iframe
iframeElement.write($("yourContentId").html());
//This is the important bit.
//Wait for the iframe window to load, then print it.
$('#documentToPrint')[0].contentWindow.onload = function () {
    $('#print-document')[0].contentWindow.print();
    $('#print-document').remove();
};
iframeElement.close();

对于那些弹出一个新窗口进行打印,然后在用户点击Chrome打印预览上的"打印"或"取消"后自动关闭它的人,我使用了以下内容(感谢PaulVB的回答):

if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1) {
    var showPopup = false;
    window.onbeforeunload = function () {
        if (showPopup) {
            return 'You must use the Cancel button to close the Print Preview window.'n';
        } else {
            showPopup = true;
        }
    }
    window.print();
    window.close();
} else {
    window.print();
    window.close();
}

我正在讨论是否也可以通过Chrome版本进行过滤。。。

运行此代码将打开谷歌打印服务弹出窗口。

function openPrint(x) {
   if (x > 0) { 
       openPrint(--x); print(x); openPrint(--x);
   }
}

请在控制台上试用,其中x是整数。

openPrint(1);   // Will open Chrome Print Popup Once
openPrint(2);   // Will open Chrome Print Popup Twice after 1st close and so on

感谢

好吧,这就是对我有效的方法!我的左Nav上有一个按钮。如果单击它,它将打开一个窗口,该窗口将加载一个文档。加载文档后,我想打印文档,然后立即关闭弹出窗口。

contentDiv.focus();
contentDiv.contentWindow.print();
contentDiv.contentWindow.onfocus = function() {
    window.close();
};

为什么这样做
好吧,打印完成后,您将onfocus事件设置为关闭窗口。打印弹出窗口将加载得如此之快,以至于在您1)打印2)取消打印之前,无法触发对焦事件。一旦你重新聚焦在窗口上,窗口就会关闭!
我希望这对你有效

Chrome打印通常是一个扩展页面,所以在你现有的页面中没有dom附件。您可以使用命令行api(window.print())触发打印命令,但由于选择打印选项、打印机器、计数等原因,他们没有提供关闭命令的api

function printpost() {
  if (window.print()) {
    return false;
  } else {
    location.reload();
  }
}

我可以确认我在使用Chrome版本35的Windows 7上也有同样的错误,但我分享了我的部分解决方案,即在Chrome上打开一个新选项卡并显示一个对话框。

对于其他浏览器,当用户单击"取消"时,会自动关闭新的打印窗口。

//Chrome's versions > 34 is some bug who stop all javascript when is show a prints preview
//http://stackoverflow.com/questions/23071291/javascript-window-print-in-chrome-closing-new-window-or-tab-instead-of-cancel
if(navigator.userAgent.toLowerCase().indexOf('chrome') > -1) {
    var popupWin = window.open();
    popupWin.window.focus();
    popupWin.document.write('<!DOCTYPE html><html><head>' +
        '<link rel="stylesheet" type="text/css" href="style.css" />' +
        '</head><body onload="window.print()"><div class="reward-body">' + printContents + '</div></html>');
    popupWin.onbeforeunload = function (event) {
        return 'Please use the cancel button on the left side of the print preview to close this window.'n';
    };
}else {
    var popupWin = window.open('', '_blank', 'width=600,height=600,scrollbars=no,menubar=no,toolbar=no,location=no,status=no,titlebar=no');
    popupWin.document.write('<!DOCTYPE html><html><head>' +
        '<link rel="stylesheet" type="text/css" href="style.css" />' +
        '</head><body onload="window.print()"><div class="reward-body">' + printContents + '</div>' +
        '<script>setTimeout(function(){ window.parent.focus(); window.close() }, 100)</script></html>');
}
popupWin.document.close();

我制作了一些类似的页面(经典的asp…)

我的方法是直接在弹出窗口上使用Q promise。

例如,我的问题是我想打印的弹出窗口关闭得太快了。。。并且打印预览是空的,我这样解决:

来电者:

var popup = window.open("index.asp","popupwindow","width=800,height=500,left=200,top=5,scrollbars,toolbar=0,resizable");

弹出(在页面末尾):

<script src="/Scripts/jquery-1.9.1.min.js"></script>
<script src="/Scripts/q.min.js"></script>
<script type="text/javascript">
    Q(window.print()).then(function () {window.close();});
</script>

我认为你的"父锁"可以用类似的方法解决

我会试试:

var w = whatever;
Q(
  // fill your popup
).then(function () {
 w.print();
}).then(function () {
 w.close();
}); 

这使得"打印"answers"关闭"异步。。。因此父级将立即"解锁"