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 service.template_base_path = 'share/print_templates/t_';
16 * context : 'default', 'receipt','label', etc.
17 * scope : data loaded into the template environment
18 * template : template name (e.g. 'checkout', 'transit_slip'
19 * content : content to print. If 'template' is set, content is
20 * derived from the template.
21 * content_type : 'text/html', 'text/plain', 'text/csv'
22 * show_dialog : boolean, if true, print dialog is shown. This setting
23 * only affects remote printers, since browser printers
24 * do not allow such control
26 service.print = function(args) {
27 if (!args) return $q.when();
30 // fetch the template, then proceed to printing
32 return service.getPrintTemplate(args.template)
33 .then(function(content) {
34 args.content = content;
35 if (!args.content_type) args.content_type = 'text/html';
36 service.getPrintTemplateContext(args.template)
37 .then(function(context) {
38 args.context = context;
39 return service.print_content(args);
45 return service.print_content(args);
48 // add commonly used attributes to the print scope
49 service.fleshPrintScope = function(scope) {
50 if (!scope) scope = {};
51 scope.today = new Date().toISOString();
52 scope.staff = egIDL.toHash(egAuth.user());
53 scope.current_location =
54 egIDL.toHash(egOrg.get(egAuth.user().ws_ou()));
57 service.last_print = {};
59 // Template has been fetched (or no template needed)
60 // Process the template and send the result off to the printer.
61 service.print_content = function(args) {
62 service.fleshPrintScope(args.scope);
64 var promise = egHatch.usePrinting() ?
65 service.print_via_hatch(args) :
66 service.print_via_browser(args);
68 return promise['finally'](
69 function() { service.clear_print_content() });
72 service.print_via_hatch = function(args) {
75 if (args.content_type == 'text/html') {
76 promise = service.ingest_print_content(
77 args.content_type, args.content, args.scope);
79 // text content requires no compilation for remote printing.
80 promise = $q.when(args.content);
83 return promise.then(function(html) {
84 // For good measure, wrap the compiled HTML in container tags.
85 html = "<html><body>" + html + "</body></html>";
86 service.last_print.content = html;
87 service.last_print.context = args.context || 'default';
88 service.last_print.content_type = args.content_type;
89 service.last_print.show_dialog = args.show_dialog;
91 egHatch.setItem('eg.print.last_printed', service.last_print);
93 return service._remotePrint();
97 service._remotePrint = function () {
98 return egHatch.remotePrint(
99 service.last_print.context,
100 service.last_print.content_type,
101 service.last_print.content,
102 service.last_print.show_dialog
106 service.print_via_browser = function(args) {
107 var type = args.content_type;
108 var content = args.content;
109 var printScope = args.scope;
111 if (type == 'text/csv' || type == 'text/plain') {
112 // preserve newlines, spaces, etc.
113 content = '<pre>' + content + '</pre>';
116 // Fetch the print CSS required for in-browser printing.
117 return $http.get(egEnv.basePath + 'css/print.css')
118 .then(function(response) {
120 // Add the bare CSS to the content
121 return '<style type="text/css" media="print">' +
126 }).then(function(content) {
127 service.last_print.content = content;
128 service.last_print.content_type = type;
129 service.last_print.printScope = printScope
131 egHatch.setItem('eg.print.last_printed', service.last_print);
133 // Ingest the content into the page DOM.
134 return service.ingest_print_content(
135 service.last_print.content_type,
136 service.last_print.content,
137 service.last_print.printScope
145 service.reprintLast = function () {
146 var deferred = $q.defer();
147 var promise = deferred.promise;
148 promise.finally( function() { service.clear_print_content() });
151 'eg.print.last_printed'
152 ).then(function (last) {
153 if (last && last.content) {
154 service.last_print = last;
156 if (egHatch.usePrinting()) {
157 promise.then(function () {
158 egHatch._remotePrint()
161 promise.then(function () {
162 service.ingest_print_content(
163 service.last_print.content_type,
164 service.last_print.content,
165 service.last_print.printScope
166 ).then(function() { $window.print() });
169 return deferred.resolve();
171 return deferred.reject();
176 // loads an HTML print template by name from the server
177 // If no template is available in local/hatch storage,
178 // fetch the template as an HTML file from the server.
179 service.getPrintTemplate = function(name) {
180 var deferred = $q.defer();
182 egHatch.getItem('eg.print.template.' + name)
183 .then(function(html) {
186 // we have a locally stored template
187 deferred.resolve(html);
191 var path = service.template_base_path + name;
192 console.debug('fetching template ' + path);
195 .success(function(data) { deferred.resolve(data) })
197 console.error('unable to locate print template: ' + name);
202 return deferred.promise;
205 service.storePrintTemplate = function(name, html) {
206 return egHatch.setItem('eg.print.template.' + name, html);
209 service.getPrintTemplateContext = function(name) {
210 var deferred = $q.defer();
212 egHatch.getItem('eg.print.template_context.' + name)
214 function(context) { deferred.resolve(context); },
215 function() { deferred.resolve('default'); }
218 return deferred.promise;
220 service.storePrintTemplateContext = function(name, context) {
221 return egHatch.setItem('eg.print.template_context.' + name, context);
229 * Container for inserting print data into the browser page.
230 * On insert, $window.print() is called to print the data.
231 * The div housing eg-print-container must apply the correct
232 * print media CSS to ensure this content (and not the rest
233 * of the page) is printed.
235 * NOTE: There should only ever be 1 egPrintContainer instance per page.
236 * egPrintContainer attaches functions to the egPrint service with
237 * closures around the egPrintContainer instance's $scope (including its
238 * DOM element). Having multiple egPrintContainers could result in chaos.
241 .directive('egPrintContainer', ['$compile', function($compile) {
244 scope : {}, // isolate our scope
245 link : function(scope, element, attrs) {
249 ['$scope','$q','$window','$timeout','egHatch','egPrint','egEnv',
250 function($scope , $q , $window , $timeout , egHatch , egPrint , egEnv) {
252 egPrint.clear_print_content = function() {
254 $compile($scope.elm.contents())($scope.$new(true));
257 // Insert the printable content into the DOM.
258 // For remote printing, this lets us exract the compiled HTML
260 // For local printing, this lets us print directly from the
261 // DOM with print CSS.
262 // Returns a promise reolved with the compiled HTML as a string.
263 egPrint.ingest_print_content = function(type, content, printScope) {
264 $scope.elm.html(content);
266 var sub_scope = $scope.$new(true);
267 angular.forEach(printScope, function(val, key) {
268 sub_scope[key] = val;
271 var resp = $compile($scope.elm.contents())(sub_scope);
274 var deferred = $q.defer();
276 // give the $digest a chance to complete then resolve
277 // with the compiled HTML from our print container
278 deferred.resolve($scope.elm.html());
281 return deferred.promise;