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