JavaScript: Send raw text to printer - no server requests/method calls, able to work offline, purely clientside
Asked Answered
M

5

15

My thorough research on the web provided me with a couple of ideas, but none of them seem to work correctly in my particular use case. Here is what I have:

1) Zebra printer, which uses ZPL as its printing language;

2) A string in javascript which consists of 3 ZPL forms for printing 3 labels.

Our system engineer has verified already, that the ZPL syntax is all correct. What I am trying to achieve is to send the string as plain text for the printer to accept it as ZPL instructions to print labels. The best I have come up with so far looks like this:

var mywindow = window.open('', 'Printing', 'width=800,height=600');
//mywindow.write("testDirectWrite"); // not working
mywindow.document.open('text/plain');
////mywindow.document.write('<html><head><title>Printing</title><meta charset="ISO-8859-1">');
///*optional stylesheet*/ //mywindow.document.write('<link rel="stylesheet" href="main.css" type="text/css" />');
////mywindow.document.write('</head><body>');
var theDiv = $(".test-printirane-po-usb");
var printContents = theDiv[0].innerText;
mywindow.document.write(printContents);
////mywindow.document.write('</body></html>');

//mywindow.document.close(); // necessary for IE >= 10
//mywindow.focus(); // necessary for IE >= 10

//mywindow.print();
//mywindow.close();

For now (testing purposes), theDiv is the container where i place the ZPL string. Basically, I understood, that the best solution is to open a new popup window, fill it with the ZPL string and call thePopupWindow.print(); The user then selects the zebra printer and hits 'Print'. The problem: it seems like the printer interprets what's being printed as an html page (because of the

<html><head></head><body>theZPLString comes here</body></html>

tags, that i see, when I inspect the popup in Chrome, for example) and prints the ZPL code as plain text, rather than interpret it and print a label. I suppose I need something like thePopupWindow.write() to avoid writing to the document property of the window, which obviously wraps the string in html code. In order to test it, I use the Generic/Text Only driver and save what's "printed" into a .txt file.

In Chrome I get an empty file.

In Mozilla, when I remove this line: mywindow.document.open('text/plain'); I get the ZPL as characters, one per line. When I add it, I get only a date and time, again one char per line.

In IE - I get this (with or without mywindow.document.open('text/plain');):

Page 1 o



    ^XA^PW400^LL37^





          12.4.2016

I found various solutions, but they involve using php, c#, even java and I don't want it to be server-side, as mentioned in the title. Any help will be appreciated. @forgivenson, thanks for the point. After reading yours, I saw the little 'x', that I can click to delete my comment, so I added the comment within the question. I missed something very important: the printer is connected via USB port!

Marinate answered 12/4, 2016 at 10:33 Comment(3)
FYI, you can edit your question to add that info.Schick
Interesting question. When I faced a similar issue, I had to create a signed Java applet whose only function was to send bytes to the printer's port. Another option would be to write a browser-specific extension. I doubt there's a way to send bytes directly to the printer using only javascript, due to security concerns.Boxer
You see, the main problem here is that the Zebra commands will only work if you can send the raw, unmodified bytes directly to the printer port; the browser won't allow you to do that, unfortunately. You will need some way to get such direct acess, one way would be through a browser extension, so you'd have less restricted access to the hardware; another option would be to use a Java applet or JNLP application to provide such an access.Boxer
S
21

When printing to a Zebra printer, everything before ^XA and after ^XZ is ignored. The html tags around the zpl don't interfere.

The only thing you must ensure is that you print RAW text to the printer.

Use the build in windows Generic / Text Only driver for your Zebra printer. Instead of the zebra driver.

  • The normal zebra driver: renders the print job to a bitmap
    • result: a slow printed image of your zpl code.
  • The text only driver: sends the zpl code straight to the printer
    • result: a fast printed sticker, from zpl rendered on the printer

Example on jsfiddle or on gist.run

function printZpl(zpl) {
  var printWindow = window.open();
  printWindow.document.open('text/plain')
  printWindow.document.write(zpl);
  printWindow.document.close();
  printWindow.focus();
  printWindow.print();
  printWindow.close();
}

Tested in

  • Edge
  • Internet Explorer
  • Firefox

Not working in:


Select the Generic / Text Only driver in your printer properties:

Zebra printer - Generic / Text Only driver

