]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/js/ui/default/staff/services/print.js
webstaff: tweaks to egPrint
[working/Evergreen.git] / Open-ILS / web / js / ui / default / staff / services / print.js
1 /**
2  * egPrint : manage print templates, process templates, print content
3  *
4  * TODO: create configurable links between print template and context.
5  */
6 angular.module('egCoreMod')
7
8 .factory('egPrint',
9        ['$q','$window','$timeout','$http','egHatch','egAuth','egIDL','egOrg','egEnv',
10 function($q , $window , $timeout , $http , egHatch , egAuth , egIDL , egOrg , egEnv) {
11
12     var service = {};
13
14     service.template_base_path = 'share/print_templates/t_';
15
16     /*
17      * context  : 'default', 'receipt','label', etc. 
18      * scope    : data loaded into the template environment
19      * template : template name (e.g. 'checkout', 'transit_slip'
20      * content  : content to print.  If 'template' is set, content is
21      *            derived from the template.
22      * content_type : 'text/html', 'text/plain', 'text/csv'
23      * show_dialog  : boolean, if true, print dialog is shown.  This setting
24      *                only affects remote printers, since browser printers
25      *                do not allow such control
26      */
27     service.print = function(args) {
28         if (!args) return $q.when();
29
30         if (args.template) {
31             // fetch the template, then proceed to printing
32
33             return service.getPrintTemplate(args.template)
34             .then(function(content) {
35                 args.content = content;
36                 if (!args.content_type) args.content_type = 'html';
37                 return service.print_content(args);
38             });
39
40         } 
41
42         return service.print_content(args);
43     }
44
45     // add commonly used attributes to the print scope
46     service.fleshPrintScope = function(scope) {
47         if (!scope) scope = {};
48         scope.today = new Date().toISOString();
49         scope.staff = egIDL.toHash(egAuth.user());
50         scope.current_location = 
51             egIDL.toHash(egOrg.get(egAuth.user().ws_ou()));
52     }
53
54     // Template has been fetched (or no template needed) 
55     // Process the template and send the result off to the printer.
56     service.print_content = function(args) {
57         service.fleshPrintScope(args.scope);
58
59         var promise;
60         if (args.content_type == 'text/html') {
61
62             // all HTML content is assumed to require compilation, 
63             // regardless of the print destination
64             promise = service.ingest_print_content(
65                 args.content_type, args.content, args.scope);
66
67         } else {
68             // text content does not require compilation for remote printing
69             promise = $q.when(args.content);
70         }
71
72         // TODO: link print context to template type
73         var context = args.context || 'default';
74
75         return promise.then(function(html) {
76
77             return egHatch.remotePrint(context,
78                 args.content_type, html, args.show_dialog)['catch'](
79
80                 function(msg) {
81                     // remote print not available; 
82
83                     if (egHatch.hatchRequired()) {
84                         console.error("Unable to print data; "
85                          + "hatchRequired=true, but hatch is not connected");
86                          return $q.reject();
87                     }
88
89                     if (args.content_type != 'text/html') {
90                         // text content does require compilation 
91                         // (absorption) for browser printing
92                         return service.ingest_print_content(
93                             args.content_type, args.content, args.scope
94                         ).then(function() { $window.print(); service.clear_print_content(); });
95                     } else {
96                         // HTML content is already ingested and accessible
97                         // within the page to the printer.  
98                         $window.print();
99                         service.clear_print_content();
100                     }
101                 }
102             );
103         });
104     }
105
106     // loads an HTML print template by name from the server
107     // If no template is available in local/hatch storage, 
108     // fetch the template as an HTML file from the server.
109     service.getPrintTemplate = function(name) {
110         var deferred = $q.defer();
111
112         egHatch.getItem('eg.print.template.' + name)
113         .then(function(html) {
114
115             if (html) {
116                 // we have a locally stored template
117                 deferred.resolve(html);
118                 return;
119             }
120
121             var path = service.template_base_path + name;
122             console.debug('fetching template ' + path);
123
124             $http.get(path)
125             .success(function(data) { deferred.resolve(data) })
126             .error(function() {
127                 console.error('unable to locate print template: ' + name);
128                 deferred.reject();
129             });
130         });
131
132         return deferred.promise;
133     }
134
135     service.storePrintTemplate = function(name, html) {
136         return egHatch.setItem('eg.print.template.' + name, html);
137     }
138
139     return service;
140 }])
141
142
143 /**
144  * Container for inserting print data into the browser page.
145  * On insert, $window.print() is called to print the data.
146  * The div housing eg-print-container must apply the correct
147  * print media CSS to ensure this content (and not the rest
148  * of the page) is printed.
149  */
150
151 // FIXME: only apply print CSS when print commands are issued via the 
152 // print container, otherwise using the browser's native print page 
153 // option will always result in empty pages.  Move the print CSS
154 // out of the standalone CSS file and put it into a template file
155 // for this directive.
156 .directive('egPrintContainer', ['$compile', '$http', function($compile, $http) {
157     return {
158         restrict : 'AE',
159         scope : {}, // isolate our scope
160         link : function(scope, element, attrs) {
161             scope.elm = element;
162         },
163         controller : 
164                    ['$scope','$q','$window','$timeout','egHatch','egPrint','egEnv',
165             function($scope , $q , $window , $timeout , egHatch , egPrint , egEnv) {
166
167                 egPrint.clear_print_content = function() {
168                     $scope.elm.html('');
169                     $compile($scope.elm.contents())($scope.$new(true));
170                 }
171
172                 egPrint.ingest_print_content = function(type, content, printScope) {
173
174                     if (type == 'text/csv' || type == 'text/plain') {
175                         // preserve newlines, spaces, etc.
176                         content = '<pre>' + content + '</pre>';
177                     }
178
179                     return $http.get(egEnv.basePath + 'css/print.css').then(
180                         function(response) {
181                             content = '<style type="text/css" media="print">' +
182                                       response.data +
183                                       '</style>' +
184                                       content;
185                             return finish_ingest_print_content(type, content, printScope);
186                         },
187                         function() {
188                             return finish_ingest_print_content(type, content, printScope);
189                         }
190                     );
191
192                 }
193
194                 function finish_ingest_print_content(type, content, printScope) {
195                     $scope.elm.html(content);
196
197                     var sub_scope = $scope.$new(true);
198                     angular.forEach(printScope, function(val, key) {
199                         sub_scope[key] = val;
200                     })
201
202                     var resp = $compile($scope.elm.contents())(sub_scope);
203
204                     var deferred = $q.defer();
205                     $timeout(function(){
206                         // give the $digest a chance to complete then
207                         // resolve with the compiled HTML from our
208                         // print container
209
210                         deferred.resolve(
211                             resp.contents()[0].parentNode.innerHTML
212                         );
213                     });
214
215                     return deferred.promise;
216                 }
217             }
218         ]
219     }
220 }])
221