2 * egPrint : manage print templates, process templates, print content
5 angular.module('egCoreMod')
8 ['$q','$window','$timeout','$http','egHatch','egAuth','egIDL','egOrg','egEnv',
9 function($q , $window , $timeout , $http , egHatch , egAuth , egIDL , egOrg , egEnv) {
13 'circ.staff_client.receipt.alert_text',
14 'circ.staff_client.receipt.event_text',
15 'circ.staff_client.receipt.footer_text',
16 'circ.staff_client.receipt.header_text',
17 'circ.staff_client.receipt.notice_text'
22 service.template_base_path = 'share/print_templates/t_';
25 * context : 'default', 'receipt','label', etc.
26 * scope : data loaded into the template environment
27 * template : template name (e.g. 'checkout', 'transit_slip'
28 * content : content to print. If 'template' is set, content is
29 * derived from the template.
30 * content_type : 'text/html', 'text/plain', 'text/csv'
31 * show_dialog : boolean, if true, print dialog is shown. This setting
32 * only affects remote printers, since browser printers
33 * do not allow such control
35 service.print = function(args) {
36 if (!args) return $q.when();
39 // fetch the template, then proceed to printing
41 return service.getPrintTemplate(args.template)
42 .then(function(content) {
43 args.content = content;
44 if (!args.content_type) args.content_type = 'text/html';
45 service.getPrintTemplateContext(args.template)
46 .then(function(context) {
47 args.context = context;
48 return service.print_content(args);
54 return service.print_content(args);
57 // add commonly used attributes to the print scope
58 service.fleshPrintScope = function(scope) {
59 if (!scope) scope = {};
60 scope.today = new Date().toISOString();
63 scope.staff = egIDL.toHash(egAuth.user());
64 scope.current_location =
65 egIDL.toHash(egOrg.get(egAuth.user().ws_ou()));
68 return service.fetch_includes(scope);
71 // Retrieve org settings for receipt includes and add them
72 // to the print scope under scope.includes.<name>
73 service.fetch_includes = function(scope) {
74 // org settings for the workstation org are cached
75 // within egOrg. No need to cache them locally.
76 return egOrg.settings(service.include_settings).then(
80 angular.forEach(settings, function(val, key) {
81 // strip the settings prefix so you just have
82 // e.g. scope.includes.alert_text
83 scope.includes[key.split(/\./).pop()] = val;
89 service.last_print = {};
91 // Template has been fetched (or no template needed)
92 // Process the template and send the result off to the printer.
93 service.print_content = function(args) {
94 return service.fleshPrintScope(args.scope).then(function() {
95 var promise = egHatch.usePrinting() ?
96 service.print_via_hatch(args) :
97 service.print_via_browser(args);
99 return promise['finally'](
100 function() { service.clear_print_content() });
104 service.print_via_hatch = function(args) {
107 if (args.content_type == 'text/html') {
108 promise = service.ingest_print_content(
109 args.content_type, args.content, args.scope);
111 // text content requires no compilation for remote printing.
112 promise = $q.when(args.content);
115 return promise.then(function(html) {
116 // For good measure, wrap the compiled HTML in container tags.
117 html = "<html><body>" + html + "</body></html>";
118 service.last_print.content = html;
119 service.last_print.context = args.context || 'default';
120 service.last_print.content_type = args.content_type;
121 service.last_print.show_dialog = args.show_dialog;
123 egHatch.setItem('eg.print.last_printed', service.last_print);
125 return service._remotePrint();
129 service._remotePrint = function () {
130 return egHatch.remotePrint(
131 service.last_print.context,
132 service.last_print.content_type,
133 service.last_print.content,
134 service.last_print.show_dialog
138 service.print_via_browser = function(args) {
139 var type = args.content_type;
140 var content = args.content;
141 var printScope = args.scope;
143 if (type == 'text/csv' || type == 'text/plain') {
144 // preserve newlines, spaces, etc.
145 content = '<pre>' + content + '</pre>';
148 // Fetch the print CSS required for in-browser printing.
149 return $http.get(egEnv.basePath + 'css/print.css')
150 .then(function(response) {
152 // Add the bare CSS to the content
153 return '<style type="text/css" media="print">' +
158 }).then(function(content) {
159 service.last_print.content = content;
160 service.last_print.content_type = type;
161 service.last_print.printScope = printScope
163 egHatch.setItem('eg.print.last_printed', service.last_print);
165 // Ingest the content into the page DOM.
166 return service.ingest_print_content(
167 service.last_print.content_type,
168 service.last_print.content,
169 service.last_print.printScope
177 service.reprintLast = function () {
178 var deferred = $q.defer();
179 var promise = deferred.promise;
180 promise.finally( function() { service.clear_print_content() });
183 'eg.print.last_printed'
184 ).then(function (last) {
185 if (last && last.content) {
186 service.last_print = last;
188 if (egHatch.usePrinting()) {
189 promise.then(function () {
190 egHatch._remotePrint()
193 promise.then(function () {
194 service.ingest_print_content(
195 service.last_print.content_type,
196 service.last_print.content,
197 service.last_print.printScope
198 ).then(function() { $window.print() });
201 return deferred.resolve();
203 return deferred.reject();
208 // loads an HTML print template by name from the server
209 // If no template is available in local/hatch storage,
210 // fetch the template as an HTML file from the server.
211 service.getPrintTemplate = function(name) {
212 var deferred = $q.defer();
214 egHatch.getItem('eg.print.template.' + name)
215 .then(function(html) {
218 // we have a locally stored template
219 deferred.resolve(html);
223 var path = service.template_base_path + name;
224 console.debug('fetching template ' + path);
227 .success(function(data) { deferred.resolve(data) })
229 console.error('unable to locate print template: ' + name);
234 return deferred.promise;
237 service.storePrintTemplate = function(name, html) {
238 return egHatch.setItem('eg.print.template.' + name, html);
241 service.removePrintTemplate = function(name) {
242 return egHatch.removeItem('eg.print.template.' + name);
245 service.getPrintTemplateContext = function(name) {
246 var deferred = $q.defer();
248 egHatch.getItem('eg.print.template_context.' + name)
250 function(context) { deferred.resolve(context); },
251 function() { deferred.resolve('default'); }
254 return deferred.promise;
256 service.storePrintTemplateContext = function(name, context) {
257 return egHatch.setItem('eg.print.template_context.' + name, context);
259 service.removePrintTemplateContext = function(name) {
260 return egHatch.removeItem('eg.print.template_context.' + name);
268 * Container for inserting print data into the browser page.
269 * On insert, $window.print() is called to print the data.
270 * The div housing eg-print-container must apply the correct
271 * print media CSS to ensure this content (and not the rest
272 * of the page) is printed.
274 * NOTE: There should only ever be 1 egPrintContainer instance per page.
275 * egPrintContainer attaches functions to the egPrint service with
276 * closures around the egPrintContainer instance's $scope (including its
277 * DOM element). Having multiple egPrintContainers could result in chaos.
280 .directive('egPrintContainer', ['$compile', function($compile) {
283 scope : {}, // isolate our scope
284 link : function(scope, element, attrs) {
288 ['$scope','$q','$window','$timeout','egHatch','egPrint','egEnv',
289 function($scope , $q , $window , $timeout , egHatch , egPrint , egEnv) {
291 egPrint.clear_print_content = function() {
293 $compile($scope.elm.contents())($scope.$new(true));
296 // Insert the printable content into the DOM.
297 // For remote printing, this lets us exract the compiled HTML
299 // For local printing, this lets us print directly from the
300 // DOM with print CSS.
301 // Returns a promise reolved with the compiled HTML as a string.
302 egPrint.ingest_print_content = function(type, content, printScope) {
303 $scope.elm.html(content);
305 var sub_scope = $scope.$new(true);
306 angular.forEach(printScope, function(val, key) {
307 sub_scope[key] = val;
310 var resp = $compile($scope.elm.contents())(sub_scope);
313 var deferred = $q.defer();
315 // give the $digest a chance to complete then resolve
316 // with the compiled HTML from our print container
317 deferred.resolve($scope.elm.html());
320 return deferred.promise;