您好我在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>
答案 0 :(得分:2)
经过一番调查后,我找到了解决方案。
Safari仅在您“取消”打印时显示打印警告。 但是,第二次空白打印的原因是您使用
删除了太快的内容document.body.removeChild(frame1)
如果您将等待时间从500毫秒增加到5秒,则可以让用户有时间关闭警告弹出并打印。
在我的情况下,我在Chrome / FF / Edge / Safari上成功测试了这个jQuery插件,在此库中还增加了删除超时https://github.com/DoersGuild/jQuery.print
答案 1 :(得分:1)
除此之外,使用上面提到的 jQuery Print 插件 Matteo Conta,我能够通过在新标签页中进行打印来在 Safari 中实现打印,没有 iframe、弹出对话框、空白打印或延迟。< /p>
我遇到的问题,就像很多人一样,是 Safari 在 iframe 中的后续打印出现问题,显示打印对话框,然后是空白打印。
目前我们使用 printThis JS 作为我们的打印插件并且已经实现了 3000 毫秒的延迟,但是这个新的更新 Big Sur 14.1 专门破坏了这个实现。 jQuery Print 插件不需要任何延迟,如果我们不再遇到 Safari 更新的问题,我们可能会弃用 printThis。
注意:即使使用 jQuery Print,如果您仍然选择在 iframe 内打印,您也会遇到相同的打印问题。
下面是我如何根据用户的浏览器实现打印的片段。希望这可以帮助任何仍在寻找解决方案的人!
var currentBrowser;
// Determine user browser
if ( navigator.userAgent.indexOf("Chrome") != -1 ) {
currentBrowser = "Google Chrome";
} else if ( navigator.userAgent.indexOf("Safari") != -1 ) {
currentBrowser = "Safari";
} else {
currentBrowser = "Others";
}
// Special Safari Treatment - Print New Window
if( currentBrowser === "Safari" ) {
/**
* jQuery Print JS
*
* Print receipts in new window with a deffered callback function.
*
* globalStyles - Will include style sheets from parent document
* iframe - Print in a new window, iframe = false
* deferred - Callback function
*/
$("#printDiv").print({
globalStyles : true,
iframe : false,
deferred: $.Deferred().done(function() {
// Callback
})
});
} else {
// Print iframe normally using printThis JS
$('#printDiv').printThis();
}
答案 2 :(得分:0)
正如Matteo Conta正确提到的那样,问题在于Safari的打印确认对话框不会停止JS代码执行流以等待打印。
因此,我们真正想要的是检测打印操作何时确切结束,以便绝对安全地进行清理。
setTimeout
解决方案是一个很好的起点,但是我想更可靠地解决该问题,并提出了一个基于事件的解决方案,该解决方案使用matchMedia
和onfocus
来捕捉确切的时刻打印完成时(取消或完成)。
下面是我针对此特定问题(ES5,iframe打印)测试过的代码。
另外,我已经用演示的通用方法创建了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();
行之后)。
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;
};
受MDN文章启发: