您好我在Safari中遇到了一个奇怪的问题。我有一个按钮,当点击它打印html的内容。我的问题是,当第一次调用window.print()
时它很好,但是,在第二次点击它会显示一个弹出窗口说明:
'这个网页正在尝试打印。你想打印这个网页吗?
如果我在此对话框中单击“打印”,则没有任任何想法为什么会发生这种情况?先感谢您!
Javascript -
$scope.print = function() {
var contents = document.getElementById("print-section").outerHTML;
var frame1 = document.createElement('iframe');
frame1.name = "frame3";
frame1.style.position = "absolute";
frame1.style.top = "-1000000px";
document.body.appendChild(frame1);
var frameDoc = frame1.contentWindow ? frame1.contentWindow : frame1.contentDocument.document ? frame1.contentDocument.document : frame1.contentDocument;
frameDoc.document.open();
frameDoc.document.write('<html><head>'); // add some libraries for the new document
frameDoc.document.write('</head><body>');
frameDoc.document.write(contents);
frameDoc.document.write('</body></html>');
frameDoc.document.close();
setTimeout(function () {
window.frames["frame3"].focus();
window.frames["frame3"].print();
document.body.removeChild(frame1);
}, 500);
return false;
};
HTML的
<div id="print-section">
<div>Section to print<>
</div>
经过一番调查,我找到了解决方案。
仅当您“取消”打印时,Safari才会显示打印警告。但是,第二次空白打印的原因是您使用了太快的内容删除
document.body.removeChild(frame1)
如果将等待时间从500毫秒增加到5秒,则可以让用户有时间关闭警告弹出窗口并进行打印。
在我的情况下,我成功测试了Chrome / FF / Edge / Safari这个jQuery插件,在这个库中也增加了删除超时qazxsw poi
正如Matteo Conta正确提到的,问题是Safari的打印确认对话框不会阻止JS代码执行流程等待打印。 因此,我们真正想要的是检测打印操作的确切时间,以便绝对安全地运行清理。
https://github.com/DoersGuild/jQuery.print解决方案是一个很好的起点,但我想更可靠地解决问题,并提出了一个基于事件的解决方案,使用setTimeout
和matchMedia
来捕捉打印完成(取消或完成)的确切时刻。
下面是我为这个特定问题(ES5,iframe打印)测试过的代码。
此外,我已经使用通用方法创建了onfocus
。希望它会有用。
a Gist on GitHub
为简洁起见,我将框架创建代码提取为一个简单的函数($scope.print = function () {
var frame = appendFrame();
// Safari
if (!window.onafterprint) {
// emulate onbeforeprint/onafterprint events
var mediaQueryCallback = function (mql) {
if (!mql.matches && frame) {
document.body.removeChild(frame);
}
};
var mediaQueryList = window.frames[frame.name].matchMedia('print');
mediaQueryList.addListener(mediaQueryCallback);
// the code below will trigger a cleanup in case a user hits Cancel button
// in that Safari's new additional print confirmation dialog
window.frames[frame.name].focus();
window.frames[frame.name].onfocus = function () {
return mediaQueryCallback(mediaQueryList);
};
}
window.frames[frame.name].print();
return false;
};
),并从原始问题(在appendFrame
行之后)中省略了setTimeout
调用。
frameDoc.document.close();
受MDN文章的启发:
var appendFrame = function () {
var contents = document.getElementById("print-section").outerHTML;
var frame1 = document.createElement('iframe');
frame1.name = "frame3";
frame1.style.position = "absolute";
frame1.style.top = "-1000000px";
document.body.appendChild(frame1);
var frameDoc = frame1.contentWindow ? frame1.contentWindow : frame1.contentDocument.document ? frame1.contentDocument.document : frame1.contentDocument;
frameDoc.document.open();
frameDoc.document.write('<html><head>'); // add some libraries for the new document
frameDoc.document.write('</head><body>');
frameDoc.document.write(contents);
frameDoc.document.write('</body></html>');
frameDoc.document.close();
return frame1;
};