From d2dec6b99fcfc878cd2388847123a4468647bb9b Mon Sep 17 00:00:00 2001 From: phasefx Date: Thu, 20 May 2010 04:55:40 +0000 Subject: [PATCH] * I18N for print admin interface * custom/external print strategy (where you dictate an external command and feed it %receipt.txt% and/or %receipt.html%) * DOS LPT1 Print strategy preserved as a legacy option, but without serving double-duty with the external linux commands * label printing now honors plain text print strategies, but we're still stuck with system defaults for print dialogs * @hex attribute for generating control characters when using HTML in templates being rendered with plain text print strategies For example,

Hello World

will transform into form feed + Hello World if used with DOS LPT1 Print or with the %receipt.txt% macro for the Custom/External Print strategy.

Hello World

will yield Hello World + form feed. git-svn-id: svn://svn.open-ils.org/ILS/trunk@16461 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- Open-ILS/web/opac/locale/en-US/lang.dtd | 15 ++- .../chrome/content/util/browser.js | 22 +++- .../chrome/content/util/browser.xul | 5 +- .../staff_client/chrome/content/util/print.js | 107 ++++++++++++++---- .../chrome/content/util/rbrowser.xul | 5 +- .../staff_client/chrome/content/util/text.js | 10 ++ .../chrome/locale/en-US/offline.properties | 3 + .../server/admin/printer_settings.html | 36 ++++-- .../server/admin/printer_settings.js | 17 ++- .../staff_client/server/cat/spine_labels.js | 5 +- 10 files changed, 177 insertions(+), 48 deletions(-) diff --git a/Open-ILS/web/opac/locale/en-US/lang.dtd b/Open-ILS/web/opac/locale/en-US/lang.dtd index 745c4b5283..d12cfa8c85 100644 --- a/Open-ILS/web/opac/locale/en-US/lang.dtd +++ b/Open-ILS/web/opac/locale/en-US/lang.dtd @@ -3241,5 +3241,16 @@ - - + + + + + + + + + + + + + diff --git a/Open-ILS/xul/staff_client/chrome/content/util/browser.js b/Open-ILS/xul/staff_client/chrome/content/util/browser.js index 8a1179283c..aa16e6eaf7 100644 --- a/Open-ILS/xul/staff_client/chrome/content/util/browser.js +++ b/Open-ILS/xul/staff_client/chrome/content/util/browser.js @@ -21,7 +21,7 @@ util.browser.prototype = { obj.url = params['url']; obj.push_xulG = params['push_xulG']; - obj.alt_print = params['alt_print']; + obj.html_source = params['html_source']; obj.browser_id = params['browser_id']; obj.debug_label = params['debug_label']; obj.passthru_content_params = params['passthru_content_params']; @@ -46,12 +46,22 @@ util.browser.prototype = { 'cmd_print' : [ ['command'], function() { - netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); - if (obj.alt_print) { + try { + netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); + var content = obj.get_content(); JSAN.use('util.print'); var p = new util.print(); - p.NSPrint(obj.get_content(),false,{}); - } else { - obj.get_content().print(); + var print_params = {}; + if (obj.html_source) { + print_params.msg = obj.html_source; + } + JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.stash_retrieve(); + if (data.print_strategy == 'webBrowserPrint') { + // Override the print strategy temporarily in this context + print_params.print_strategy = 'window.print'; + } + p.NSPrint(content,false,print_params); + } catch(E) { + alert('browser.js, cmd_print exception: ' + E); } } ], diff --git a/Open-ILS/xul/staff_client/chrome/content/util/browser.xul b/Open-ILS/xul/staff_client/chrome/content/util/browser.xul index 5c27f4a537..1d02de5b75 100644 --- a/Open-ILS/xul/staff_client/chrome/content/util/browser.xul +++ b/Open-ILS/xul/staff_client/chrome/content/util/browser.xul @@ -51,13 +51,10 @@ var push_xulG = true; if (xul_param('no_xulG')) push_xulG = false; - var alt_print = false; - if (xul_param('alternate_print')) alt_print = true; - var p = { 'url' : url, 'push_xulG' : push_xulG, - 'alt_print' : alt_print, + 'html_source' : xul_param('html_source'), 'debug_label' : 'debug' }; if (typeof window.xulG == 'object' && typeof window.xulG.passthru_content_params == 'object') { diff --git a/Open-ILS/xul/staff_client/chrome/content/util/print.js b/Open-ILS/xul/staff_client/chrome/content/util/print.js index bf2d870914..15c515994b 100644 --- a/Open-ILS/xul/staff_client/chrome/content/util/print.js +++ b/Open-ILS/xul/staff_client/chrome/content/util/print.js @@ -11,6 +11,11 @@ util.print = function () { JSAN.use('util.functional'); JSAN.use('util.file'); + var prefs = Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces['nsIPrefBranch']); + var key = 'oils.printer.external.cmd'; + var has_key = prefs.prefHasUserValue(key); + this.oils_printer_external_cmd = has_key ? prefs.getCharPref(key) : ''; + return this; }; @@ -20,7 +25,9 @@ util.print.prototype = { try { var obj = this; obj.data.init({'via':'stash'}); if (!obj.data.last_print) { - alert('Nothing to re-print'); + alert( + document.getElementById('offlineStrings').getString('printing.nothing_to_reprint') + ); return; } var msg = obj.data.last_print.msg; @@ -31,9 +38,48 @@ util.print.prototype = { } }, + 'html2txt' : function(html) { + JSAN.use('util.text'); + //dump('html2txt, before:\n' + html + '\n'); + var lines = html.split(/\n/); + var new_lines = []; + for (var i = 0; i < lines.length; i++) { + var line = lines[i]; + if (line) { + // This undoes the util.text.preserve_string_in_html call that spine_label.js does + line = util.text.reverse_preserve_string_in_html(line); + // This looks for @hex attributes containing 2-digit hex codes, and converts them into real characters + line = line.replace(/(<.+?)hex=['"](.+?)['"](.*?>)/gi, function(str,p1,p2,p3,offset,s) { + var raw_chars = ''; + var hex_chars = p2.match(/[0-9,a-f,A-F][0-9,a-f,A-F]/g); + for (var j = 0; j < hex_chars.length; j++) { + raw_chars += String.fromCharCode( parseInt(hex_chars[j],16) ); + } + return p1 + p3 + raw_chars; + }); + line = line.replace(/.*?<\/head>/gi, ''); + line = line.replace(//gi,'\r\n'); + line = line.replace(//gi,''); + line = line.replace(//gi,''); + line = line.replace(//gi,'\r\n'); + line = line.replace(//gi,''); + line = line.replace(//gi,''); + line = line.replace(//gi,' * '); + line = line.replace(/<.+?>/gi,''); + if (line) { new_lines.push(line); } + } else { + new_lines.push(line); + } + } + var new_html = new_lines.join('\n'); + //dump('html2txt, after:\n' + new_html + '\nhtml2txt, done.\n'); + return new_html; + }, + 'simple' : function(msg,params) { try { if (!params) params = {}; + params.msg = msg; var obj = this; @@ -60,15 +106,18 @@ util.print.prototype = { switch(params.print_strategy || obj.data.print_strategy) { case 'dos.print': + params.dos_print = true; + case 'custom.print': /* FIXME - this it a kludge.. we're going to sidestep window-based html rendering for printing */ /* I'm using regexps to mangle the html receipt templates; it'd be nice to use xsl but the */ - /* templates aren't guaranteed to be valid xml */ + /* templates aren't guaranteed to be valid xml. The unadulterated msg is still preserved in */ + /* params */ if (content_type=='text/html') { - w = msg.replace(//gi,'\r\n').replace(//gi,'\r\n').replace(//gi,'\r\n').replace(//gi,'\r\n').replace(//gi,'\r\n').replace(//gi,'\r\n').replace(//gi,'\r\n * ').replace(/<.+?>/gi,''); + w = obj.html2txt(msg); } else { w = msg; } - if (! params.no_form_feed) { w = w + '\r\n\r\n\r\n\r\n\r\n\r\n\f'; } + if (! params.no_form_feed) { w = w + '\f'; } obj.NSPrint(w, silent, params); return; break; @@ -246,14 +295,24 @@ util.print.prototype = { if (params.print_strategy || obj.data.print_strategy) { +dump('params.print_strategy = ' + params.print_strategy + ' || obj.data.print_strategy = ' + obj.data.print_strategy + ' => ' + ( params.print_strategy || obj.data.print_strategy ) + '\n'); switch(params.print_strategy || obj.data.print_strategy) { case 'dos.print': + case 'custom.print': if (typeof w != 'string') { - netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); - w.getSelection().selectAllChildren(w.document.firstChild); - w = w.getSelection().toString(); + try { + var temp_w = params.msg || w.document.firstChild.innerHTML; + if (!params.msg) { params.msg = temp_w; } + if (typeof temp_w != 'string') { throw(temp_w); } + w = obj.html2txt(temp_w); + } catch(E) { + dump('util.print: Could not use w.document.firstChild.innerHTML with ' + w + ': ' + E + '\n'); + netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); + w.getSelection().selectAllChildren(w.document.firstChild); + w = w.getSelection().toString(); + } } - obj._NSPrint_dos_print(w,silent,params); + obj._NSPrint_custom_print(w,silent,params); break; case 'window.print': w.print(); @@ -279,28 +338,34 @@ util.print.prototype = { }, - '_NSPrint_dos_print' : function(w,silent,params) { + '_NSPrint_custom_print' : function(w,silent,params) { var obj = this; try { - /* OLD way: This is a kludge/workaround. webBrowserPrint doesn't always work. So we're going to let - the html window handle our receipt template rendering, and then force a selection of all - the text nodes and dump that to a file, for printing through a dos utility */ - - /* NEW way: we just pass in the text */ - var text = w; + var html = params.msg || w; - var file = new util.file('receipt.txt'); - file.write_content('truncate',text); - var path = file._file.path; - file.close(); + var txt_file = new util.file('receipt.txt'); + txt_file.write_content('truncate',text); + var text_path = '"' + txt_file._file.path + '"'; + txt_file.close(); + + var html_file = new util.file('receipt.html'); + html_file.write_content('truncate',html); + var html_path = '"' + html_file._file.path + '"'; + html_file.close(); + var cmd = params.dos_print ? + 'copy ' + text_path + ' lpt1 /b\n' + : obj.oils_printer_external_cmd.replace('%receipt.txt%',text_path).replace('%receipt.html%',html_path) + ; + file = new util.file('receipt.bat'); - file.write_content('truncate+exec','#!/bin/sh\ncopy "' + path + '" lpt1 /b\nlpr ' + path + '\n'); + file.write_content('truncate+exec',cmd); file.close(); file = new util.file('receipt.bat'); + dump('print exec: ' + cmd + '\n'); var process = Components.classes["@mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess); process.init(file._file); @@ -312,7 +377,7 @@ util.print.prototype = { } catch (e) { //alert('Probably not printing: ' + e); - this.error.sdump('D_ERROR','_NSPrint_dos_print PRINT EXCEPTION: ' + js2JSON(e) + '\n'); + this.error.sdump('D_ERROR','_NSPrint_custom_print PRINT EXCEPTION: ' + js2JSON(e) + '\n'); } }, diff --git a/Open-ILS/xul/staff_client/chrome/content/util/rbrowser.xul b/Open-ILS/xul/staff_client/chrome/content/util/rbrowser.xul index 31a3f1a7c1..18f4636ab6 100644 --- a/Open-ILS/xul/staff_client/chrome/content/util/rbrowser.xul +++ b/Open-ILS/xul/staff_client/chrome/content/util/rbrowser.xul @@ -54,13 +54,10 @@ var push_xulG = true; if (xul_param('no_xulG')) push_xulG = false; - var alt_print = false; - if (xul_param('alternate_print')) alt_print = true; - var p = { 'url' : url, 'push_xulG' : push_xulG, - 'alt_print' : alt_print, + 'html_source' : xul_param('html_source'), 'debug_label' : 'debug' } if (typeof window.xulG == 'object' && typeof window.xulG.passthru_content_params == 'object') { diff --git a/Open-ILS/xul/staff_client/chrome/content/util/text.js b/Open-ILS/xul/staff_client/chrome/content/util/text.js index 91f4c558b9..48819be62a 100644 --- a/Open-ILS/xul/staff_client/chrome/content/util/text.js +++ b/Open-ILS/xul/staff_client/chrome/content/util/text.js @@ -35,4 +35,14 @@ util.text.preserve_string_in_html = function( text ) { return text; } +util.text.reverse_preserve_string_in_html = function( text ) { + text = text.replace(/&/g, '&'); + text = text.replace(/"/g, '"'); + text = text.replace(/'/g, "'"); + text = text.replace(/ /g, ' '); + text = text.replace(/</g, '<'); + text = text.replace(/>/g, '>'); + return text; +} + dump('exiting util/text.js\n'); diff --git a/Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties b/Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties index f592087a40..dd0401b5cf 100644 --- a/Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties +++ b/Open-ILS/xul/staff_client/chrome/locale/en-US/offline.properties @@ -269,3 +269,6 @@ staff.cat.opac.title_for_hold_transfer.destination_needed.label=Need to mark a r staff.cat.opac.title_for_hold_transfer.success.label=Holds transferred. staff.cat.opac.title_for_hold_transfer.failure.label=Holds not transferred. staff.cat.create_or_rebarcode_items=Create or Re-barcode Items +printing.nothing_to_reprint=Nothing to re-print +printing.prompt_for_external_print_cmd=Enter external print command and parameters (use %receipt.txt% or %receipt.html% as the file containing the print data. Those values will be substituted with the proper path.): +printing.print_strategy_saved=Print strategy (%1$s) saved to file system. diff --git a/Open-ILS/xul/staff_client/server/admin/printer_settings.html b/Open-ILS/xul/staff_client/server/admin/printer_settings.html index 783138ed33..bd7d228739 100644 --- a/Open-ILS/xul/staff_client/server/admin/printer_settings.html +++ b/Open-ILS/xul/staff_client/server/admin/printer_settings.html @@ -1,5 +1,16 @@ - + + +]> + + + + @@ -15,15 +26,24 @@ -