Spidery answered 10/5, 2016 at 11:23 Comment(6)
+1 Thank you for your helpful answer. Exactly as you said, we are now able to print labels using a Zebra printer and the Generic / Text Only driver in Internet Explorer and Firefox. Chrome does not print when we open the System Print Dialog (ctrl + shift + p) and select Generic / Text Only driver and pops up an error alert. Now we are having an issue related to encoding. All cyrillic characters are transformed into a '.' (dot) character. This is related to the Generic / Text Only driver, because even when I print sth from notepad in cyrillic, we get a number of dots. Any ideas on this?Marinate
Glad to hear that it worked for you. Take a look at the following answer, on how to escape encoding errors with the ^FH command: stackoverflow.com/a/13041688Spidery
Thank you for suggesting the ^FH command as well! I actually came across this exact same thread when looking for a solution to the encoding issue. In the ZPL docs from Zebra I found the ^CI command and trying with ^CI33 did the trick. I'm not sure where should I put it. I just inserted it before the fields (before the first ^FD in the ZPL).Marinate
@Lakerfield, should your answer work with EPL as well ? I'm with a need exactly as the one from this question and your answer was very helpful for me and indeed did the trick for ZPL. My problem is that I also need to support EPL and simply switching ZPL code for EPL code doesn't seem to work. Do you know if any change is necessary in order to be able to send EPL as well ? Thank you.Adorn
You can find the driver under the 'Generic' manufacturer list on the left side of the windows printer properties dialogEntomostracan
Just following up in the year 2024. This works fine in Chrome/Edge now. As long as you print to the Generic / Text Only Driver it works from the Browser.Outside
R
4

If you want to accomplish this consistently without involving the opening of popups or user prompts, you are going to need an application running on the client PC to act as mediator between your application's javascript and the client's printer.

One popular way of doing this is via a browser plugin (NPAPI). But this approach is quickly becoming obsolete as many browsers have begun to remove NPAPI support entirely (Chrome, Firefox).

Another approach is to develop a small application that runs on your client's PC which listens for websocket connections. Your web application will send the ZPL through a connection to the client's websocket server, which in turn will generate a print job.

A third approach - some printers have an internal IP address that can be sent raw ZPL. If you build your web application so that a user can configure this IP address, it would be an option to send the ZPL to that address. However, this won't work if your users are using printers that don't support this functionality.

Raman answered 13/4, 2016 at 2:29 Comment(0)
W
2

Following snippet worked for me on Firefox and IE11, with a little change to printer's properties.

I was using this printer emulator.

In Chrome I get error from emulator when printing from Chrome's Print Dialog. Using system dialog gives error about printing failure from Chrome. CTRL + SHIFT + P(shortcut to skip Chrome dialog) no error and nothing happens. All these errors may be related to emulator, but I don't have real printer to test it.

In Printer's Properties I set following options:

  • Begin Print Job : ${
  • End Print Job: }$

As you can see in script below ZPL code is wrapped in '${' and '}$'

<script type="text/javascript">
  function openWin() {
    var printWindow = window.open();
    printWindow.document.open('text/plain')
    printWindow.document.write('${^XA^FO50,100^BXN,10,200^FDYourTextHere^FS^XZ}$');
    printWindow.document.close();
    printWindow.focus();
    printWindow.print();
  }
</script>
<input type="button" value="Print code" onclick="openWin()" />

JSFiddle

Walters answered 12/4, 2016 at 22:8 Comment(2)
Thank you, but, unfortunately, it didn't work this time. I went to our service engineer and we both tested your solution. He set those Printer Properties for Begin & End Print Job. This time, we get the string '${^XA^FO50,100^BXN,10,200^FDYourTextHere^FS^XZ}$' printed, rather than a real label. Maybe, it has something to do with encoding of the new window, which holds the ZPL and where i call theWindow.print(); printWindow.document.open('text/plain') didn't help either. I see, that I need it as raw text, somehow.Marinate
Is it possible that you installed EPL drivers instead of ZPL?Manipur
P
2

Zebra created an application called (BROWSER PRINT) they released April 2016. It appears to be a local JAVA service that runs on your computer and exposes a pseudo rest api. They provide a javascript api to hide the details and simplify usage.

Currently supports (ZD500, ZD410, LP2824+, ZT230, ZT420, QLn320, GX420)

It allows you to select the printer if there are multiple. Also allows 2 way communication where you can ask the printer it's status and get the result. They recently added support for printers connected to Ethernet but do not support printers mapped via Windows UNC path.

https://www.zebra.com/us/en/products/software/barcode-printers/link-os/browser-print.html

Peng answered 30/1, 2017 at 22:51 Comment(0)
B
0

You see, the main problem here is that the Zebra commands will only work if you can send the raw, unmodified bytes directly to the printer port; the browser won't allow you to do that, unfortunately.

You will need some way to get such direct acess:

  • One way would be through a browser extension, so you'd have less restricted access to the hardware; you could do that through NPAPI, but Chrome does not support that, and both Mozilla and IE will cease supporting that really soon;; Chrome can allow direct access to the hardware through the Native Messaging API; Mozilla may support a similar solution really soon;
  • Another option would be to use a Java JNLP application to provide such an access, and it can be called from a browser.
Boxer answered 14/4, 2016 at 13:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.