2
votes

I'm trying to print text only from a web-application to a thermal printer. Ideally, this functionality will be in a SharePoint Online website for print receipts.

I used window.print and tested in Microsoft Edge and Internet Explorer (IE9+) and the printing of a selected text works.

In Google Chrome, however, once pressed the "print" button available in the printing preview, the thermal printer only shows the blank paper.


The following source code is just a sample about how we print the text "in a new window"; but, as I saido, in Google Chrome there's not printed.

function printThisDocument() {
    try {           
        var mywindow = window.open('', 'my div', 'height=600,width=1000');
        mywindow.document.write('<html moznomarginboxes mozdisallowselectionprint><head><title>Sticker #1</title>');
        mywindow.document.write('</head><body>');
        mywindow.document.write(document.getElementById('divHidden').innerHTML.trim());
        mywindow.document.write('</body></html>');
        mywindow.document.close(); // necessary for IE >= 10
        mywindow.focus(); // necessary for IE >= 10
        setTimeout(function(){ mywindow.print(); mywindow.close(); }, 500);
    } catch (ex) {
        alert('An error ocurred. Try again.');
        console.log(ex);
    }
}

I selected various paper size in the printing preview in Chrome, but only with "Letter" peper size, the thermal printer "prints-actually, uses paper, but not printing results shows".

If I selected other paper sizes, the thermal printer does not use any paper at all.

This situation happens with any highlighted text (you can try select a text, right click and select "Print").

Chrome prints text as graphics, or at least on all the web sites I tried. It uses line drawing to draw the text rather than printing actual characters

Source

And in this bug report:

[...] unfortunately its not possible due to the way chrome prints :( chrome cant print plain text [...]

So, I'm running without ideas.

¿Is there a cause/motive about why Chrome cannot print generic text-only?

What I need to archieve is print generic text-only from a SharePoint Online website, using a thermal printer or a sticker machine printer.

I checked another answer about javascipt cannot interact with driver and another server objects, but I also check about java applets, but I'm not sure about how applets works and if this is the only solution - I though applets are outdated.

1

1 Answers

3
votes

I ended by using QZ Tray 2.0.4 free version.

Adapting the source code available in his demo website I did print stickers using the browser1.

NOTE: If you want use this code, you have to download and install in your computer "or your client's computer" QZ Tray 2.0.4 and modify the source code provided here according to your purposes. You might also check the official documentation. Also, QZ Tray 2.0.4 must be running and the user must accept that QZ Tray 2.0.4 connects to the asigned localhost for check the printer. In this case, I use findDefaultPrinter(true); function for get the default printer.

<!-- Required scripts-->
<script type="text/javascript" src="/js/dependencies/rsvp-3.1.0.min.js"></script>
<script type="text/javascript" src="/js/dependencies/sha-256.min.js"></script>
<script type="text/javascript" src="/js/qz-tray.js"></script>

<script type="text/javascript">

    /// This is the function I use in the "onclick" attribute.
    function printStuff() {

        var config = getUpdatedConfig();

        var data = ['Raw Data\n', 'More Raw Data\n', 'Even More Raw Data\n'];

        // Print.
        qz.print(config, data).catch(function(e) { console.error(e); });
    }

    /// Authentication setup ///
    qz.security.setCertificatePromise(function(resolve, reject) {
        //Preferred method - from server
        //$.ajax("assets/signing/digital-certificate.txt").then(resolve, reject);

        //Alternate method 1 - anonymous
        //resolve();

        //Alternate method 2 - direct
        resolve("-----BEGIN CERTIFICATE-----\n" +
                "MIIFAzCCAuugAwIBAgICEAIwDQYJKoZIhvcNAQEFBQAwgZgxCzAJBgNVBAYTAlVT\n" +
                "MQswCQYDVQQIDAJOWTEbMBkGA1UECgwSUVogSW5kdXN0cmllcywgTExDMRswGQYD\n" +
                "VQQLDBJRWiBJbmR1c3RyaWVzLCBMTEMxGTAXBgNVBAMMEHF6aW5kdXN0cmllcy5j\n" +
                "b20xJzAlBgkqhkiG9w0BCQEWGHN1cHBvcnRAcXppbmR1c3RyaWVzLmNvbTAeFw0x\n" +
                "NTAzMTkwMjM4NDVaFw0yNTAzMTkwMjM4NDVaMHMxCzAJBgNVBAYTAkFBMRMwEQYD\n" +
                "VQQIDApTb21lIFN0YXRlMQ0wCwYDVQQKDAREZW1vMQ0wCwYDVQQLDAREZW1vMRIw\n" +
                "EAYDVQQDDAlsb2NhbGhvc3QxHTAbBgkqhkiG9w0BCQEWDnJvb3RAbG9jYWxob3N0\n" +
                "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFzbBDRTDHHmlSVQLqjY\n" +
                "aoGax7ql3XgRGdhZlNEJPZDs5482ty34J4sI2ZK2yC8YkZ/x+WCSveUgDQIVJ8oK\n" +
                "D4jtAPxqHnfSr9RAbvB1GQoiYLxhfxEp/+zfB9dBKDTRZR2nJm/mMsavY2DnSzLp\n" +
                "t7PJOjt3BdtISRtGMRsWmRHRfy882msBxsYug22odnT1OdaJQ54bWJT5iJnceBV2\n" +
                "1oOqWSg5hU1MupZRxxHbzI61EpTLlxXJQ7YNSwwiDzjaxGrufxc4eZnzGQ1A8h1u\n" +
                "jTaG84S1MWvG7BfcPLW+sya+PkrQWMOCIgXrQnAsUgqQrgxQ8Ocq3G4X9UvBy5VR\n" +
                "CwIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdl\n" +
                "bmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUpG420UhvfwAFMr+8vf3pJunQ\n" +
                "gH4wHwYDVR0jBBgwFoAUkKZQt4TUuepf8gWEE3hF6Kl1VFwwDQYJKoZIhvcNAQEF\n" +
                "BQADggIBAFXr6G1g7yYVHg6uGfh1nK2jhpKBAOA+OtZQLNHYlBgoAuRRNWdE9/v4\n" +
                "J/3Jeid2DAyihm2j92qsQJXkyxBgdTLG+ncILlRElXvG7IrOh3tq/TttdzLcMjaR\n" +
                "8w/AkVDLNL0z35shNXih2F9JlbNRGqbVhC7qZl+V1BITfx6mGc4ayke7C9Hm57X0\n" +
                "ak/NerAC/QXNs/bF17b+zsUt2ja5NVS8dDSC4JAkM1dD64Y26leYbPybB+FgOxFu\n" +
                "wou9gFxzwbdGLCGboi0lNLjEysHJBi90KjPUETbzMmoilHNJXw7egIo8yS5eq8RH\n" +
                "i2lS0GsQjYFMvplNVMATDXUPm9MKpCbZ7IlJ5eekhWqvErddcHbzCuUBkDZ7wX/j\n" +
                "unk/3DyXdTsSGuZk3/fLEsc4/YTujpAjVXiA1LCooQJ7SmNOpUa66TPz9O7Ufkng\n" +
                "+CoTSACmnlHdP7U9WLr5TYnmL9eoHwtb0hwENe1oFC5zClJoSX/7DRexSJfB7YBf\n" +
                "vn6JA2xy4C6PqximyCPisErNp85GUcZfo33Np1aywFv9H+a83rSUcV6kpE/jAZio\n" +
                "5qLpgIOisArj1HTM6goDWzKhLiR/AeG3IJvgbpr9Gr7uZmfFyQzUjvkJ9cybZRd+\n" +
                "G8azmpBBotmKsbtbAU/I/LVk8saeXznshOVVpDRYtVnjZeAneso7\n" +
                "-----END CERTIFICATE-----\n" +
                "--START INTERMEDIATE CERT--\n" +
                "-----BEGIN CERTIFICATE-----\n" +
                "MIIFEjCCA/qgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgawxCzAJBgNVBAYTAlVT\n" +
                "MQswCQYDVQQIDAJOWTESMBAGA1UEBwwJQ2FuYXN0b3RhMRswGQYDVQQKDBJRWiBJ\n" +
                "bmR1c3RyaWVzLCBMTEMxGzAZBgNVBAsMElFaIEluZHVzdHJpZXMsIExMQzEZMBcG\n" +
                "A1UEAwwQcXppbmR1c3RyaWVzLmNvbTEnMCUGCSqGSIb3DQEJARYYc3VwcG9ydEBx\n" +
                "emluZHVzdHJpZXMuY29tMB4XDTE1MDMwMjAwNTAxOFoXDTM1MDMwMjAwNTAxOFow\n" +
                "gZgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJOWTEbMBkGA1UECgwSUVogSW5kdXN0\n" +
                "cmllcywgTExDMRswGQYDVQQLDBJRWiBJbmR1c3RyaWVzLCBMTEMxGTAXBgNVBAMM\n" +
                "EHF6aW5kdXN0cmllcy5jb20xJzAlBgkqhkiG9w0BCQEWGHN1cHBvcnRAcXppbmR1\n" +
                "c3RyaWVzLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTDgNLU\n" +
                "iohl/rQoZ2bTMHVEk1mA020LYhgfWjO0+GsLlbg5SvWVFWkv4ZgffuVRXLHrwz1H\n" +
                "YpMyo+Zh8ksJF9ssJWCwQGO5ciM6dmoryyB0VZHGY1blewdMuxieXP7Kr6XD3GRM\n" +
                "GAhEwTxjUzI3ksuRunX4IcnRXKYkg5pjs4nLEhXtIZWDLiXPUsyUAEq1U1qdL1AH\n" +
                "EtdK/L3zLATnhPB6ZiM+HzNG4aAPynSA38fpeeZ4R0tINMpFThwNgGUsxYKsP9kh\n" +
                "0gxGl8YHL6ZzC7BC8FXIB/0Wteng0+XLAVto56Pyxt7BdxtNVuVNNXgkCi9tMqVX\n" +
                "xOk3oIvODDt0UoQUZ/umUuoMuOLekYUpZVk4utCqXXlB4mVfS5/zWB6nVxFX8Io1\n" +
                "9FOiDLTwZVtBmzmeikzb6o1QLp9F2TAvlf8+DIGDOo0DpPQUtOUyLPCh5hBaDGFE\n" +
                "ZhE56qPCBiQIc4T2klWX/80C5NZnd/tJNxjyUyk7bjdDzhzT10CGRAsqxAnsjvMD\n" +
                "2KcMf3oXN4PNgyfpbfq2ipxJ1u777Gpbzyf0xoKwH9FYigmqfRH2N2pEdiYawKrX\n" +
                "6pyXzGM4cvQ5X1Yxf2x/+xdTLdVaLnZgwrdqwFYmDejGAldXlYDl3jbBHVM1v+uY\n" +
                "5ItGTjk+3vLrxmvGy5XFVG+8fF/xaVfo5TW5AgMBAAGjUDBOMB0GA1UdDgQWBBSQ\n" +
                "plC3hNS56l/yBYQTeEXoqXVUXDAfBgNVHSMEGDAWgBQDRcZNwPqOqQvagw9BpW0S\n" +
                "BkOpXjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAJIO8SiNr9jpLQ\n" +
                "eUsFUmbueoxyI5L+P5eV92ceVOJ2tAlBA13vzF1NWlpSlrMmQcVUE/K4D01qtr0k\n" +
                "gDs6LUHvj2XXLpyEogitbBgipkQpwCTJVfC9bWYBwEotC7Y8mVjjEV7uXAT71GKT\n" +
                "x8XlB9maf+BTZGgyoulA5pTYJ++7s/xX9gzSWCa+eXGcjguBtYYXaAjjAqFGRAvu\n" +
                "pz1yrDWcA6H94HeErJKUXBakS0Jm/V33JDuVXY+aZ8EQi2kV82aZbNdXll/R6iGw\n" +
                "2ur4rDErnHsiphBgZB71C5FD4cdfSONTsYxmPmyUb5T+KLUouxZ9B0Wh28ucc1Lp\n" +
                "rbO7BnjW\n" +
                "-----END CERTIFICATE-----\n");
    });

    qz.security.setSignaturePromise(function(toSign) {
        return function(resolve, reject) {
            //Preferred method - from server
            //$.ajax("/secure/url/for/sign-message?request=" + toSign).then(resolve, reject);

            //Alternate method - unsigned
            resolve();
        };
    });


    /// Connection ///
    function launchQZ() {
        if (!qz.websocket.isActive()) {
            window.location.assign("qz:launch");
            //Retry 5 times, pausing 1 second between each attempt
            startConnection({ retries: 5, delay: 1 });
        }
    }

    function startConnection(config) {
        if (!qz.websocket.isActive()) {
            qz.websocket.connect(config).then(function() {
                findDefaultPrinter(true); /* Instead of findVersion(); */
            }).catch(handleConnectionError);
        } else {
            displayAlert('An active connection with QZ already exists.');
        }
    }

    function endConnection() {
        if (qz.websocket.isActive()) {
            qz.websocket.disconnect().then(function() {
                alert('Desconectado');
            }).catch(handleConnectionError);
        } else {
            displayAlert('No active connection with QZ exists. Openinig a new one.');
            startConnection();
        }
    }

    // Recargar la página para iniciar la conexión.
    function restartConnection() {
        startConnection({ retries: 5, delay: 1 });
    }

    /// Detection ///
    function findDefaultPrinter(set) {
        qz.printers.getDefault().then(function(data) {
            displayAlert("La impresora (" + data + ") ha sido encontrada.\nAhora puede proceder a imprimir stickers.");
            if (set) { setPrinter(data); }
        }).catch(createConsoleLog);
    }

    /// Raw Printers ///
    function printEPL() {
        var config = getUpdatedConfig();

        /* Información de prueba. */
        var printData = [
            '\nN\n',
            'q609\n',
            'Q203,26\n',
            'B5,26,0,1A,3,7,152,B,"1234"\n',
            'A310,26,0,3,1,1,N,"SKU 00000 MFG 0000"\n',
            'A310,56,0,3,1,1,N,"QZ PRINT APPLET"\n',
            'A310,86,0,3,1,1,N,"TEST PRINT SUCCESSFUL"\n',
            'A310,116,0,3,1,1,N,"FROM SAMPLE.HTML"\n',
            'A310,146,0,3,1,1,N,"QZ.IO"\n',
            '\nP1,1\n'
        ];

        qz.print(config, printData).catch(createConsoleLog);
    }

    /// Page load ///
    $(document).ready(function() {
        window.readingWeight = false;       
        startConnection();      
        // ¡La conexión con la impresora se establece cuando la conexión sea exitosa!
        alert('============================================\n' +
              '              You're using QZ Tray software.\n' + 
              '============================================\n' +
              'For sticker printing, you mus install\n' +
              'QZ Tray 2.0.4\n\n' + 
              'QZ Tray 2.0.4 will detect the default printer.\n\n' +
              'Click on "Accept" and\n' +
              'Wait until your printer's name is shown.');
    });

    qz.websocket.setClosedCallbacks(function(evt) {
        console.log(evt);

        if (evt.reason) {
            displayAlert("Connection closed:" + evt.reason);
        }
    });

    qz.websocket.setErrorCallbacks(handleConnectionError);

    /// Helpers ///
    function handleConnectionError(err) {
        if (err.target != undefined) {
            if (err.target.readyState >= 2) { //if CLOSING or CLOSED
                createConsoleLog("Connection to QZ Tray was closed");
            } else {
                createConsoleLog("A connection error occurred, check log for details");
                console.error(err);
            }
        } else {
            createConsoleLog(err);
        }
    }

    function createConsoleLog(err) {
        console.error(err);
        displayAlert(err);
    }

    function displayAlert(msg, css) {
        alert(msg);
    }

    /// QZ Config ///
    var cfg = null;
    function getUpdatedConfig() {
        if (cfg == null) {
            cfg = qz.configs.create(null);
        }

        updateConfig();
        return cfg
    }

    // Los parámetros estarán como "undefined" ya que no existen en mi código final.
    function updateConfig() {
        var pxlSize = null;
        var pxlMargins = $("#pxlMargins").val(); // = undefined.
        var jobName = "Impresión Sticker";

        cfg.reconfigure({
            altPrinting: $("#rawAltPrinting").prop('checked'),
            encoding: $("#rawEncoding").val(),
            endOfDoc: $("#rawEndOfDoc").val(),
            perSpool: $("#rawPerSpool").val(),
            colorType: $("#pxlColorType").val(),
            copies: 1,
            density: $("#pxlDensity").val(),
            duplex: $("#pxlDuplex").prop('checked'),
            interpolation: $("#pxlInterpolation").val(),
            jobName: jobName,
            margins: pxlMargins,
            orientation: $("#pxlOrientation").val(),
            paperThickness: $("#pxlPaperThickness").val(),
            printerTray: $("#pxlPrinterTray").val(),
            rasterize: $("#pxlRasterize").prop('checked'),
            rotation: $("#pxlRotation").val(),
            scaleContent: $("#pxlScale").prop('checked'),
            size: pxlSize,
            units: $("input[name='pxlUnits']:checked").val()
        });
    }

    function setPrinter(printer) {
        var cf = getUpdatedConfig();
        cf.setPrinter(printer);
    }

</script>
<!--FIN-->

1 Test made in Google Chrome Version 60.0.3112.90 (Build oficial) (64 bits).