web-dev-qa-db-fra.com

Javascript window.print () en chrome, la fermeture d'une nouvelle fenêtre ou d'un nouvel onglet au lieu d'annuler l'impression laisse javascript bloqué dans la fenêtre mère

Dans l'application sur laquelle je travaille, il existe plusieurs endroits différents où un utilisateur peut imprimer. Dans tous ces cas, nous utilisons le même processus: ouvrir une nouvelle fenêtre (ou un nouvel onglet), écrire tout ce dont nous avons besoin pour imprimer sur le document de la nouvelle fenêtre, puis nous appellerons

    $(w.document).ready(function () {
        w.focus();
        w.print();
        w.close();
    });  

Le problème que je vois est que dans Chrome, si je ferme l'onglet ou la fenêtre ouverte pour l'aperçu avant impression au lieu de cliquer sur le bouton d'annulation, Chrome bloque toujours le javascript dans la fenêtre parente.

C'est similaire au problème décrit ici:

Google Chrome bloque les demandes ajax lorsque l'aperçu avant impression est ouvert dans la fenêtre enfant

Nous rencontrons également ce problème, mais je pense que cela découle de la manière dont nous mettons en œuvre l'impression dans une nouvelle fenêtre et du mode de fonctionnement de l'aperçu avant impression de Chrome. Dans IE et Firefox, la fenêtre d'impression affiche la boîte de dialogue modale et vous ne pouvez rien faire dans la fenêtre parent jusqu'à ce que la fenêtre d'impression soit fermée. De même, chrome bloque l'utilisation de la fenêtre parente jusqu'à ce que l'aperçu avant impression soit annulé. Cependant, je m'attendrais à ce que la fermeture de cet onglet ou de cette fenêtre fonctionne de la même manière que l'annulation de l'impression.
Quelqu'un d'autre at-il eu ce problème ou connaissait-il une bonne solution?

Je vous remercie!

46
umitelight

Il semble que le problème ait été résolu avec la dernière Chrome mise à jour ... J'utilise le Chrome Version 36.0.1964.4 dev-m.

J'étais trop limité pour empêcher l'utilisateur de fermer la fenêtre d'aperçu avant impression en procédant comme suit:

if(navigator.userAgent.toLowerCase().indexOf('chrome') > -1){   // Chrome Browser Detected?
    window.PPClose = false;                                     // Clear Close Flag
    window.onbeforeunload = function(){                         // Before Window Close Event
        if(window.PPClose === false){                           // Close not OK?
            return 'Leaving this page will block the parent window!\nPlease select "Stay on this Page option" and use the\nCancel button instead to close the Print Preview Window.\n';
        }
    }                   
    window.print();                                             // Print preview
    window.PPClose = true;                                      // Set Close Flag to OK.
}

L'avertissement ne s'affiche plus après la Chrome update.

21
Paul VB

Le problème est qu’il existe un dialogue d’impression dans le navigateur dans la fenêtre contextuelle. Si vous appelez window.close() immédiatement, le dialogue n'est pas vu par l'utilisateur. L'utilisateur doit cliquer sur "Imprimer" dans le dialogue. Ce n'est pas la même chose que sur d'autres navigateurs où la boîte de dialogue d'impression fait partie du système d'exploitation et bloque la window.close() jusqu'à son exclusion - sous Chrome, il fait partie de Chrome et non du système d'exploitation.

C'est le code que j'ai utilisé, dans une petite fenêtre contextuelle créée par la fenêtre parente:

var is_chrome = function () { return Boolean(window.chrome); }
window.onload = function() {
    if(is_chrome){
        /*
         * These 2 lines are here because as usual, for other browsers,
         * the window is a tiny 100x100 box that the user will barely see.
         * On Chrome, it needs to be big enough for the dialogue to be read
         * (NB, it also includes a page preview).
        */
        window.moveTo(0,0);
        window.resizeTo(640, 480);

        // This line causes the print dialogue to appear, as usual:
        window.print();

        /*
         * This setTimeout isn't fired until after .print() has finished
         * or the dialogue is closed/cancelled.
         * It doesn't need to be a big pause, 500ms seems OK.
        */
        setTimeout(function(){
            window.close();
        }, 500);
    } else {
        // For other browsers we can do things more briefly:
        window.print();
        window.close();
    }
}
5
Coder

Pour ceux d’entre vous qui ouvrent une nouvelle fenêtre d’impression, puis le ferment automatiquement lorsque l’utilisateur clique sur "Imprimer" ou "Annuler" sur l’aperçu avant impression de Chrome, j’ai utilisé ce qui suit: (grâce à l'aide de la réponse de PaulVB):

if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1) {
    var showPopup = false;
    window.onbeforeunload = function () {
        if (showPopup) {
            return 'You must use the Cancel button to close the Print Preview window.\n';
        } else {
            showPopup = true;
        }
    }
    window.print();
    window.close();
} else {
    window.print();
    window.close();
}