Normal Settings

+
+

&staff.printing.normal_settings.header;


- -
-

Advanced Settings

- - + +
+

&staff.printing.advanced_settings.header;

+ + +

- Warning: The alternate (DOS LPT1) print strategy will ignore the printer settings made in the "Normal Settings" section. In Windows, you must map your printer to the LPT1 port, under Start Menu -> Printers and Faxes -> your printer -> right-click, Properties -> Ports. Also, HTML styling such as different font weights and sizes will be lost when using the DOS LPT1 print. Data is sent to the printer as simple text in this case. +

+
&staff.printing.advanced.dos_print.warning.header;
+
&staff.printing.advanced.dos_print.warning.text;
+
&staff.printing.advanced.custom_print.warning.header;
+
&staff.printing.advanced.custom_print.warning.text;
+
&staff.printing.advanced.html_templates.warning.header;
+
&staff.printing.advanced.html_templates.warning.text;
+

diff --git a/Open-ILS/xul/staff_client/server/admin/printer_settings.js b/Open-ILS/xul/staff_client/server/admin/printer_settings.js index 7f4de9f4dd..45028a262d 100644 --- a/Open-ILS/xul/staff_client/server/admin/printer_settings.js +++ b/Open-ILS/xul/staff_client/server/admin/printer_settings.js @@ -11,6 +11,8 @@ function my_init() { JSAN.use('util.print'); g.print = new util.print(); + g.prefs = Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces['nsIPrefBranch']); + /* netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); g.PSSVC = Components.classes["@mozilla.org/gfx/printsettings-service;1"].getService(Components.interfaces.nsIPrintSettingsService); @@ -39,12 +41,25 @@ g.printer_settings = function() { g.set_print_strategy = function(which) { netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); + if (which == 'custom.print') { + var key = 'oils.printer.external.cmd'; + var has_key = g.prefs.prefHasUserValue(key); + var value = has_key ? g.prefs.getCharPref(key) : ''; + var cmd = window.prompt( + document.getElementById('offlineStrings').getString('printing.prompt_for_external_print_cmd'), + value + ); + if (!cmd) { return; } + g.prefs.setCharPref(key,cmd); + } JSAN.use('util.file'); var file = new util.file('print_strategy'); file.write_content( 'truncate', String( which ) ); file.close(); JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'}); data.print_strategy = which; data.stash('print_strategy'); - alert('Print strategy (' + which + ') saved to file system.'); + alert( + document.getElementById('offlineStrings').getFormattedString('printing.print_strategy_saved',[which]) + ); } g.save_settings = function() { g.print.save_settings(); } diff --git a/Open-ILS/xul/staff_client/server/cat/spine_labels.js b/Open-ILS/xul/staff_client/server/cat/spine_labels.js index ebe5b700e9..3dbf544ea2 100644 --- a/Open-ILS/xul/staff_client/server/cat/spine_labels.js +++ b/Open-ILS/xul/staff_client/server/cat/spine_labels.js @@ -263,7 +263,7 @@ } html += '\n'; } - html += '\n'; + html += '\n'; } } html += ''; @@ -274,7 +274,8 @@ 'tab_name' : $("catStrings").getString('staff.cat.spine_labels.preview.title') }, { - 'url' : 'data:text/html,'+html, + 'url' : 'data:text/html;charset=utf-8,'+window.escape(html), + 'html_source' : html, 'show_print_button' : 1, 'no_xulG' : 1 } -- 2.43.2