pau*_*590 6 html javascript printing safari
您好我在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;
};
Run Code Online (Sandbox Code Playgroud)
HTML的
<div id="print-section">
<div>Section to print<>
</div>
Run Code Online (Sandbox Code Playgroud)
正如 Matteo Conta 正确提到的,问题在于 Safari 的打印确认对话框不会停止 JS 代码执行流程以等待打印。
因此,我们真正想要的是检测打印操作何时结束,以便绝对安全地运行清理。
setTimeout
解决方案是一个很好的起点,但我想更可靠地解决问题,并提出了一个基于事件的解决方案,使用matchMedia
和onfocus
捕获打印完成(取消或完成)的确切时刻。
下面是我针对这个特定问题测试过的代码(ES5,iframe 打印)。
此外,我还在GitHub 上创建了一个 Gist,并演示了通用方法。希望它会有用。
$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;
};
Run Code Online (Sandbox Code Playgroud)
为了简洁起见,我将框架创建代码提取到一个简单的函数(appendFrame
)中,并省略了setTimeout
原始问题(行后frameDoc.document.close();
)中的调用。
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;
};
Run Code Online (Sandbox Code Playgroud)
灵感来自 MDN 文章:
经过一番调查,我找到了解决方案。
仅当您“取消”打印时,Safari 才会显示打印警告。然而,第二次空白打印的原因是您使用太快删除内容
document.body.removeChild(frame1)
Run Code Online (Sandbox Code Playgroud)
如果将等待时间从 500 毫秒增加到 5 秒,用户就有时间关闭警告弹出窗口并进行打印。
就我而言,我成功地在 Chrome/FF/Edge/Safari 上测试了这个 jQuery 插件,还在这个库中增加了删除超时https://github.com/DoersGuild/jQuery.print