Je me demande si ce serait une bonne idée de filtrer également par la version de Chrome ...

1
Primalpat

L’impression Chrome étant généralement une page d’extension, il n’ya pas d’attachement de dom sur votre page existante. Vous pouvez déclencher la commande d'impression en utilisant la commande apis de la ligne de commande (window.print ()), mais ils n'ont pas fourni d'indication de fermeture pour la fermer, car ils peuvent choisir des options d'impression, imprimer une machine, compter, etc.

0
Venkatesh Nadar

OK voici ce qui a fonctionné pour moi! J'ai un bouton sur mon gauche Nav. Si vous cliquez dessus, une fenêtre s’ouvrira et cette fenêtre chargera un document. Après avoir chargé le document, je souhaite imprimer le document, puis ferme la fenêtre contextuelle immédiatement.

contentDiv.focus();
contentDiv.contentWindow.print();
contentDiv.contentWindow.onfocus = function() {
    window.close();
};

Pourquoi cela a-t-il fonctionné?
Après l’impression, vous définissez l’événement onfocus de manière à fermer la fenêtre. La fenêtre contextuelle d'impression se chargera si rapidement que l'événement onfocus n'aura aucune chance de se déclencher tant que vous 1) imprimez 2) annulez l'impression. Une fois que vous avez réactivé la fenêtre, celle-ci se ferme!
J'espère que ça marchera pour toi

0
AhmedGadir

Exécutez ce code. Il ouvrira la fenêtre contextuelle du service d'impression Google.

function openPrint(x) {

   if (x > 0) { 
       openPrint(--x); print(x); openPrint(--x);
   }

}

Essayez-le sur la console où x est un entier.

openPrint(1);   // Will open Chrome Print Popup Once
openPrint(2);   // Will open Chrome Print Popup Twice after 1st close and so on

Merci

0
Siddharth

Je peux confirmer que j'ai le même bogue sous Windows 7 en utilisant Chrome version 35 mais je partage ma solution partielle qui ouvre un nouvel onglet sur Chrome et en affichant un dialogue.

Pour les autres navigateurs, lorsque l'utilisateur clique sur Annuler, ferme automatiquement la nouvelle fenêtre d'impression.

//Chrome's versions > 34 is some bug who stop all javascript when is show a prints preview
//http://stackoverflow.com/questions/23071291/javascript-window-print-in-chrome-closing-new-window-or-tab-instead-of-cancel
if(navigator.userAgent.toLowerCase().indexOf('chrome') > -1) {
    var popupWin = window.open();
    popupWin.window.focus();
    popupWin.document.write('<!DOCTYPE html><html><head>' +
        '<link rel="stylesheet" type="text/css" href="style.css" />' +
        '</head><body onload="window.print()"><div class="reward-body">' + printContents + '</div></html>');
    popupWin.onbeforeunload = function (event) {
        return 'Please use the cancel button on the left side of the print preview to close this window.\n';
    };
}else {
    var popupWin = window.open('', '_blank', 'width=600,height=600,scrollbars=no,menubar=no,toolbar=no,location=no,status=no,titlebar=no');
    popupWin.document.write('<!DOCTYPE html><html><head>' +
        '<link rel="stylesheet" type="text/css" href="style.css" />' +
        '</head><body onload="window.print()"><div class="reward-body">' + printContents + '</div>' +
        '<script>setTimeout(function(){ window.parent.focus(); window.close() }, 100)</script></html>');
}
popupWin.document.close();
0
Eduardo Chavira

Utilisez ce code pour retourner et recharger la fenêtre en cours:

function printpost() {
  if (window.print()) {
    return false;
  } else {
    location.reload();
  }
}
0
karthikeyan ganesan

Si la fonction setTimeout ne fonctionne pas non plus pour vous, procédez comme suit:

//Create an iframe
iframe = $('body').append($('<iframe id="documentToPrint" name="documentToPrint" src="about:blank"/>'));
iframeElement = $('#documentToPrint')[0].contentWindow.document;

//Open the iframe
iframeElement.open();

//Write your content to the iframe
iframeElement.write($("yourContentId").html());

//This is the important bit.
//Wait for the iframe window to load, then print it.
$('#documentToPrint')[0].contentWindow.onload = function () {
    $('#print-document')[0].contentWindow.print();
    $('#print-document').remove();
};
iframeElement.close();
0
Daybreak