]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/xul/staff_client/chrome/content/OpenILS/global_util.js
LP1615805 No inputs after submit in patron search (AngularJS)
[working/Evergreen.git] / Open-ILS / xul / staff_client / chrome / content / OpenILS / global_util.js
1     if(window.arguments && typeof window.arguments[0] == 'object' && typeof xulG == 'undefined') {
2         xulG = window.arguments[0];
3     }
4
5     function $(id) { return document.getElementById(id); }
6
7     function oils_unsaved_data_V() {
8         var tabs = window.parent.parent.document.getElementById('main_tabs');
9
10         if (tabs) {
11             var idx = tabs.selectedIndex;
12             var tab = tabs.childNodes[idx];
13         }
14
15         JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.stash_retrieve();
16         data.stash_retrieve();
17         if (typeof data.unsaved_data == 'undefined') { data.unsaved_data = 0; }
18         //If there are tabs, we allow unsaved data to be incremented only a single time from marc edit.
19         //If there are not tabs, then we are in a new window like the Copy Editor (so retain original locking).
20         if (tab) {
21             if (tab.marc_edit_allow_multiple_locks || tab.in_marc_edit == false) {
22                 data.unsaved_data++;
23                 window.oils_lock++;
24             }
25         } else {
26             data.unsaved_data++;
27             window.oils_lock++;
28         }
29
30         data.stash('unsaved_data');
31         dump('\n=-=-=-=-=\n');
32         dump('oils_unsaved_data_V for ' + location.href + '\n');
33         dump('incrementing window.oils_lock\n');
34         dump('incrementing data.unsaved_data\n');
35         dump('\twindow.oils_lock == ' + window.oils_lock + '\n');
36         dump('\tdata.unsaved_data == ' + data.unsaved_data + '\n');
37     }
38
39     function oils_unsaved_data_P(count) {
40         dump('\n=-=-=-=-=\n');
41         dump('oils_unsaved_data_P for ' + location.href + '\n');
42         if (!count) { count = 1; }
43         dump('decrementing window.oils_lock by ' + count + '\n');
44         window.oils_lock -= count;
45         if (window.oils_lock < 0) { window.oils_lock = 0; }
46         JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.stash_retrieve();
47         data.stash_retrieve();
48         if (typeof data.unsaved_data == 'undefined') { data.unsaved_data = 0; }
49         dump('decrementing data.unsaved_data by ' + count + '\n');
50         data.unsaved_data -= count;
51         if (data.unsaved_data < 0) { data.unsaved_data = 0; }
52         data.stash('unsaved_data');
53         dump('\twindow.oils_lock == ' + window.oils_lock + '\n');
54         dump('\tdata.unsaved_data == ' + data.unsaved_data + '\n');
55     }
56
57     function oils_lock_page(params) {
58         dump('\n=-=-=-=-=\n');
59         dump('oils_lock_page for ' + location.href + '\n');
60         if (!params) { params = {}; }
61         if (window.oils_lock > 0) {
62             if (!params.allow_multiple_locks) {
63                 return window.oils_lock;
64             }
65         }
66         var tabs = window.parent.parent.document.getElementById('main_tabs');
67
68         if (tabs) {
69             var idx = tabs.selectedIndex;
70             var tab = tabs.childNodes[idx];
71         }
72
73         if (typeof xulG != 'undefined') {
74             if (typeof xulG.unlock_tab == 'function') {
75                 dump('\twith xulG.lock_tab\n');
76                 xulG.lock_tab();
77                 //make sure we are not in the marc edit window
78                 var marceditRe = /\/marcedit.xul$/;
79                 if (marceditRe.exec(window.document.location)) {
80                     //We do not have to check for tab here because
81                     //the MARC editor is explicitly in a tabbed window
82                     if (tab) {
83                         tab.marc_edit_changed = true;
84                         tab.marc_edit_allow_multiple_locks = false;
85                     }
86                 }
87                 window.oils_lock++; // different window scope than the chrome of xulG.lock_tab
88             } else {
89                 dump('\twithout xulG.lock_tab\n');
90                 oils_unsaved_data_V();
91             }
92         } else {
93             dump('\twithout xulG.lock_tab\n');
94             oils_unsaved_data_V();
95         }
96         return window.oils_lock;
97     }
98
99     function oils_unlock_page(params) {
100         dump('\n=-=-=-=-=\n');
101         dump('oils_unlock_page for ' + location.href + '\n');
102
103         if (typeof xulG != 'undefined') {
104             if (typeof xulG.unlock_tab == 'function') {
105                 dump('\twith xulG.unlock_tab\n');
106                 xulG.unlock_tab();
107                 window.oils_lock--; // different window scope than the chrome of xulG.unlock_tab
108                 if (window.oils_lock < 0) { window.oils_lock = 0; }
109             } else {
110                 dump('\twithout xulG.unlock_tab\n');
111                 oils_unsaved_data_P();
112             }
113         } else {
114             dump('\twithout xulG.unlock_tab\n');
115             oils_unsaved_data_P();
116         }
117         return window.oils_lock;
118     }
119
120     window.oils_lock = 0;
121     dump('\n=-=-=-=-=\n');
122     dump('init window.oils_lock == ' + window.oils_lock + ' for ' + location.href + '\n');
123     window.addEventListener(
124         'close',
125         function(ev) {
126             try {
127                 dump('\n=-=-=-=-=\n');
128                 dump('oils_lock_page/oils_unlock_page onclose handler for ' + location.href + '\n');
129                 if (window.oils_lock > 0) {
130                     var confirmation = window.confirm($('offlineStrings').getString('menu.close_window.unsaved_data_warning'));
131                     if (!confirmation) {
132                         ev.preventDefault();
133                         return false;
134                     }
135                 }
136
137                 if (typeof xulG != 'undefined') {
138                     if (typeof xulG.unlock_tab == 'function') {
139                         xulG.unlock_tab();
140                     } else {
141                         oils_unsaved_data_P( window.oils_lock );
142                     }
143                 } else {
144                     oils_unsaved_data_P( window.oils_lock );
145                 }
146                 window.oils_lock = 0;
147                 dump('forcing window.oils_lock == ' + window.oils_lock + '\n');
148
149                 // Dispatching the window close event doesn't always close the window, even though the event does happen
150                 setTimeout(
151                     function() {
152                         try {
153                             window.close();
154                         } catch(E) {
155                             dump('Error inside global_util.js, onclose handler, setTimeout window.close KLUDGE: ' + E + '\n');
156                         }
157                     }, 0
158                 );
159
160                 return true;
161             } catch(E) {
162                 dump('Error inside global_util.js, onclose handler: ' + E + '\n');
163                 return true;
164             }
165         },
166         false
167     );
168
169     function ses(a,params) {
170         try {
171             if (!params) params = {};
172             var data;
173             if (params.data) {
174                 data = params.data; data.stash_retrieve();
175             } else {
176                 // 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
177                 JSAN.use('OpenILS.data'); data = new OpenILS.data(); data.stash_retrieve();
178             }
179
180             switch(a) {
181                 case 'staff' : return data.list.au[0]; break;
182                 case 'staff_id' : return data.list.au[0].id(); break;
183                 case 'staff_usrname' : return data.list.au[0].usrname(); break;
184                 case 'ws_name':
185                     return data.ws_name;
186                 break;
187                 case 'ws_id' :
188                     return data.list.au[0].wsid();
189                 break;
190                 case 'ws_ou' :
191                     return data.list.au[0].ws_ou();
192                 break;
193                 case 'ws_ou_shortname' :
194                     return data.hash.aou[ data.list.au[0].ws_ou() ].shortname();
195                 break;
196                 case 'authtime' :
197                     return data.session.authtime;
198                 break;
199                 case 'key':
200                 default:
201                     return data.session.key;
202                 break;
203             }
204         } catch(E) {
205             alert(location.href + '\nError in global_utils.js, ses(): ' + E);
206             throw(E);
207         }
208     }
209
210     function font_helper() {
211         try {
212             JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
213             removeCSSClass(document.documentElement,'ALL_FONTS_LARGER');
214             removeCSSClass(document.documentElement,'ALL_FONTS_SMALLER');
215             removeCSSClass(document.documentElement,'ALL_FONTS_XX_SMALL');
216             removeCSSClass(document.documentElement,'ALL_FONTS_X_SMALL');
217             removeCSSClass(document.documentElement,'ALL_FONTS_SMALL');
218             removeCSSClass(document.documentElement,'ALL_FONTS_MEDIUM');
219             removeCSSClass(document.documentElement,'ALL_FONTS_LARGE');
220             removeCSSClass(document.documentElement,'ALL_FONTS_X_LARGE');
221             removeCSSClass(document.documentElement,'ALL_FONTS_XX_LARGE');
222             addCSSClass(document.documentElement,data.global_font_adjust);
223         } catch(E) {
224             var Strings = $('offlineStrings') || $('commonStrings');
225             alert(Strings.getFormattedString('openils.global_util.font_size.error', [E]));
226         }
227     }
228
229     function oils_persist(e,cancelable) {
230         try {
231             if (!e) { return; }
232             if (typeof cancelable == 'undefined') { cancelable = false; } 
233             var evt = document.createEvent("Events");
234             evt.initEvent( 'oils_persist', false, cancelable ); // event name, bubbles, cancelable
235             e.dispatchEvent(evt);
236         } catch(E) {
237             alert('Error with oils_persist():' + E);
238         }
239     }
240
241     function oils_persist_hostname() {
242         if(location.protocol == 'oils:') {
243             JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
244             return data.server_unadorned;
245         } else {
246             return location.hostname;
247         }
248     }
249
250     function persist_helper(base_key_suffix) {
251         try {
252             if (base_key_suffix) {
253                 base_key_suffix = base_key_suffix.replace(/[^A-Za-z]/g,'_') + '_';
254             } else {
255                 base_key_suffix = '';
256             }
257             window.persist_helper_event_listeners = new EventListenerList();
258
259             function gen_event_handler(etype,node) {
260                 return function(ev) {
261                     try {
262                         oils_persist(ev.target);
263                     } catch(E) {
264                         alert('Error in persist_helper, firing virtual event oils_persist after ' + etype + ' event on ' + node.nodeName + '.id = ' + node.id + ': ' + E);
265                     }
266                 };
267             };
268
269             function gen_oils_persist_handler(bk,node) {
270                 return function(ev) {
271                     try {
272                         var target;
273                         if (ev.target.nodeName == 'command') {
274                             target = node;
275                             if (ev.explicitOriginalTarget != node) return;
276                         } else {
277                             target = ev.target;
278                             if (target == window) {
279                                 target = window.document.documentElement;
280                             }
281                         }
282                         var filename = location.pathname.split('/')[ location.pathname.split('/').length - 1 ];
283                         var base_key = 'oils_persist_' + String(oils_persist_hostname() + '_' + filename + '_' + target.getAttribute('id')).replace('/','_','g') + '_' + base_key_suffix;
284                         var attribute_list = target.getAttribute('oils_persist').split(' ');
285                         dump('on_oils_persist: <<< ' + target.nodeName + '.id = ' + target.id + '\t' + bk + '\n');
286                         for (var j = 0; j < attribute_list.length; j++) {
287                             var key = base_key + attribute_list[j];
288                             var value;
289                             try {
290                                 value = encodeURI(target.getAttribute( attribute_list[j] ));
291                             } catch(E) {
292                                 dump('Error in persist_helper with encodeURI: ' + E + '\n');
293                                 value = target.getAttribute( attribute_list[j] );
294                             }
295                             if ( attribute_list[j] == 'checked' && ['checkbox','toolbarbutton'].indexOf( target.nodeName ) > -1 ) {
296                                 value = target.checked;
297                                 dump('\t' + value + ' <== .' + attribute_list[j] + '\n');
298                             } else if ( attribute_list[j] == 'value' && ['menulist'].indexOf( target.nodeName ) > -1 ) {
299                                 value = target.value;
300                                 dump('\t' + value + ' <== .' + attribute_list[j] + '\n');
301                             } else if ( attribute_list[j] == 'value' && ['textbox'].indexOf( target.nodeName ) > -1 ) {
302                                 value = target.value;
303                                 dump('\t' + value + ' <== .' + attribute_list[j] + '\n');
304                             } else if ( attribute_list[j] == 'sizemode' && ['window'].indexOf( target.nodeName ) > -1 ) {
305                                 value = window.windowState;
306                                 dump('\t' + value + ' <== window.windowState, @' + attribute_list[j] + '\n');
307                             } else if ( attribute_list[j] == 'height' && ['window'].indexOf( target.nodeName ) > -1 ) {
308                                 value = window.outerHeight;
309                                 dump('\t' + value + ' <== window.outerHeight, @' + attribute_list[j] + '\n');
310                             } else if ( attribute_list[j] == 'width' && ['window'].indexOf( target.nodeName ) > -1 ) {
311                                 value = window.outerWidth;
312                                 dump('\t' + value + ' <== window.outerWidth, @' + attribute_list[j] + '\n');
313                             } else {
314                                 dump('\t' + value + ' <== @' + attribute_list[j] + '\n');
315                             }
316                             prefs.setCharPref( key, value );
317                             // TODO: Need to add logic for splitter repositioning, grippy state, etc.
318                             // NOTE: oils_persist_peers and oils_persist="width" on those peers can help with the elements adjacent to a splitter
319                         }
320                         if (target.hasAttribute('oils_persist_peers') && ! ev.cancelable) { // We abuse the .cancelable field on the oils_persist event to prevent looping
321                             var peer_list = target.getAttribute('oils_persist_peers').split(' ');
322                             for (var j = 0; j < peer_list.length; j++) {
323                                 dump('on_oils_persist: dispatching oils_persist to peer ' + peer_list[j] + '\n');
324                                 oils_persist( document.getElementById( peer_list[j] ), true );
325                             } 
326                         }
327                     } catch(E) {
328                         alert('Error in persist_helper() event listener for ' + bk + ': ' + E);
329                     }
330                 };
331             }
332
333             var prefs = Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces['nsIPrefBranch']);
334             var nodes = document.getElementsByAttribute('oils_persist','*');
335             for (var i = 0; i < nodes.length; i++) {
336                 var filename = location.pathname.split('/')[ location.pathname.split('/').length - 1 ];
337                 var base_key = 'oils_persist_' + String(oils_persist_hostname() + '_' + filename + '_' + nodes[i].getAttribute('id')).replace('/','_','g') + '_' + base_key_suffix;
338                 var attribute_list = nodes[i].getAttribute('oils_persist').split(' ');
339                 dump('persist_helper: >>> ' + nodes[i].nodeName + '.id = ' + nodes[i].id + '\t' + base_key + '\n');
340                 for (var j = 0; j < attribute_list.length; j++) {
341                     var key = base_key + attribute_list[j];
342                     var has_key = prefs.prefHasUserValue(key);
343                     var value;
344                     try {
345                         value = has_key ? decodeURI(prefs.getCharPref(key)) : null;
346                     } catch(E) {
347                         dump('Error in persist_helper with decodeURI: ' + E + '\n');
348                         value = has_key ? prefs.getCharPref(key) : null;
349                     }
350                     if (value == 'true') { value = true; }
351                     if (value == 'false') { value = false; }
352                     if (has_key) {
353                         if ( attribute_list[j] == 'checked' && ['checkbox','toolbarbutton'].indexOf( nodes[i].nodeName ) > -1 ) {
354                             nodes[i].checked = value; 
355                             dump('\t' + value + ' ==> .' + attribute_list[j] + '\n');
356                             if (!value) {
357                                 nodes[i].removeAttribute('checked');
358                                 dump('\tremoving @checked\n');
359                             }
360                         } else if ( attribute_list[j] == 'value' && ['textbox'].indexOf( nodes[i].nodeName ) > -1 ) {
361                             nodes[i].value = value;
362                             dump('\t' + value + ' ==> .' + attribute_list[j] + '\n');
363                         } else if ( attribute_list[j] == 'value' && ['menulist'].indexOf( nodes[i].nodeName ) > -1 ) {
364                             nodes[i].value = value;
365                             dump('\t' + value + ' ==> .' + attribute_list[j] + '\n');       
366                         } else if ( attribute_list[j] == 'sizemode' && ['window'].indexOf( nodes[i].nodeName ) > -1 ) {
367                             switch(value) {
368                                 case window.STATE_MAXIMIZED:
369                                     window.maximize();
370                                     break;
371                                 case window.STATE_MINIMIZED:
372                                     window.minimize();
373                                     break;
374                             };
375                             dump('\t' + value + ' ==> window.windowState, @' + attribute_list[j] + '\n');
376                         } else if ( attribute_list[j] == 'height' && ['window'].indexOf( nodes[i].nodeName ) > -1 ) {
377                             window.outerHeight = value;
378                             dump('\t' + value + ' ==> window.outerHeight, @' + attribute_list[j] + '\n');
379                         } else if ( attribute_list[j] == 'width' && ['window'].indexOf( nodes[i].nodeName ) > -1 ) {
380                             window.outerWidth = value;
381                             dump('\t' + value + ' ==> window.outerWidth, @' + attribute_list[j] + '\n');
382                         } else {
383                             nodes[i].setAttribute( attribute_list[j], value);
384                             dump('\t' + value + ' ==> @' + attribute_list[j] + '\n');
385                         }
386                     }
387                 }
388                 var cmd = nodes[i].getAttribute('command');
389                 var cmd_el = document.getElementById(cmd);
390                 if (nodes[i].disabled == false && nodes[i].hidden == false) {
391                     var no_poke = nodes[i].getAttribute('oils_persist_no_poke');
392                     if (no_poke && no_poke == 'true') {
393                         // Timing issue for some checkboxes; don't poke them with an event
394                         dump('\tnot poking\n');
395                     } else {
396                         if (cmd_el) {
397                             dump('\tpoking @command\n');
398                             var evt = document.createEvent("Events");
399                             evt.initEvent( 'command', true, true );
400                             cmd_el.dispatchEvent(evt);
401                         } else {
402                             dump('\tpoking\n');
403                             var evt = document.createEvent("Events");
404                             evt.initEvent( 'command', true, true );
405                             nodes[i].dispatchEvent(evt);
406                         }
407                     }
408                 }
409                 if (cmd_el) {
410                     window.persist_helper_event_listeners.add(cmd_el, 
411                         'command',
412                         gen_event_handler('command',cmd_el),
413                         false
414                     );
415                     window.persist_helper_event_listeners.add(cmd_el, 
416                         'oils_persist',
417                         gen_oils_persist_handler( base_key, nodes[i] ),
418                         false
419                     );
420                 } else {
421                     var node = nodes[i];
422                     var event_types = [];
423                     if (node.hasAttribute('oils_persist_events')) {
424                         var event_type_list = node.getAttribute('oils_persist_events').split(' ');
425                         for (var j = 0; j < event_type_list.length; j++) {
426                             event_types.push( event_type_list[j] );
427                         }
428                     } else {
429                         if (node.nodeName == 'textbox') { 
430                             event_types.push('change');
431                         } else if (node.nodeName == 'menulist') { 
432                             event_types.push('select');  
433                         } else if (node.nodeName == 'window') {
434                             event_types.push('resize'); 
435                             node = window; // xul window is an element of window.document
436                         } else {
437                             event_types.push('command'); 
438                         }
439                     }
440                     for (var j = 0; j < event_types.length; j++) {
441                         window.persist_helper_event_listeners.add(node, 
442                             event_types[j],
443                             gen_event_handler(event_types[j],node),
444                             false
445                         );
446                     }
447                     window.persist_helper_event_listeners.add(node, 
448                         'oils_persist',
449                         gen_oils_persist_handler( base_key, node ),
450                         false
451                     );
452                 }
453             }
454         } catch(E) {
455             alert('Error in persist_helper(): ' + E);
456         }
457     }
458
459     function persist_helper_cleanup() {
460         try {
461             window.persist_helper_event_listeners.removeAll();
462         } catch(E) {
463             alert('Error in persist_helper_cleanup(): ' + E);
464         }
465     }
466
467     function getKeys(o) {
468         var keys = [];
469         for (var k in o) keys.push(k);
470         return keys;
471     }
472
473     function get_contentWindow(frame) {
474         try {
475             if (frame && frame.contentWindow) {
476                 try {
477                     if (typeof frame.contentWindow.wrappedJSObject != 'undefined') {
478                                      return frame.contentWindow.wrappedJSObject;
479                           }
480                 } catch(E) {
481                     var Strings = $('offlineStrings') || $('commonStrings');
482                     alert(Strings.getFormattedString('openils.global_util.content_window_jsobject.error', [frame, E]));
483                 }
484                 return frame.contentWindow;
485             } else {
486                 return null;
487             }
488         } catch(E) {
489             var Strings = $('offlineStrings') || $('commonStrings');
490             alert(Strings.getFormattedString('openils.global_util.content_window.error', [frame, E]));
491         }
492     }
493
494     function xul_param(param_name,_params) {
495         /* 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 */
496         try {
497             //dump('xul_param('+param_name+','+js2JSON(_params)+')\n');
498             var value = undefined; if (!_params) _params = {};
499             if (typeof _params.no_cgi == 'undefined') {
500                 var cgi = new CGI();
501                 if (cgi.param(param_name)) {
502                     var x = cgi.param(param_name);
503                     //dump('\tfound via location.href = ' + x + '\n');
504                     if (typeof _params.JSON2js_if_cgi != 'undefined') {
505                         x = JSON2js( x );
506                         //dump('\tJSON2js = ' + x + '\n');
507                     }
508                     if (typeof _params.concat == 'undefined') {
509                         //alert(param_name + ' x = ' + x);
510                         return x; // value
511                     } else {
512                         if (value) {
513                             if (value.constructor != Array) value = [ value ];
514                             value = value.concat(x);
515                         } else {
516                             value = x;
517                         }
518                     }
519                 }
520             }
521             if (typeof _params.no_xulG == 'undefined') {
522                 if (typeof xulG == 'object' && typeof xulG[ param_name ] != 'undefined') {
523                     var x = xulG[ param_name ];
524                     //dump('\tfound via xulG = ' + x + '\n');
525                     if (typeof _params.JSON2js_if_xulG != 'undefined') {
526                         x = JSON2js( x );
527                         //dump('\tJSON2js = ' + x + '\n');
528                     }
529                     if (typeof _params.concat == 'undefined') {
530                         //alert(param_name + ' x = ' + x);
531                         return x; // value
532                     } else {
533                         if (value) {
534                             if (value.constructor != Array) value = [ value ];
535                             value = value.concat(x);
536                         } else {
537                             value = x;
538                         }
539                     }
540                 }
541             }
542             if (typeof _params.no_xpcom == 'undefined') {
543                 /* 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 */
544                 if (typeof _params.stash_name != 'undefined') { 
545                     JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
546                     if (typeof data[ _params.stash_name ] != 'undefined') {
547                         var x = data[ _params.stash_name ];
548                         //dump('\tfound via xpcom = ' + x + '\n');
549                         if (typeof _params.JSON2js_if_xpcom != 'undefined') {
550                             x = JSON2js( x );
551                             //dump('\tJSON2js = ' + x + '\n');
552                         }
553                         if (_params.clear_xpcom) { 
554                             data[ _params.stash_name ] = undefined; data.stash( _params.stash_name ); 
555                         }
556                         if (typeof _params.concat == 'undefined') {
557                             //alert(param_name + ' x = ' + x);
558                             return x; // value
559                         } else {
560                             if (value) {
561                                 if (value.constructor != Array) value = [ value ];
562                                 value = value.concat(x);
563                             } else {
564                                 value = x;
565                             }
566                         }
567                     }
568                 }
569             }
570             //alert(param_name + ' value = ' + value);
571             return value;
572         } catch(E) {
573             dump('xul_param error: ' + E + '\n');
574         }
575     }
576
577     function get_bool(a) {
578         // Normal javascript interpretation except 'f' == false, per postgres, and 'F' == false, and '0' == false (newer JSON is returning '0' instead of 0 in cases)
579         // So false includes 'f', '', '0', 0, null, and undefined
580         if (a == 'f') return false;
581         if (a == 'F') return false;
582         if (a == '0') return false;
583         if (a) return true; else return false;
584     }
585
586     function get_localized_bool(a) {
587         var Strings = $('offlineStrings') || $('commonStrings');
588         return get_bool(a) ? Strings.getString('common.yes') : Strings.getString('common.no');
589     }
590
591     function get_db_true() {
592         return 't';
593     }
594
595     function get_db_false() {
596         return 'f';
597     }
598
599     function copy_to_clipboard(ev) {
600         try {
601             var text;
602             if (typeof ev == 'object') {
603                 if (typeof ev.target != 'undefined') {
604                     if (typeof ev.target.textContent != 'undefined') if (ev.target.textContent) text = ev.target.textContent;
605                     if (typeof ev.target.value != 'undefined') if (ev.target.value) text = ev.target.value;
606                 }
607             } else if (typeof ev == 'string') {
608                 text = ev;
609             }
610             const gClipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"]
611                 .getService(Components.interfaces.nsIClipboardHelper);
612             gClipboardHelper.copyString(text);
613             var Strings = $('offlineStrings') || $('commonStrings');
614             // alert(Strings.getFormattedString('openils.global_util.clipboard', [text]));
615         } catch(E) {
616             var Strings = $('offlineStrings') || $('commonStrings');
617             alert(Strings.getFormattedString('openils.global_util.clipboard.error', [E]));    
618         }
619     }
620
621     function clear_the_cache() {
622         try {
623             var cacheClass         = Components.classes["@mozilla.org/network/cache-service;1"];
624             var cacheService    = cacheClass.getService(Components.interfaces.nsICacheService);
625             cacheService.evictEntries(Components.interfaces.nsICache.STORE_ON_DISK);
626             cacheService.evictEntries(Components.interfaces.nsICache.STORE_IN_MEMORY);
627         } catch(E) {
628             var Strings = $('offlineStrings') || $('commonStrings');
629             alert(Strings.getFormattedString('openils.global_util.clear_cache.error', [E]));
630         }
631     }
632
633     function toOpenWindowByType(inType, uri) {
634         var winopts = "chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar";
635         window.open(uri, "_blank", winopts);
636     }
637
638     function url_prefix(url) {
639         var base_url = url.match(/^[^?/|]+/);
640         if(base_url) {
641             base_url = base_url[0];
642             if(urls[base_url])
643                 url = url.replace(/^[^?/|]+\|?/, urls[base_url]);
644         }
645         if (url.match(/^\//)) url = urls.remote + url;
646         if (! url.match(/^(http|https|chrome|oils):\/\//) && ! url.match(/^data:/) ) url = 'http://' + url;
647         dump('url_prefix = ' + url + '\n');
648         return url;
649     }
650
651     function widget_prompt(node,args) {
652         // args is an object that may contain the following keys: title, desc, ok_label, ok_accesskey, cancel_label, cancel_accesskey, access, method
653         // access may contain 'property' or 'attribute' or 'method' for retrieving the value from the node
654         // if 'method', then the method key will reference a function that returns the value
655         try {
656             if (!node) { return false; }
657             if (!args) { args = {}; }
658             args[ 'widget' ] = node;
659
660             var url = location.protocol == 'chrome'
661                 ? 'chrome://open_ils_staff_client/content/util/widget_prompt.xul'
662                 : '/xul/server/util/widget_prompt.xul';
663
664             JSAN.use('util.window'); var win = new util.window();
665             var my_xulG = win.open(
666                 url,
667                 args.title || 'widget_prompt',
668                 'chrome,modal',
669                 args
670             );
671
672             if (my_xulG.status == 'incomplete') {
673                 return false;
674             } else {
675                 return my_xulG.value;
676             }
677         } catch(E) {
678             alert('Error in global_utils.js, widget_prompt(): ' + E);
679         }
680     }
681
682
683     window.addEventListener(
684         'load',
685         function(ev) {
686             try {
687                 if (window.oils_autoloaded) { return; }
688                 JSAN.use('addon.autoloader');
689                 window.oils_autoloaded = new addon.autoloader();
690             } catch(E) {
691                 dump('Error in global_util.js with addon.autoloader: ' + E + '\n');
692             }
693         },
694         false
695     );