1 angular.module('egCoreMod')
4 * Iframe container for (mostly legacy) embedded interfaces
6 .directive('egEmbedFrame', function() {
11 // URL to load in the embed iframe
14 // optional hash of functions which augment or override
15 // the stock xulG functions defined below.
19 // called after onload of each new iframe page
24 templateUrl : './share/t_eframe',
26 link: function (scope, element, attrs) {
27 element.find('iframe').on(
29 function() {scope.egEmbedFrameLoader(this)}
34 ['$scope','$window','$location','$q','$timeout','egCore',
35 function($scope , $window , $location , $q , $timeout , egCore) {
37 $scope.save_space = $scope.saveSpace ? $scope.saveSpace : 300;
38 // Set the initial iframe height to just under the window height.
39 // leave room for the navbar, padding, margins, etc.
40 $scope.height = $window.outerHeight - $scope.save_space;
42 // browser client doesn't use cookies, so we don't load the
43 // (at the time of writing, quite limited) angular.cookies
44 // module. We could load something, but this seems to work
45 // well enough for setting the auth cookie (at least, until
48 // note: document.cookie is smart enough to leave unreferenced
49 // cookies alone, so contrary to how this might look, it's not
50 // deleting other cookies (anoncache, etc.)
52 // delete any existing ses cookie
53 $window.document.cookie = "ses=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT";
54 // push our authtoken in
55 $window.document.cookie = 'ses=' + egCore.auth.token() + '; path=/; secure'
57 // $location has functions for modifying paths and search,
58 // but they all assume you are staying within the angular
59 // app, which we are not. Build the URLs by hand.
60 function open_tab(path) {
61 var url = 'https://' + $window.location.hostname +
62 egCore.env.basePath + path;
63 console.debug('egEmbedFrame opening tab ' + url);
64 $window.open(url, '_blank').focus();
67 // define our own xulG functions to be inserted into the
68 // iframe. NOTE: window-level functions are bad. Though
69 // there is probably a way, I was unable to correctly wire
70 // up the iframe onload handler within the controller or link
71 // funcs. In any event, the code below is meant as a stop-gap
72 // for porting dojo, etc. apps to angular apps and should
73 // eventually go away.
74 // NOTE: catalog integration is not a stop-gap
76 $scope.egEmbedFrameLoader = function(iframe) {
78 $scope.frame = {dom:iframe};
79 $scope.iframe = iframe;
81 // Reset the iframe height to the final content height.
82 if ($scope.height < $scope.iframe.contentWindow.document.body.scrollHeight)
83 $scope.height = $scope.iframe.contentWindow.document.body.scrollHeight;
85 var page = $scope.iframe.contentWindow.location.href;
86 console.debug('egEmbedFrameLoader(): ' + page);
88 // reload ifram page w/o reloading the entire UI
89 $scope.reload = function() {
90 $scope.iframe.contentWindow.location.replace(
91 $scope.iframe.contentWindow.location);
94 // tell the iframe'd window its inside the staff client
95 $scope.iframe.contentWindow.IAMXUL = true;
97 // also tell it it's inside the browser client, which
98 // may be needed in a few special cases.
99 $scope.iframe.contentWindow.IAMBROWSER /* hear me roar */ = true;
101 // XUL has a dump() function which is occasinally called
102 // from embedded browsers.
103 $scope.iframe.contentWindow.dump = function(msg) {
104 console.debug('egEmbedFrame:dump(): ' + msg);
107 // Adjust the height again if the iframe loads the openils.Util Dojo module
108 $timeout(function () {
109 if ($scope.iframe.contentWindow.openils && $scope.iframe.contentWindow.openils.Util) {
111 // HACK! for patron reg page
112 var e = $scope.iframe.contentWindow.document.getElementById('myForm');
115 // HACK! for vandelay
117 e = $scope.iframe.contentWindow.document.getElementById('vl-body-wrapper');
122 e = $scope.iframe.contentWindow.document.body;
126 if ($scope.height < e.scrollHeight + extra) {
127 $scope.iframe.contentWindow.openils.Util.addOnLoad( function() {
128 var old_height = $scope.height;
129 $scope.height = e.scrollHeight + extra;
136 // define a few commonly used stock xulG handlers.
138 $scope.iframe.contentWindow.xulG = {
140 spawn_search : function(search) {
141 open_tab('/circ/patron/search?search='
142 + encodeURIComponent(js2JSON(search)));
145 // edit an existing user
146 spawn_editor : function(info) {
148 open_tab('/circ/patron/register/edit/' + info.usr);
150 } else if (info.clone) {
151 // FIXME: The save-and-clone operation in the
152 // patron editor results in this action.
153 // For some reason, this specific function results
154 // in a new browser window opening instead of a
155 // browser tab. Possibly this is caused by the
156 // fact that the action occurs as a result of a
157 // button click instead of an href. *shrug*.
159 open_tab('/circ/patron/register/clone/' + info.clone);
163 // open a user account
164 new_patron_tab : function(tab_info, usr_info) {
165 open_tab('/circ/patron/' + usr_info.id + '/checkout');
168 get_barcode_and_settings_async : function(barcode, only_settings) {
169 if (!barcode) return $q.reject();
170 var deferred = $q.defer();
172 var barcode_promise = $q.when(barcode);
173 if (!only_settings) {
175 // first verify / locate the barcode
176 barcode_promise = egCore.net.request(
178 'open-ils.actor.get_barcodes',
180 egCore.auth.user().ws_ou(), 'actor', barcode
181 ).then(function(resp) {
183 if (!resp || egCore.evt.parse(resp) || !resp.length) {
184 console.error('user not found: ' + barcode);
190 return barcode = resp.barcode;
194 barcode_promise.then(function(barcode) {
195 if (!barcode) return;
197 return egCore.net.request(
199 'open-ils.actor.user.fleshed.retrieve_by_barcode',
200 egCore.auth.token(), barcode);
202 }).then(function(user) {
203 if (!user) return null;
205 if (e = egCore.evt.parse(user)) {
206 console.error('user fetch failed : ' + e.toString());
211 // copied more or less directly from XUL menu.js
213 for(var i = 0; i < user.settings().length; i++) {
214 settings[user.settings()[i].name()] =
215 JSON2js(user.settings()[i].value());
218 if(!settings['opac.default_phone'] && user.day_phone())
219 settings['opac.default_phone'] = user.day_phone();
220 if(!settings['opac.hold_notify'] && settings['opac.hold_notify'] !== '')
221 settings['opac.hold_notify'] = 'email:phone';
223 // Taken from patron/util.js format_name
226 ( user.prefix() ? user.prefix() + ' ' : '') +
227 user.family_name() + ', ' +
228 user.first_given_name() + ' ' +
229 ( user.second_given_name() ? user.second_given_name() + ' ' : '' ) +
230 ( user.suffix() ? user.suffix() : '');
234 "settings" : settings,
235 "user_email" : user.email(),
236 "patron_name" : patron_name
240 return deferred.promise;
244 if ($scope.handlers) {
245 $scope.handlers.reload = $scope.reload;
246 angular.forEach($scope.handlers, function(val, key) {
247 console.log('eframe applying xulG handlers: ' + key);
248 $scope.iframe.contentWindow.xulG[key] = val;
252 if ($scope.onchange) $scope.onchange(page);