[英]Print function only works after second click
我有這個功能來打印DIV。
每當頁面加載並點擊我的“打印”鏈接時,顯示DIV沒有CSS打印。
如果我關閉Chrome的打印可視化頁面並再次單擊“打印”鏈接,則DIV已應用CSS。
有什么想法嗎?
function printDiv(divId) {
var printDivCSSpre =
'<link href="/static/assets/vendor/sb-admin-2-1.0.7/bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">' +
'<link href="/static/assets/vendor/sb-admin-2-1.0.7/dist/css/sb-admin-2.css" rel="stylesheet">' +
'<div style="width:1000px; padding-right:20px;">';
var printDivCSSpost = '</div>';
$('body').append('<iframe id="print_frame" name="print_frame" width="0" height="0" frameborder="0" src="about:blank"></iframe>');
$("link").clone().appendTo($("#print_frame").contents().find("head"));
window.frames["print_frame"].document.body.innerHTML =
printDivCSSpre + document.getElementById(divId).innerHTML + printDivCSSpost;
window.frames["print_frame"].window.focus();
var windowInstance = window.frames["print_frame"].window;
windowInstance.print();
}
<a id="print" href="#">
<i class="fa fa-print"></i> Print
</a>
<script>
$('#print').click(function () {
printDiv('report')
})
</script>
<div id="report" class="report">
<p># Generated Table#</p>
</div>
發生這種情況是因為當您調用printDiv()函數時,css也是使用內部HTML編寫的,在這種情況下,CSS在第一次單擊時不會應用,因為即使在DIV中不存在CSS,也會向元素編寫CSS。
根據需要工作的函數必須首先編寫DIV內容,然后應該應用CSS。 我會說在DIV的內容之后寫css或者在HTML頁面上加載並且只寫DIV內容。
希望有所幫助。
正如其他人提到的,如果沒有看到問題的工作示例很難看到你的問題,而只是從代碼中猜測:
print()
調用之前加載CSS。 print()
調用之前呈現CSS。 記住改變你的JS功能可能會有所幫助
function printDiv(divId) {
$("link").clone().appendTo($("#print_frame").contents().find("head"));
window.frames["print_frame"].document.body.innerHTML =
printDivCSSpre + document.getElementById(divId).innerHTML + printDivCSSpost;
window.frames["print_frame"].window.focus();
var windowInstance = window.frames["print_frame"].window;
setTimeout(function() {
windowInstance.print();
}, 0);
}
這個函數背后的想法是讓我們在窗口中添加更改HTML / CSS代碼后讓瀏覽器執行它的代碼 - 請參閱為什么setTimeout(fn,0)有時會有用?
警告:此方法未針對您的特定問題進行測試,並且它可能也不起作用,因為我們轉義/離開鼠標單擊調用堆棧,可能無法在用戶交互堆棧之外調用print()
方法。
更新:在查看發布的jsfiddle后 - 我的假設是正確的,瀏覽器需要一些時間來加載和渲染CSS,這就是為什么在更改iframe內容之后立即調用print()
不會產生所需的結果。 有3.5種方法可以解決這個問題:
iframe
元素的事件和它的孩子 試試這個吧。 問題主要是因為在啟動打印命令時css尚未應用於頁面。 setTimeout
是解決它的一種方法,正如其他人提到的那樣,但實際上無法預測你需要多少延遲。 在觸發print語句之前,緩慢的Internet連接需要很長的延遲。 但是,以下代碼僅在將css正確應用於iframe后觸發打印事件。
$('#print').click(function () {
if($("#print_frame").length == 0) {
$('#report').after('<iframe id="print_frame" name="print_frame" width="0" height="0" frameborder="0" src="about:blank"></iframe>');
}
var $head = $("#print_frame").contents().find("head");
// for now for ease I will just empty head
// ideally you would want to check if this is not empty
// append css only if empty
$head.empty();
$.ajax({
url : "https://dl.dropboxusercontent.com/u/7760475/reports.css",
dataType: "text",
success : function (reports) {
// grab css and apply its content to the iframe document
$head.append('<style>'+reports+'</style>');
$.ajax({
url : "https://dl.dropboxusercontent.com/u/7760475/bootstrap.css",
dataType: "text",
success : function (bootstrap) {
// grab another css and apply its content to the iframe document
// there may be better ways to load both css files at once but this works fine too
$head.append('<style>'+bootstrap+'</style>');
// css has been applied
// clone your div and print
var $body = $("#print_frame").contents().find('body');
// empty for ease
// but later append content only if empty
$body.empty();
$("#report").clone().appendTo($body);
$('#print_frame').get(0).contentWindow.print();
}
});
}
});
});
正如其他人提到的,這里的問題是使用的CSS文件是外部資源,瀏覽器需要時間下載並在本地緩存它。 一旦它被緩存,它將更快地服務,這就是為什么它從第二次點擊工作正常。
正如Anton所說,setTimeout是關鍵所在! 您可能會增加超時秒數以使其工作。 我嘗試將它設置為500毫秒,這是有效的,
setTimeout(function(){windowInstance.print();},500);
請改用內聯CSS。 原因:如果我們打印或保存為PDF,如果無法獲取外部css文件,那么我們必須使用內聯css。 編輯您的文件請參閱:jsfiddle.net/ytzcwykz/18/
每件事都是對的,只需改變順序即可。 在第一次單擊時,它在瀏覽器調試器中沒有在sources部分顯示'print_frame',而在第二次單擊時它(我使用chrome devtool)。
因此在onload期間使用css屬性加載到內存框架中:
var windowInstance;
$(function(){
$('body').append('<iframe id="print_frame" name="print_frame" width="0" height="0" frameborder="0" src="about:blank"></iframe>');
$("link").clone().appendTo($("#print_frame").contents().find("head"));
windowInstance = window.frames["print_frame"].window;
});
和onClick只是附加html
$('#print').click(function () {
var divId = 'report';
var printDivCSSpre ='<div id="printReportDiv" style="width:1000px; padding-right:20px;">';
var printDivCSSpost = '</div>';
window.frames["print_frame"].document.body.innerHTML = printDivCSSpre + document.getElementById(divId).innerHTML + printDivCSSpost;
window.frames["print_frame"].window.focus();
windowInstance.print();
});
更新了jsfiddle
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.