簡體   English   中英

打印功能僅在第二次單擊后有效

[英]Print function only works after second click

我有這個功能來打印DIV。
每當頁面加載並點擊我的“打印”鏈接時,顯示DIV沒有CSS打印。
如果我關閉Chrome的打印可視化頁面並再次單擊“打印”鏈接,則DIV已應用CSS。

有什么想法嗎?

使用Javascript

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();
}

HTML

<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>

首先點擊:

http://imgur.com/a/Go81Y

關閉打印預覽頁面並再次單擊打印

http://imgur.com/a/SCxJF

發生這種情況是因為當您調用printDiv()函數時,css也是使用內部HTML編寫的,在這種情況下,CSS在第一次單擊時不會應用,因為即使在DIV中不存在CSS,也會向元素編寫CSS。

根據需要工作的函數必須首先編寫DIV內容,然后應該應用CSS。 我會說在DIV的內容之后寫css或者在HTML頁面上加載並且只寫DIV內容。

希望有所幫助。

正如其他人提到的,如果沒有看到問題的工作示例很難看到你的問題,而只是從代碼中猜測:

  1. 瀏覽器無法在print()調用之前加載CSS。
  2. 瀏覽器無法在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種方法可以解決這個問題:

  1. 使用事件來標識iframe文檔和窗口何時完成加載和渲染。 我嘗試了兩種方法,到目前為止都失敗了,需要更仔細地閱讀文檔,了解文檔和窗口在加載過程中的時間:
    • 我們可以從iframe外部做到這一點,即聽iframe元素的事件和它的孩子
    • 我們可以從iframe內部做到這一點,即添加一些小的javascript片段,里面會在加載完成后向父窗口發送一條消息。
  2. 考慮將打印結果形成不同,打印樣式表怎么樣? 即添加一個帶有打印媒體查詢的樣式表到父文檔,並在其上調用print?
  3. 考慮形成一個已加載並准備打印的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM