]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/xul/staff_client/chrome/content/OpenILS/global_util.js
add unsaved data warning to offline interface. tweak oils_lock_page/oils_unlock_page...
[working/Evergreen.git] / Open-ILS / xul / staff_client / chrome / content / OpenILS / global_util.js
1     function $(id) { return document.getElementById(id); }
2
3     function oils_lock_page(params) {
4         dump('oils_lock_page\n');
5         if (!params) { params = {}; }
6         if (window.oils_lock > 0) {
7             if (!params.allow_multiple_locks) {
8                 return window.oils_lock;
9             }
10         }
11         window.oils_lock++;
12         if (typeof xulG != 'undefined') {
13             if (typeof xulG.unlock_tab == 'function') {
14                 xulG.lock_tab();
15             }
16         }
17         return window.oils_lock;
18     }
19
20     function oils_unlock_page(params) {
21         dump('oils_unlock_page\n');
22         window.oils_lock--;
23         if (window.oils_lock < 0) { window.oils_lock = 0; }
24         if (typeof xulG != 'undefined') {
25             if (typeof xulG.unlock_tab == 'function') {
26                 xulG.unlock_tab();
27             }
28         }
29         return window.oils_lock;
30     }
31
32     window.oils_lock = 0;
33     window.addEventListener(
34         'close',
35         function(ev) {
36             try {
37                 dump('oils_lock_page/oils_unlock_page onclose handler\n');
38                 if (window.oils_lock > 0) {
39                     var confirmation = window.confirm($('offlineStrings').getString('menu.close_window.unsaved_data_warning'));
40                     if (!confirmation) {
41                         ev.preventDefault();
42                         return false;
43                     }
44                 }
45
46                 window.oils_lock = 0;
47                 if (typeof xulG != 'undefined') {
48                     if (typeof xulG.unlock_tab == 'function') {
49                         xulG.unlock_tab();
50                     }
51                 }
52
53                 // Dispatching the window close event doesn't always close the window, even though the event does happen
54                 setTimeout(
55                     function() {
56                         try {
57                             window.close();
58                         } catch(E) {
59                             dump('Error inside global_util.js, onclose handler, setTimeout window.close KLUDGE: ' + E + '\n');
60                         }
61                     }, 0
62                 );
63
64                 return true;
65             } catch(E) {
66                 dump('Error inside global_util.js, onclose handler: ' + E + '\n');
67                 return true;
68             }
69         },
70         false
71     );
72
73     function ses(a,params) {
74         try {
75             if (!params) params = {};
76             var data;
77             if (params.data) {
78                 data = params.data; data.stash_retrieve();
79             } else {
80                 // This has been breaking in certain contexts, with an internal instantiation of util.error failing because of util.error being an object instead of the constructor function it should be
81                 JSAN.use('OpenILS.data'); data = new OpenILS.data(); data.stash_retrieve();
82             }
83
84             switch(a) {
85                 case 'staff' : return data.list.au[0]; break;
86                 case 'staff_id' : return data.list.au[0].id(); break;
87                 case 'staff_usrname' : return data.list.au[0].usrname(); break;
88                 case 'ws_ou' :
89                     return data.list.au[0].ws_ou();
90                 break;
91                 case 'ws_ou_shortname' :
92                     return data.hash.aou[ data.list.au[0].ws_ou() ].shortname();
93                 break;
94                 case 'authtime' :
95                     return data.session.authtime;
96                 break;
97                 case 'key':
98                 default:
99                     return data.session.key;
100                 break;
101             }
102         } catch(E) {
103             alert(location.href + '\nError in global_utils.js, ses(): ' + E);
104             throw(E);
105         }
106     }
107
108     function font_helper() {
109         try {
110             JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
111             removeCSSClass(document.documentElement,'ALL_FONTS_LARGER');
112             removeCSSClass(document.documentElement,'ALL_FONTS_SMALLER');
113             removeCSSClass(document.documentElement,'ALL_FONTS_XX_SMALL');
114             removeCSSClass(document.documentElement,'ALL_FONTS_X_SMALL');
115             removeCSSClass(document.documentElement,'ALL_FONTS_SMALL');
116             removeCSSClass(document.documentElement,'ALL_FONTS_MEDIUM');
117             removeCSSClass(document.documentElement,'ALL_FONTS_LARGE');
118             removeCSSClass(document.documentElement,'ALL_FONTS_X_LARGE');
119             removeCSSClass(document.documentElement,'ALL_FONTS_XX_LARGE');
120             addCSSClass(document.documentElement,data.global_font_adjust);
121         } catch(E) {
122             var Strings = $('offlineStrings') || $('commonStrings');
123             alert(Strings.getFormattedString('openils.global_util.font_size.error', [E]));
124         }
125     }
126
127     function oils_persist(e,cancelable) {
128         try {
129             if (!e) { return; }
130             if (typeof cancelable == 'undefined') { cancelable = false; } 
131             var evt = document.createEvent("Events");
132             evt.initEvent( 'oils_persist', false, cancelable ); // event name, bubbles, cancelable
133             e.dispatchEvent(evt);
134         } catch(E) {
135             alert('Error with oils_persist():' + E);
136         }
137     }
138
139     function persist_helper(base_key_suffix) {
140         try {
141             if (base_key_suffix) {
142                 base_key_suffix = base_key_suffix.replace(/[^A-Za-z]/g,'_') + '_';
143             } else {
144                 base_key_suffix = '';
145             }
146
147             function gen_event_handler(etype,node) {
148                 return function(ev) {
149                     try {
150                         oils_persist(ev.target);
151                     } catch(E) {
152                         alert('Error in persist_helper, firing virtual event oils_persist after ' + etype + ' event on ' + node.nodeName + '.id = ' + node.id + ': ' + E);
153                     }
154                 };
155             };
156
157             function gen_oils_persist_handler(bk,node) {
158                 return function(ev) {
159                     try {
160                         netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
161                         var target;
162                         if (ev.target.nodeName == 'command') {
163                             target = node;
164                             if (ev.explicitOriginalTarget != node) return;
165                         } else {
166                             target = ev.target;
167                             if (target == window) {
168                                 target = window.document.documentElement;
169                             }
170                         }
171                         var filename = location.pathname.split('/')[ location.pathname.split('/').length - 1 ];
172                         var base_key = 'oils_persist_' + String(location.hostname + '_' + filename + '_' + target.getAttribute('id')).replace('/','_','g') + '_' + base_key_suffix;
173                         var attribute_list = target.getAttribute('oils_persist').split(' ');
174                         dump('on_oils_persist: <<< ' + target.nodeName + '.id = ' + target.id + '\t' + bk + '\n');
175                         for (var j = 0; j < attribute_list.length; j++) {
176                             var key = base_key + attribute_list[j];
177                             var value = target.getAttribute( attribute_list[j] );
178                             if ( attribute_list[j] == 'checked' && ['checkbox','toolbarbutton'].indexOf( target.nodeName ) > -1 ) {
179                                 value = target.checked;
180                                 dump('\t' + value + ' <== .' + attribute_list[j] + '\n');
181                             } else if ( attribute_list[j] == 'value' && ['textbox'].indexOf( target.nodeName ) > -1 ) {
182                                 value = target.value;
183                                 dump('\t' + value + ' <== .' + attribute_list[j] + '\n');
184                             } else if ( attribute_list[j] == 'sizemode' && ['window'].indexOf( target.nodeName ) > -1 ) {
185                                 value = window.windowState;
186                                 dump('\t' + value + ' <== window.windowState, @' + attribute_list[j] + '\n');
187                             } else if ( attribute_list[j] == 'height' && ['window'].indexOf( target.nodeName ) > -1 ) {
188                                 value = window.outerHeight;
189                                 dump('\t' + value + ' <== window.outerHeight, @' + attribute_list[j] + '\n');
190                             } else if ( attribute_list[j] == 'width' && ['window'].indexOf( target.nodeName ) > -1 ) {
191                                 value = window.outerWidth;
192                                 dump('\t' + value + ' <== window.outerWidth, @' + attribute_list[j] + '\n');
193                             } else {
194                                 dump('\t' + value + ' <== @' + attribute_list[j] + '\n');
195                             }
196                             prefs.setCharPref( key, value );
197                             // TODO: Need to add logic for splitter repositioning, grippy state, etc.
198                             // NOTE: oils_persist_peers and oils_persist="width" on those peers can help with the elements adjacent to a splitter
199                         }
200                         if (target.hasAttribute('oils_persist_peers') && ! ev.cancelable) { // We abuse the .cancelable field on the oils_persist event to prevent looping
201                             var peer_list = target.getAttribute('oils_persist_peers').split(' ');
202                             for (var j = 0; j < peer_list.length; j++) {
203                                 dump('on_oils_persist: dispatching oils_persist to peer ' + peer_list[j] + '\n');
204                                 oils_persist( document.getElementById( peer_list[j] ), true );
205                             } 
206                         }
207                     } catch(E) {
208                         alert('Error in persist_helper() event listener for ' + bk + ': ' + E);
209                     }
210                 };
211             }
212
213             netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
214             var prefs = Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces['nsIPrefBranch']);
215             var nodes = document.getElementsByAttribute('oils_persist','*');
216             for (var i = 0; i < nodes.length; i++) {
217                 var filename = location.pathname.split('/')[ location.pathname.split('/').length - 1 ];
218                 var base_key = 'oils_persist_' + String(location.hostname + '_' + filename + '_' + nodes[i].getAttribute('id')).replace('/','_','g') + '_' + base_key_suffix;
219                 var attribute_list = nodes[i].getAttribute('oils_persist').split(' ');
220                 dump('persist_helper: >>> ' + nodes[i].nodeName + '.id = ' + nodes[i].id + '\t' + base_key + '\n');
221                 for (var j = 0; j < attribute_list.length; j++) {
222                     var key = base_key + attribute_list[j];
223                     var has_key = prefs.prefHasUserValue(key);
224                     var value = has_key ? prefs.getCharPref(key) : null;
225                     if (value == 'true') { value = true; }
226                     if (value == 'false') { value = false; }
227                     if (has_key) {
228                         if ( attribute_list[j] == 'checked' && ['checkbox','toolbarbutton'].indexOf( nodes[i].nodeName ) > -1 ) {
229                             nodes[i].checked = value; 
230                             dump('\t' + value + ' ==> .' + attribute_list[j] + '\n');
231                             if (!value) {
232                                 nodes[i].removeAttribute('checked');
233                                 dump('\tremoving @checked\n');
234                             }
235                         } else if ( attribute_list[j] == 'value' && ['textbox'].indexOf( nodes[i].nodeName ) > -1 ) {
236                             nodes[i].value = value;
237                             dump('\t' + value + ' ==> .' + attribute_list[j] + '\n');
238                         } else if ( attribute_list[j] == 'sizemode' && ['window'].indexOf( nodes[i].nodeName ) > -1 ) {
239                             switch(value) {
240                                 case window.STATE_MAXIMIZED:
241                                     window.maximize();
242                                     break;
243                                 case window.STATE_MINIMIZED:
244                                     window.minimize();
245                                     break;
246                             };
247                             dump('\t' + value + ' ==> window.windowState, @' + attribute_list[j] + '\n');
248                         } else if ( attribute_list[j] == 'height' && ['window'].indexOf( nodes[i].nodeName ) > -1 ) {
249                             window.outerHeight = value;
250                             dump('\t' + value + ' ==> window.outerHeight, @' + attribute_list[j] + '\n');
251                         } else if ( attribute_list[j] == 'width' && ['window'].indexOf( nodes[i].nodeName ) > -1 ) {
252                             window.outerWidth = value;
253                             dump('\t' + value + ' ==> window.outerWidth, @' + attribute_list[j] + '\n');
254                         } else {
255                             nodes[i].setAttribute( attribute_list[j], value);
256                             dump('\t' + value + ' ==> @' + attribute_list[j] + '\n');
257                         }
258                     }
259                 }
260                 var cmd = nodes[i].getAttribute('command');
261                 var cmd_el = document.getElementById(cmd);
262                 if (nodes[i].disabled == false && nodes[i].hidden == false) {
263                     var no_poke = nodes[i].getAttribute('oils_persist_no_poke');
264                     if (no_poke && no_poke == 'true') {
265                         // Timing issue for some checkboxes; don't poke them with an event
266                         dump('\tnot poking\n');
267                     } else {
268                         if (cmd_el) {
269                             dump('\tpoking @command\n');
270                             var evt = document.createEvent("Events");
271                             evt.initEvent( 'command', true, true );
272                             cmd_el.dispatchEvent(evt);
273                         } else {
274                             dump('\tpoking\n');
275                             var evt = document.createEvent("Events");
276                             evt.initEvent( 'command', true, true );
277                             nodes[i].dispatchEvent(evt);
278                         }
279                     }
280                 }
281                 if (cmd_el) {
282                     cmd_el.addEventListener(
283                         'command',
284                         gen_event_handler('command',cmd_el),
285                         false
286                     );
287                     cmd_el.addEventListener(
288                         'oils_persist',
289                         gen_oils_persist_handler( base_key, nodes[i] ),
290                         false
291                     );
292                 } else {
293                     var node = nodes[i];
294                     var event_types = [];
295                     if (node.hasAttribute('oils_persist_events')) {
296                         var event_type_list = node.getAttribute('oils_persist_events').split(' ');
297                         for (var j = 0; j < event_type_list.length; j++) {
298                             event_types.push( event_type_list[j] );
299                         }
300                     } else {
301                         if (node.nodeName == 'textbox') { 
302                             event_types.push('change'); 
303                         } else if (node.nodeName == 'window') {
304                             event_types.push('resize'); 
305                             node = window; // xul window is an element of window.document
306                         } else {
307                             event_types.push('command'); 
308                         }
309                     }
310                     for (var j = 0; j < event_types.length; j++) {
311                         node.addEventListener(
312                             event_types[j],
313                             gen_event_handler(event_types[j],node),
314                             false
315                         );
316                     }
317                     node.addEventListener(
318                         'oils_persist',
319                         gen_oils_persist_handler( base_key, node ),
320                         false
321                     );
322                 }
323             }
324         } catch(E) {
325             alert('Error in persist_helper(): ' + E);
326         }
327     }
328
329     function getKeys(o) {
330         var keys = [];
331         for (var k in o) keys.push(k);
332         return keys;
333     }
334
335     function get_contentWindow(frame) {
336         try {
337             netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
338             if (frame && frame.contentWindow) {
339                 try {
340                     if (typeof frame.contentWindow.wrappedJSObject != 'undefined') {
341                                      return frame.contentWindow.wrappedJSObject;
342                           }
343                 } catch(E) {
344                     var Strings = $('offlineStrings') || $('commonStrings');
345                     alert(Strings.getFormattedString('openils.global_util.content_window_jsobject.error', [frame, E]));
346                 }
347                 return frame.contentWindow;
348             } else {
349                 return null;
350             }
351         } catch(E) {
352             var Strings = $('offlineStrings') || $('commonStrings');
353             alert(Strings.getFormattedString('openils.global_util.content_window.error', [frame, E]));
354         }
355     }
356
357     function update_modal_xulG(v) {
358         try {
359             JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
360             var key = location.pathname + location.search + location.hash;
361             if (typeof data.modal_xulG_stack != 'undefined' && typeof data.modal_xulG_stack[key] != 'undefined') {
362                 data.modal_xulG_stack[key][ data.modal_xulG_stack[key].length - 1 ] = v;
363                 data.stash('modal_xulG_stack');
364             }
365         } catch(E) {
366             alert('FIXME: update_modal_xulG => ' + E);
367         }
368     }
369
370     function xul_param(param_name,_params) {
371         /* By default, this function looks for a CGI-style query param identified by param_name.  If one isn't found, it then looks in xulG.  If one still isn't found, and _params.stash_name is true, it looks in the global xpcom stash for the field identified by stash_name.  If _params.concat is true, then it looks in all these places and concatenates the results.  There are also options for converting JSON to javascript objects, and clearing the xpcom stash_name field after retrieval.  Also added, ability to search a specific spot in the xpcom stash that implements a stack to hold xulG's for modal windows */
372         try {
373             //dump('xul_param('+param_name+','+js2JSON(_params)+')\n');
374             var value = undefined; if (!_params) _params = {};
375             if (typeof _params.no_cgi == 'undefined') {
376                 var cgi = new CGI();
377                 if (cgi.param(param_name)) {
378                     var x = cgi.param(param_name);
379                     //dump('\tfound via location.href = ' + x + '\n');
380                     if (typeof _params.JSON2js_if_cgi != 'undefined') {
381                         x = JSON2js( x );
382                         //dump('\tJSON2js = ' + x + '\n');
383                     }
384                     if (typeof _params.concat == 'undefined') {
385                         //alert(param_name + ' x = ' + x);
386                         return x; // value
387                     } else {
388                         if (value) {
389                             if (value.constructor != Array) value = [ value ];
390                             value = value.concat(x);
391                         } else {
392                             value = x;
393                         }
394                     }
395                 }
396             }
397             if (typeof _params.no_xulG == 'undefined') {
398                 if (typeof _params.modal_xulG != 'undefined') {
399                     JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
400                     var key = location.pathname + location.search + location.hash;
401                     //dump('xul_param, considering modal key = ' + key + '\n');
402                     if (typeof data.modal_xulG_stack != 'undefined' && typeof data.modal_xulG_stack[key] != 'undefined') {
403                         xulG = data.modal_xulG_stack[key][ data.modal_xulG_stack[key].length - 1 ];
404                     }
405                 }
406                 if (typeof xulG == 'object' && typeof xulG[ param_name ] != 'undefined') {
407                     var x = xulG[ param_name ];
408                     //dump('\tfound via xulG = ' + x + '\n');
409                     if (typeof _params.JSON2js_if_xulG != 'undefined') {
410                         x = JSON2js( x );
411                         //dump('\tJSON2js = ' + x + '\n');
412                     }
413                     if (typeof _params.concat == 'undefined') {
414                         //alert(param_name + ' x = ' + x);
415                         return x; // value
416                     } else {
417                         if (value) {
418                             if (value.constructor != Array) value = [ value ];
419                             value = value.concat(x);
420                         } else {
421                             value = x;
422                         }
423                     }
424                 }
425             }
426             if (typeof _params.no_xpcom == 'undefined') {
427                 /* the field names used for temp variables in the global stash tend to be more unique than xuLG or CGI param names, to avoid collisions */
428                 if (typeof _params.stash_name != 'undefined') { 
429                     JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
430                     if (typeof data[ _params.stash_name ] != 'undefined') {
431                         var x = data[ _params.stash_name ];
432                         //dump('\tfound via xpcom = ' + x + '\n');
433                         if (typeof _params.JSON2js_if_xpcom != 'undefined') {
434                             x = JSON2js( x );
435                             //dump('\tJSON2js = ' + x + '\n');
436                         }
437                         if (_params.clear_xpcom) { 
438                             data[ _params.stash_name ] = undefined; data.stash( _params.stash_name ); 
439                         }
440                         if (typeof _params.concat == 'undefined') {
441                             //alert(param_name + ' x = ' + x);
442                             return x; // value
443                         } else {
444                             if (value) {
445                                 if (value.constructor != Array) value = [ value ];
446                                 value = value.concat(x);
447                             } else {
448                                 value = x;
449                             }
450                         }
451                     }
452                 }
453             }
454             //alert(param_name + ' value = ' + value);
455             return value;
456         } catch(E) {
457             dump('xul_param error: ' + E + '\n');
458         }
459     }
460
461     function get_bool(a) {
462         // Normal javascript interpretation except 'f' == false, per postgres, and 'F' == false, and '0' == false (newer JSON is returning '0' instead of 0 in cases)
463         // So false includes 'f', '', '0', 0, null, and undefined
464         if (a == 'f') return false;
465         if (a == 'F') return false;
466         if (a == '0') return false;
467         if (a) return true; else return false;
468     }
469
470     function get_localized_bool(a) {
471         var Strings = $('offlineStrings') || $('commonStrings');
472         return get_bool(a) ? Strings.getString('common.yes') : Strings.getString('common.no');
473     }
474
475     function get_db_true() {
476         return 't';
477     }
478
479     function get_db_false() {
480         return 'f';
481     }
482
483     function copy_to_clipboard(ev) {
484         try {
485             netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
486             var text;
487             if (typeof ev == 'object') {
488                 if (typeof ev.target != 'undefined') {
489                     if (typeof ev.target.textContent != 'undefined') if (ev.target.textContent) text = ev.target.textContent;
490                     if (typeof ev.target.value != 'undefined') if (ev.target.value) text = ev.target.value;
491                 }
492             } else if (typeof ev == 'string') {
493                 text = ev;
494             }
495             const gClipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"]
496                 .getService(Components.interfaces.nsIClipboardHelper);
497             gClipboardHelper.copyString(text);
498             var Strings = $('offlineStrings') || $('commonStrings');
499             alert(Strings.getFormattedString('openils.global_util.clipboard', [text]));
500         } catch(E) {
501             var Strings = $('offlineStrings') || $('commonStrings');
502             alert(Strings.getFormattedString('openils.global_util.clipboard.error', [E]));    
503         }
504     }
505
506     function clear_the_cache() {
507         try {
508             netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
509             var cacheClass         = Components.classes["@mozilla.org/network/cache-service;1"];
510             var cacheService    = cacheClass.getService(Components.interfaces.nsICacheService);
511             cacheService.evictEntries(Components.interfaces.nsICache.STORE_ON_DISK);
512             cacheService.evictEntries(Components.interfaces.nsICache.STORE_IN_MEMORY);
513         } catch(E) {
514             var Strings = $('offlineStrings') || $('commonStrings');
515             alert(Strings.getFormattedString('openils.global_util.clear_cache.error', [E]));
516         }
517     }
518
519     function toOpenWindowByType(inType, uri) {
520         var winopts = "chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar";
521         window.open(uri, "_blank", winopts);
522     }
523
524     function url_prefix(url) {
525         if (url.match(/^\//)) url = urls.remote + url;
526         if (! url.match(/^(http|chrome):\/\//) && ! url.match(/^data:/) ) url = 'http://' + url;
527         dump('url_prefix = ' + url + '\n');
528         return url;
529     }
530