qzindustries / qz-print

Free browser applet for sending documents and raw commands to a printer.
Other
49 stars 4 forks source link

Setting default printer in list of available printers #50

Closed dwwheeler closed 9 years ago

dwwheeler commented 9 years ago

Can anyone tell me how I can get the available printers and also the default printer? I can do one or the other but when I try to do both neither works....well, at least the part to get the list of printers doesn't work. Here is my code to get the list of printers, which works fine on it's own:

        qz.findPrinter('\\{bogus_printer\\}');

        window['qzDoneFinding'] = function() {
            // Get the CSV listing of attached printers
            var printers = qz.getPrinters().split(',');

            var printerList = document.getElementById('printerList');
            for (i in printers) {
                var selected = false;
                var newPrinterOption = new Option(printers[i], i, selected, selected);
                printerList.options[printerList.options.length] = newPrinterOption;
            }

            // Remove reference to this function
            window['qzDoneFinding'] = null;
        };

However, if I add qz.findPrinter() to get the default printer, the code above no longer works.(the qzDoneFinding code doesn't execute). I've tried calling findPrinter() from inside and outside that funciton but it doesn't seem to matter where I call findPrinter(). It always breaks the code to get the list of printers.

Thanks, Dave

tresf commented 9 years ago

The default printer button fires qzDoneFinding() here:

http://demo.qzindustries.com/

What you are describing is likely qz.findPrinter() returning the default printer without populating the entire list of available printers. This is intended because iterating over the available printers can really slow down some machines.

I would recommend splitting off qzDoneFinding() into a dedicated function and just calling qz.findPrinter() twice (once with a dummy value to populate the list, again to snag default). To make sure it can recurse, you'll need to use some form of global variable to control subsequent findPrinter() call, etc.

-Tres

tresf commented 9 years ago

On a side note, qz.getPrinters() should probably be enhanced to support a JSON response message and flag the default printer as default.

dwwheeler commented 9 years ago

Thanks so much for the quick reply!

OK, so I started over from scratch by copying the javascript code from the http://demo.qzindustries.com/ page and made the following modifications:

deployQZ(); //this is the existing  call at the top of the javascript code.

//My added code....
qz.findPrinter();
qz.findPrinter('\\{bogus_printer\\}');

function qzDoneFinding() {
    // Get the CSV listing of attached printers
    var printers = qz.getPrinters().split(',');
    alert("printers: " + printers);

    var defaultPrinter = qz.getPrinter();
    alert(defaultPrinter !== null ? 'Default printer found: "' + defaultPrinter + '"':
        'Default printer ' + 'not found');
}

//...end of my added code

When I run this code I get the alert for the list of printers which shows all of my installed printers. I then get the second alert for the default printer which displays "Default printer not found". this doesn't make sense to me as it appears the qzDoneFinding is getting called on the second findPrinter call only (with the bogus printer name as a parameter).

Note: I did have to modify deployQZ for my own environment: function deployQZ() { var attributes = {id: "qz", code:'qz.PrintApplet.class', archive:'qz-print/qz-print.jar', width:1, height:1}; var parameters = {jnlp_href: 'qz-print/qz-print_jnlp.jnlp', cache_option:'plugin', disable_logging:'false', initial_focus:'false'}; if (deployJava.versionCheck("1.7+") == true) {} else if (deployJava.versionCheck("1.6+") == true) { delete parameters['jnlp_href']; } deployJava.runApplet(attributes, parameters, '1.5'); }

I don't have any previous experience with applets and I'm having a hard time understanding how this whole thing works, so you may have to "dum it down" for me :(

Thanks, Dave

tresf commented 9 years ago

@dwwheeler,

What you are experiencing is just a race condition, not much to do with applets really. Our software doesn't yet queue requests, so you can't call qz.findPrinter() twice in succession.

Instead you need to use a variable to distinguish when the finding is done so you can call it again.

var defaultPrinter = null;

function qzReady() {
   window['qz'] = document.getElementById('qz');
   qz.findPrinter(); // Get default printer
}

function qzDoneFinding() {
   if (defaultPrinter == null) {
      // First pass, stash the default printer name (if there is one)
      defaultPrinter = qz.getPrinter() != null ? qz.getPrinter() : "<NOT SPECIFIED>";
      qz.findPrinter("BOGUS_SEARCH_FOR_FINDING_ALL");  // Yes, we kind of recurse on ourselves with this line
   } else {
      // Second pass, process the full printer listing
      alert("Found all printers: \n\n" + qz.getPrinters());
      alert("Default printer is: \n\n" + defaultPrinter);
   }
}
dwwheeler commented 9 years ago

Thanks for the hint. With some additional modifications to your code I have my drop-down now populating with the list of printers and the selected option is set to the default printer.

However, now when I send my data to print I'm getting the error: "qz.PrintRaw.print() failed".

To print my data I'm doing the following:

qz.append("<\r\nJONES\r\nFLOYD J\r\n000-00-0000\r\nO NEG\r\nNone>\r\n\r\n<\r\nSMITH\r\nTIMOTHY H\r\n111-22-3333\r\nO POS\r\nNone>\r\n\r\n<\r\nAnderson\r\nMelissa S\r\n333-55-6666\r\nO POS\r\nNone>");

qz.print();

Note: the string to print is actually being passed in as a variable and I'm passing that variable to the print() function.

How do I go about debugging the failed qz.PrintRaw.print() call? I've tried the put a try/catch block around the qz.print() call but that doesn't work.

Thanks, Dave

tresf commented 9 years ago

@dwwheeler usually the Java Console has a hint as to where the problem is. This can be enabled via the Advanced Settings in the Java Control Panel, AKA "Configure Java".

-Tres

dwwheeler commented 9 years ago

According to my Java console I'm getting a null pointer exception at line 206 of PrintRaw:

public boolean print(byte[] data) throws IOException, PrintException, InterruptedException, UnsupportedEncodingException { if (this.ps.get() == null) throw new NullPrintServiceException("qz.PrintRaw.print() failed."); //this is line 206 ...

Any suggestions?

Thanks, Dave

tresf commented 9 years ago

Can you send the whole log please? Feel free to remove any proprietary information from it.

tresf commented 9 years ago

Furthermore, make sure to send the data after the second findPrinter() pass and after you've selected a printer by index using qz.setPrinter(index)

tresf commented 9 years ago

You may ask "Why do I need to set the printer?" Because qz.findPrinter() usually sets it for us but we're passing in a bogus value when searching. You may choose to get the full list first, then the default printer second so that you don't need to set by index when the default printer is selected, although you'll need to set by index if its changed, so you might as well do it every time.

BTW, qz.setPrinter(index) is synchronous. You don't need to wait for a callback like you do with the findPrinter function.

dwwheeler commented 9 years ago

Tres, not setting the printer index was the problem. After you clued me in on that I realized that I was setting then printer index when the selected printer was changed but I wasn't setting it on the initial load of the options. So, I was able to print successfully only if I changed the selected printer before I tried to print. Once I set the printer index on page load, I was able to print using the default printer selected on page load.

Thanks a million for all your help on this!!!!!

tresf commented 9 years ago

:+1: