2fbe422c3b94cc290e56da2f9fc14444be524118
[working/Evergreen.git] / Open-ILS / xul / staff_client / chrome / content / cat / opac.js
1 var docid; var marc_html; var top_pane; var bottom_pane; var opac_frame; var opac_url;
2
3 var marc_view_reset = true;
4 var marc_edit_reset = true;
5 var copy_browser_reset = true;
6 var manage_parts_reset = true;
7 var manage_multi_home_reset = true;
8 var hold_browser_reset = true;
9 var serctrl_view_reset = true;
10
11 function $(id) { return document.getElementById(id); }
12
13 function my_init() {
14     try {
15         netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
16         if (typeof JSAN == 'undefined') { throw(document.getElementById('offlineStrings').getString('common.jsan.missing')); }
17         JSAN.errorLevel = "die"; // none, warn, or die
18         JSAN.addRepository('..');
19         JSAN.use('util.error'); g.error = new util.error();
20         g.error.sdump('D_TRACE','my_init() for cat/opac.xul');
21
22         JSAN.use('OpenILS.data'); g.data = new OpenILS.data(); g.data.init({'via':'stash'});
23         XML_HTTP_SERVER = g.data.server_unadorned;
24
25         // Pull in local customizations
26         var r = new XMLHttpRequest();
27         r.open("GET", xulG.url_prefix('/xul/server/skin/custom.js'), false);
28         r.send(null);
29         if (r.status == 200) {
30             dump('Evaluating /xul/server/skin/custom.js\n');
31             eval( r.responseText );
32         }
33
34         window.help_context_set_locally = true;
35
36         JSAN.use('util.network'); g.network = new util.network();
37
38         g.cgi = new CGI();
39         try { authtime = g.cgi.param('authtime') || xulG.authtime; } catch(E) { g.error.sdump('D_ERROR',E); }
40         try { docid = g.cgi.param('docid') || xulG.docid; } catch(E) { g.error.sdump('D_ERROR',E); }
41         try { opac_url = g.cgi.param('opac_url') || xulG.opac_url; } catch(E) { g.error.sdump('D_ERROR',E); }
42         try { g.view_override = g.cgi.param('default_view') || xulG.default_view; } catch(E) { g.error.sdump('D_ERROR',E); }
43
44         JSAN.use('util.deck');
45         top_pane = new util.deck('top_pane');
46         bottom_pane = new util.deck('bottom_pane');
47
48         set_opac();
49
50     } catch(E) {
51         var err_msg = document.getElementById("offlineStrings").getFormattedString("common.exception", ["cat/opac.xul", E]);
52         try { g.error.sdump('D_ERROR',err_msg); } catch(E) { dump(err_msg); }
53         alert(err_msg);
54     }
55 }
56
57 function default_focus() {
58     opac_wrapper_set_help_context(); 
59 }
60
61 function opac_wrapper_set_help_context() {
62     try {
63         dump('Entering opac.js, opac_wrapper_set_help_context\n');
64         var cw = bottom_pane.get_contentWindow(); 
65         if (cw && typeof cw['location'] != 'undefined') {
66             if (typeof cw.help_context_set_locally == 'undefined') {
67                 var help_params = {
68                     'protocol' : cw.location.protocol,
69                     'hostname' : cw.location.hostname,
70                     'port' : cw.location.port,
71                     'pathname' : cw.location.pathname,
72                     'src' : ''
73                 };
74                 xulG.set_help_context(help_params);
75             } else {
76                 dump('\tcw.help_context_set_locally = ' + cw.help_context_set_locally + '\n');
77                 if (typeof cw.default_focus == 'function') {
78                     cw.default_focus();
79                 }
80             }
81         } else {
82             dump('opac.js: problem in opac_wrapper_set_help_context(): bottom_pane = ' + bottom_pane + ' cw = ' + cw + '\n');
83             dump('\tcw.location = ' + cw.location + '\n');
84         }
85     } catch(E) {
86         // We can expect some errors here if this called before the DOM is ready.  Easiest to just trap and ignore
87         dump('Error in opac.js, opac_wrapper_set_help_context(): ' + E + '\n');
88     }
89 }
90
91 function set_brief_view() {
92     var url = xulG.url_prefix( urls.XUL_BIB_BRIEF ) + '?docid=' + window.escape(docid); 
93     dump('spawning ' + url + '\n');
94
95     var content_params = {
96         'set_tab_name' : function(n) {
97             if (typeof window.xulG == 'object' && typeof window.xulG.set_tab_name == 'function') {
98                 try { window.xulG.set_tab_name(document.getElementById('offlineStrings').getFormattedString("cat.bib_record", [n])); } catch(E) { alert(E); }
99             } else {
100                 dump('no set_tab_name\n');
101             }
102         }
103     };
104
105     ["url_prefix", "new_tab", "set_tab", "close_tab", "new_patron_tab",
106         "set_patron_tab", "volume_item_creator", "get_new_session",
107         "holdings_maintenance_tab", "open_chrome_window", "url_prefix",
108         "network_meter", "page_meter", "set_statusbar", "set_help_context"
109     ].forEach(function(k) { content_params[k] = xulG[k]; });
110
111     top_pane.set_iframe( 
112         url,
113         {},
114         content_params
115     );
116 }
117
118 function set_marc_view() {
119     g.view = 'marc_view';
120     if (marc_view_reset) {
121         bottom_pane.reset_iframe( xulG.url_prefix( urls.XUL_MARC_VIEW ) + '?docid=' + window.escape(docid),{},xulG);
122         marc_view_reset = false;
123     } else {
124         bottom_pane.set_iframe( xulG.url_prefix( urls.XUL_MARC_VIEW ) + '?docid=' + window.escape(docid),{},xulG);
125     }
126     opac_wrapper_set_help_context(); 
127     bottom_pane.get_contentWindow().addEventListener('load',opac_wrapper_set_help_context,false);
128 }
129
130 function set_marc_edit() {
131     g.view = 'marc_edit';
132     var a =    xulG.url_prefix( urls.XUL_MARC_EDIT );
133     var b =    {};
134     var c =    {
135             'marc_control_number_identifier' : g.data.hash.aous['cat.marc_control_number_identifier'] || 'Set cat.marc_control_number_identifier in Library Settings',
136             'record' : { 'url' : '/opac/extras/supercat/retrieve/marcxml/record/' + docid, "id": docid, "rtype": "bre" },
137             'fast_add_item' : function(doc_id,cn_label,cp_barcode) {
138                 try {
139                     var cat = { util: {} }; /* FIXME: kludge since we can't load remote JSAN libraries into chrome */
140                     cat.util.spawn_copy_editor = function(params) {
141                         try {
142                             if (!params.copy_ids && !params.copies) return;
143                             if (params.copy_ids && params.copy_ids.length == 0) return;
144                             if (params.copies && params.copies.length == 0) return;
145                             if (params.copy_ids) params.copy_ids = js2JSON(params.copy_ids); // legacy
146                             if (!params.caller_handles_update) params.handle_update = 1; // legacy
147
148                             var obj = {};
149                             JSAN.use('util.network'); obj.network = new util.network();
150                             JSAN.use('util.error'); obj.error = new util.error();
151                         
152                             var title = '';
153                             if (params.copy_ids && params.copy_ids.length > 1 && params.edit == 1)
154                                 title = $("offlineStrings").getString('staff.cat.util.copy_editor.batch_edit');
155                             else if(params.copies && params.copies.length > 1 && params.edit == 1)
156                                 title = $("offlineStrings").getString('staff.cat.util.copy_editor.batch_view');
157                             else if(params.copy_ids && params.copy_ids.length == 1)
158                                 title = $("offlineStrings").getString('staff.cat.util.copy_editor.edit');
159                             else
160                                 title = $("offlineStrings").getString('staff.cat.util.copy_editor.view');
161
162                             JSAN.use('util.window'); var win = new util.window();
163                             var my_xulG = win.open(
164                                 (urls.XUL_COPY_EDITOR),
165                                 title,
166                                 'chrome,modal,resizable',
167                                 params
168                             );
169                             if (!my_xulG.copies && params.edit) {
170                             } else {
171                                 return my_xulG.copies;
172                             }
173                             return [];
174                         } catch(E) {
175                             JSAN.use('util.error'); var error = new util.error();
176                             error.standard_unexpected_error_alert('Error in chrome/content/cat/opac.js, cat.util.spawn_copy_editor',E);
177                         }
178                     }
179                     cat.util.fast_item_add = function(doc_id,cn_label,cp_barcode) {
180                         var error;
181                         try {
182
183                             JSAN.use('util.error'); error = new util.error();
184                             JSAN.use('util.network'); var network = new util.network();
185
186                             var acn_blob = network.simple_request(
187                                 'FM_ACN_FIND_OR_CREATE',
188                                 [ ses(), cn_label, doc_id, ses('ws_ou') ]
189                             );
190
191                             if (typeof acn_blob.ilsevent != 'undefined') {
192                                 error.standard_unexpected_error_alert('Error in chrome/content/cat/opac.js, cat.util.fast_item_add', acn_blob);
193                                 return;
194                             }
195
196                             // Get the default copy status; default to available if unset, per 1.6
197                             var fast_ccs = g.data.hash.aous['cat.default_copy_status_fast'] || 0;
198
199                             var copy_obj = new acp();
200                             copy_obj.id( -1 );
201                             copy_obj.isnew('1');
202                             copy_obj.barcode( cp_barcode );
203                             copy_obj.call_number( acn_blob.acn_id );
204                             copy_obj.circ_lib( ses('ws_ou') );
205                             /* FIXME -- use constants */
206                             copy_obj.deposit(0);
207                             copy_obj.price(0);
208                             copy_obj.deposit_amount(0);
209                             copy_obj.fine_level(2); // Normal
210                             copy_obj.loan_duration(2); // Normal
211                             copy_obj.location(1); // Stacks
212                             copy_obj.status(fast_ccs);
213                             copy_obj.circulate(get_db_true());
214                             copy_obj.holdable(get_db_true());
215                             copy_obj.opac_visible(get_db_true());
216                             copy_obj.ref(get_db_false());
217
218                             JSAN.use('util.window'); var win = new util.window();
219                             return cat.util.spawn_copy_editor( { 'handle_update' : 1, 'edit' : 1, 'docid' : doc_id, 'copies' : [ copy_obj ] });
220
221                         } catch(E) {
222                             if (error) error.standard_unexpected_error_alert('Error in chrome/content/cat/opac.js, cat.util.fast_item_add #2',E); else alert('FIXME: ' + E);
223                         }
224                     }
225                     return cat.util.fast_item_add(doc_id,cn_label,cp_barcode);
226                 } catch(E) {
227                     alert('Error in chrome/content/cat/opac.js, set_marc_edit, fast_item_add: ' + E);
228                 }
229             },
230             'save' : {
231                 'label' : document.getElementById('offlineStrings').getString('cat.save_record'),
232                 'func' : function (new_marcxml) {
233                     try {
234                         var r = g.network.simple_request('MARC_XML_RECORD_UPDATE', [ ses(), docid, new_marcxml ]);
235                         marc_view_reset = true;
236                         copy_browser_reset = true;
237                         hold_browser_reset = true;
238                         if (typeof r.ilsevent != 'undefined') {
239                             throw(r);
240                         } else {
241                             return {
242                                 'id' : r.id(),
243                                 'oncomplete' : function() {}
244                             };
245                         }
246                     } catch(E) {
247                             g.error.standard_unexpected_error_alert(document.getElementById('offlineStrings').getString("cat.save.failure"), E);
248                     }
249                 }
250             },
251             'lock_tab' : xulG.lock_tab,
252             'unlock_tab' : xulG.unlock_tab
253         };
254     if (marc_edit_reset) {
255         bottom_pane.reset_iframe( a,b,c );
256         marc_edit_reset = false;
257     } else {
258         bottom_pane.set_iframe( a,b,c );
259     }
260     opac_wrapper_set_help_context(); 
261     bottom_pane.get_contentWindow().addEventListener('load',opac_wrapper_set_help_context,false);
262 }
263
264 function set_copy_browser() {
265     g.view = 'copy_browser';
266     if (copy_browser_reset) {
267         bottom_pane.reset_iframe( xulG.url_prefix( urls.XUL_COPY_VOLUME_BROWSE ) + '?docid=' + window.escape(docid),{},xulG);
268         copy_browser_reset =false;
269     } else {
270         bottom_pane.set_iframe( xulG.url_prefix( urls.XUL_COPY_VOLUME_BROWSE ) + '?docid=' + window.escape(docid),{},xulG);
271     }
272     opac_wrapper_set_help_context(); 
273     bottom_pane.get_contentWindow().addEventListener('load',opac_wrapper_set_help_context,false);
274 }
275
276 function set_hold_browser() {
277     g.view = 'hold_browser';
278     if (hold_browser_reset) {
279         bottom_pane.reset_iframe( xulG.url_prefix( urls.XUL_HOLDS_BROWSER ) + '?docid=' + window.escape(docid),{},xulG);
280         hold_browser_reset = false;
281     } else {
282         bottom_pane.set_iframe( xulG.url_prefix( urls.XUL_HOLDS_BROWSER ) + '?docid=' + window.escape(docid),{},xulG);
283     }
284     opac_wrapper_set_help_context(); 
285     bottom_pane.get_contentWindow().addEventListener('load',opac_wrapper_set_help_context,false);
286 }
287
288
289 function open_acq_orders() {
290     try {
291         var content_params = {
292             "session": ses(),
293             "authtime": ses("authtime"),
294             "no_xulG": false,
295             "show_nav_buttons": true,
296             "show_print_button": false
297         };
298
299         ["url_prefix", "new_tab", "set_tab", "close_tab", "new_patron_tab",
300             "set_patron_tab", "volume_item_creator", "get_new_session",
301             "holdings_maintenance_tab", "set_tab_name", "open_chrome_window",
302             "url_prefix", "network_meter", "page_meter", "set_statusbar",
303             "set_help_context"
304         ].forEach(function(k) { content_params[k] = xulG[k]; });
305
306         var loc = urls.XUL_BROWSER + "?url=" + window.escape(
307             xulG.url_prefix("/eg/acq/lineitem/related/") +
308             docid + "?target=bib"
309         );
310         xulG.new_tab(
311             loc, {
312                 "tab_name": $("offlineStrings").getString(
313                     "staff.cat.opac.related_items"
314                 ),
315                 "browser": false
316             }, content_params
317         );
318     } catch (E) {
319         g.error.sdump("D_ERROR", E);
320     }
321 }
322
323 function open_alt_serial_mgmt() {
324     try {
325         var content_params = {
326             "session": ses(),
327             "authtime": ses("authtime"),
328             "show_nav_buttons": true,
329             "no_xulG": false,
330             "show_print_button": false
331         };
332
333         ["url_prefix", "new_tab", "set_tab", "close_tab", "new_patron_tab",
334             "set_patron_tab", "volume_item_creator", "get_new_session",
335             "holdings_maintenance_tab", "set_tab_name", "open_chrome_window",
336             "url_prefix", "network_meter", "page_meter", "set_statusbar",
337             "set_help_context"
338         ].forEach(function(k) { content_params[k] = xulG[k]; });
339
340         var loc = urls.XUL_BROWSER + "?url=" + window.escape(
341             xulG.url_prefix("/eg/serial/list_subscription?record_entry=") +
342             docid
343         );
344         xulG.new_tab(
345             loc, {
346                 "tab_name": $("offlineStrings").getString(
347                     "staff.cat.opac.serial_alt_mgmt"
348                 ),
349                 "browser": false
350             }, content_params
351         );
352     } catch (E) {
353         g.error.sdump("D_ERROR", E);
354     }
355 }
356
357 function set_opac() {
358     g.view = 'opac';
359     try {
360         var content_params = { 
361             'show_nav_buttons' : true,
362             'show_print_button' : true,
363             'passthru_content_params' : { 
364                 'authtoken' : ses(), 
365                 'authtime' : ses('authtime'),
366                 'window_open' : function(a,b,c) {
367                     try {
368                         netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
369                         return window.open(a,b,c);
370                     } catch(E) {
371                         g.error.standard_unexpected_error_alert('window_open',E);
372                     }
373                 }
374             },
375             'on_url_load' : function(f) {
376                 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
377                 var win;
378                 try {
379                     if (typeof f.contentWindow.wrappedJSObject.attachEvt != 'undefined') {
380                         win = f.contentWindow.wrappedJSObject;
381                     } else {
382                         win = f.contentWindow;
383                     }
384                 } catch(E) {
385                     win = f.contentWindow;
386                 }
387                 win.attachEvt("rdetail", "recordRetrieved",
388                     function(id){
389                         try {
390                             if (docid == id) return;
391                             docid = id;
392                             refresh_display(id);
393                         } catch(E) {
394                             g.error.standard_unexpected_error_alert('rdetail -> recordRetrieved',E);
395                         }
396                     }
397                 );
398                 
399                 g.f_record_start = null; g.f_record_prev = null; g.f_record_next = null; g.f_record_end = null;
400                 $('record_start').disabled = true; $('record_next').disabled = true;
401                 $('record_prev').disabled = true; $('record_end').disabled = true;
402                 $('record_pos').setAttribute('value','');
403
404                 win.attachEvt("rdetail", "nextPrevDrawn",
405                     function(rIndex,rCount){
406                         $('record_pos').setAttribute('value', document.getElementById('offlineStrings').getFormattedString('cat.record.counter', [(1+rIndex), rCount ? rCount : 1]));
407                         if (win.rdetailNext) {
408                             g.f_record_next = function() { 
409                                 g.view_override = g.view; 
410                                 win.rdetailNext(); 
411                             }
412                             $('record_next').disabled = false;
413                         }
414                         if (win.rdetailPrev) {
415                             g.f_record_prev = function() { 
416                                 g.view_override = g.view; 
417                                 win.rdetailPrev(); 
418                             }
419                             $('record_prev').disabled = false;
420                         }
421                         if (win.rdetailStart) {
422                             g.f_record_start = function() { 
423                                 g.view_override = g.view; 
424                                 win.rdetailStart(); 
425                             }
426                             $('record_start').disabled = false;
427                         }
428                         if (win.rdetailEnd) {
429                             g.f_record_end = function() { 
430                                 g.view_override = g.view; 
431                                 win.rdetailEnd(); 
432                             }
433                             $('record_end').disabled = false;
434                         }
435                     }
436                 );
437
438                 $('mfhd_add').setAttribute('oncommand','create_mfhd()');
439                 var mfhd_edit_menu = $('mfhd_edit');
440                 var mfhd_delete_menu = $('mfhd_delete');
441
442                 // clear menus on subsequent loads
443                 if (mfhd_edit_menu.firstChild) {
444                     mfhd_edit_menu.removeChild(mfhd_edit_menu.firstChild);
445                     mfhd_delete_menu.removeChild(mfhd_delete_menu.firstChild);
446                 }
447
448                 mfhd_edit_menu.disabled = true;
449                 mfhd_delete_menu.disabled = true;
450
451                 win.attachEvt("rdetail", "MFHDDrawn",
452                     function() {
453                         if (win.mfhdDetails && win.mfhdDetails.length > 0) {
454                             g.mfhd = {};
455                             g.mfhd.details = win.mfhdDetails;
456                             mfhd_edit_menu.disabled = false;
457                             mfhd_delete_menu.disabled = false;
458                             for (var i = 0; i < win.mfhdDetails.length; i++) {
459                                 var mfhd_details = win.mfhdDetails[i];
460                                 var num = mfhd_details.entryNum;
461                                 num++;
462                                 var label = mfhd_details.label + ' (' + num + ')';
463                                 var item = mfhd_edit_menu.appendItem(label);
464                                 item.setAttribute('oncommand','open_mfhd_editor('+mfhd_details.id+')');
465                                 item = mfhd_delete_menu.appendItem(label);
466                                 item.setAttribute('oncommand','delete_mfhd('+mfhd_details.id+')');
467                             }
468                         }
469                     }
470                 );
471             },
472             'url_prefix' : xulG.url_prefix,
473         };
474         content_params.new_tab = xulG.new_tab;
475         content_params.set_tab = xulG.set_tab;
476         content_params.close_tab = xulG.close_tab;
477         content_params.lock_tab = xulG.lock_tab;
478         content_params.unlock_tab = xulG.unlock_tab;
479         content_params.inspect_tab = xulG.inspect_tab;
480         content_params.new_patron_tab = xulG.new_patron_tab;
481         content_params.set_patron_tab = xulG.set_patron_tab;
482         content_params.volume_item_creator = xulG.volume_item_creator;
483         content_params.get_new_session = xulG.get_new_session;
484         content_params.holdings_maintenance_tab = xulG.holdings_maintenance_tab;
485         content_params.set_tab_name = xulG.set_tab_name;
486         content_params.open_chrome_window = xulG.open_chrome_window;
487         content_params.url_prefix = xulG.url_prefix;
488         content_params.network_meter = xulG.network_meter;
489         content_params.page_meter = xulG.page_meter;
490         content_params.set_statusbar = xulG.set_statusbar;
491         content_params.set_help_context = xulG.set_help_context;
492
493         if (opac_url) { content_params.url = opac_url; } else { content_params.url = xulG.url_prefix( urls.browser ); }
494         browser_frame = bottom_pane.set_iframe( xulG.url_prefix(urls.XUL_BROWSER) + '?name=Catalog', {}, content_params);
495         /* // Remember to use the REMOTE_BROWSER if we ever try to move this to remote xul again
496         browser_frame = bottom_pane.set_iframe( xulG.url_prefix(urls.XUL_REMOTE_BROWSER) + '?name=Catalog', {}, content_params);
497         */
498     } catch(E) {
499         g.error.sdump('D_ERROR','set_opac: ' + E);
500     }
501     opac_wrapper_set_help_context(); 
502     bottom_pane.get_contentWindow().addEventListener('load',opac_wrapper_set_help_context,false);
503 }
504
505 function set_serctrl_view() {
506     g.view = 'serctrl_view';
507     if (serctrl_view_reset) {
508         bottom_pane.reset_iframe( xulG.url_prefix( urls.XUL_SERIAL_SERCTRL_MAIN ) + '?docid=' + window.escape(docid), {}, xulG);
509         serctrl_view_reset =false;
510     } else {
511         bottom_pane.set_iframe( xulG.url_prefix( urls.XUL_SERIAL_SERCTRL_MAIN ) + '?docid=' + window.escape(docid), {}, xulG);
512     }
513 }
514
515 function create_mfhd() {
516     try {
517         JSAN.use('util.window'); var win = new util.window();
518         var select_aou_window = win.open(
519             xulG.url_prefix(urls.XUL_SERIAL_SELECT_AOU),
520             '_blank',
521             'chrome,resizable,modal,centerscreen',
522             {'server_unadorned' : g.data.server_unadorned}
523         );
524         if (!select_aou_window.create_mfhd_aou) {
525             return;
526         }
527         var r = g.network.simple_request(
528                 'MFHD_XML_RECORD_CREATE',
529                 [ ses(), 1, select_aou_window.create_mfhd_aou, docid ]
530             );
531         if (typeof r.ilsevent != 'undefined') {
532             throw(r);
533         }
534         alert("MFHD record created."); //TODO: better success message
535         //TODO: refresh opac display
536     } catch(E) {
537         g.error.standard_unexpected_error_alert("Create MFHD failed", E); //TODO: better error handling
538     }
539 }
540
541 function delete_mfhd(sre_id) {
542     if (g.error.yns_alert(
543         document.getElementById('offlineStrings').getFormattedString('serial.delete_record.confirm', [sre_id]),
544         document.getElementById('offlineStrings').getString('cat.opac.delete_record'),
545         document.getElementById('offlineStrings').getString('cat.opac.delete'),
546         document.getElementById('offlineStrings').getString('cat.opac.cancel'),
547         null,
548         document.getElementById('offlineStrings').getString('cat.opac.record_deleted.confirm')) == 0) {
549         var robj = g.network.request(
550                 'open-ils.permacrud',
551                 'open-ils.permacrud.delete.sre',
552                 [ses(),sre_id]);
553         if (typeof robj.ilsevent != 'undefined') {
554             alert(document.getElementById('offlineStrings').getFormattedString('cat.opac.record_deleted.error',  [docid, robj.textcode, robj.desc]) + '\n');
555         } else {
556             alert(document.getElementById('offlineStrings').getString('cat.opac.record_deleted'));
557             //TODO: refresh opac display
558         }
559     }
560 }
561
562 function open_mfhd_editor(sre_id) {
563     try {
564         var r = g.network.simple_request(
565                 'FM_SRE_RETRIEVE',
566                 [ ses(), sre_id ]
567               );
568         if (typeof r.ilsevent != 'undefined') {
569             throw(r);
570         }
571         open_marc_editor(r, 'MFHD');
572     } catch(E) {
573         g.error.standard_unexpected_error_alert("Create MFHD failed", E); //TODO: better error handling
574     }
575 }
576
577 function open_marc_editor(rec, label) {
578     win = window.open( xulG.url_prefix('/xul/server/cat/marcedit.xul') );
579
580     win.xulG = {
581         record : {marc : rec.marc()},
582         save : {
583             label: 'Save ' + label,
584             func: function(xmlString) {  // TODO: switch to pcrud, or define an sre update method in Serial.pm?
585                 var method = 'open-ils.permacrud.update.' + rec.classname;
586                 rec.marc(xmlString);
587                 g.network.request(
588                     'open-ils.permacrud', method,
589                     [ses(), rec]
590                 );
591             }
592         }
593     };
594 }
595
596 function bib_in_new_tab() {
597     try {
598         var url = browser_frame.contentWindow.g.browser.controller.view.browser_browser.contentWindow.wrappedJSObject.location.href;
599         var content_params = { 'session' : ses(), 'authtime' : ses('authtime'), 'opac_url' : url };
600         content_params.url_prefix = xulG.url_prefix;
601         content_params.new_tab = xulG.new_tab;
602         content_params.set_tab = xulG.set_tab;
603         content_params.close_tab = xulG.close_tab;
604         content_params.lock_tab = xulG.lock_tab;
605         content_params.unlock_tab = xulG.unlock_tab;
606         content_params.inspect_tab = xulG.inspect_tab;
607         content_params.new_patron_tab = xulG.new_patron_tab;
608         content_params.set_patron_tab = xulG.set_patron_tab;
609         content_params.volume_item_creator = xulG.volume_item_creator;
610         content_params.get_new_session = xulG.get_new_session;
611         content_params.holdings_maintenance_tab = xulG.holdings_maintenance_tab;
612         content_params.set_tab_name = xulG.set_tab_name;
613         content_params.open_chrome_window = xulG.open_chrome_window;
614         content_params.url_prefix = xulG.url_prefix;
615         content_params.network_meter = xulG.network_meter;
616         content_params.page_meter = xulG.page_meter;
617         content_params.set_statusbar = xulG.set_statusbar;
618         content_params.set_help_context = xulG.set_help_context;
619
620         xulG.new_tab(xulG.url_prefix(urls.XUL_OPAC_WRAPPER), {}, content_params);
621     } catch(E) {
622         g.error.sdump('D_ERROR',E);
623     }
624 }
625
626 function batch_receive_in_new_tab() {
627     try {
628         var content_params = {"session": ses(), "authtime": ses("authtime")};
629
630         ["url_prefix", "new_tab", "set_tab", "close_tab", "new_patron_tab",
631             "set_patron_tab", "volume_item_creator", "get_new_session",
632             "holdings_maintenance_tab", "set_tab_name", "open_chrome_window",
633             "url_prefix", "network_meter", "page_meter", "set_statusbar",
634             "set_help_context"
635         ].forEach(function(k) { content_params[k] = xulG[k]; });
636
637         xulG.new_tab(
638             xulG.url_prefix(urls.XUL_SERIAL_BATCH_RECEIVE) +
639                 "?docid=" + window.escape(docid), {
640                 "tab_name": $("offlineStrings").getString(
641                     "menu.cmd_serial_batch_receive.tab"
642                 )
643             }, content_params
644         );
645     } catch (E) {
646         g.error.sdump("D_ERROR", E);
647     }
648 }
649
650 function remove_me() {
651     var url = xulG.url_prefix( urls.XUL_BIB_BRIEF ) + '?docid=' + window.escape(docid);
652     dump('removing ' + url + '\n');
653     try { top_pane.remove_iframe( url ); } catch(E) { dump(E + '\n'); }
654     $('nav').setAttribute('hidden','true');
655 }
656
657 function add_to_bucket() {
658     JSAN.use('util.window'); var win = new util.window();
659     win.open(
660         xulG.url_prefix(urls.XUL_RECORD_BUCKETS_QUICK),
661         '_blank',
662         'chrome,resizable,modal,centerscreen',
663         {
664             record_ids: [ docid ]
665         }
666     );
667 }
668
669 function mark_for_overlay() {
670     g.data.marked_record = docid;
671     g.data.stash('marked_record');
672     var robj = g.network.simple_request('MODS_SLIM_RECORD_RETRIEVE.authoritative',[docid]);
673     if (typeof robj.ilsevent == 'undefined') {
674         g.data.marked_record_mvr = robj;
675     } else {
676         g.data.marked_record_mvr = null;
677         g.error.standard_unexpected_error_alert('in mark_for_overlay',robj);
678     }
679     g.data.stash('marked_record_mvr');
680     if (g.data.marked_record_mvr) {
681         alert(document.getElementById('offlineStrings').getFormattedString('cat.opac.record_marked_for_overlay.tcn.alert',[ g.data.marked_record_mvr.tcn() ]));
682         xulG.set_statusbar(
683             1,
684             $("offlineStrings").getFormattedString('staff.cat.z3950.marked_record_for_overlay_indicator.tcn.label',[g.data.marked_record_mvr.tcn()]),
685             $("offlineStrings").getFormattedString('staff.cat.z3950.marked_record_for_overlay_indicator.record_id.label',[g.data.marked_record]),
686             gen_statusbar_click_handler('marked_record')
687         );
688     } else {
689         alert(document.getElementById('offlineStrings').getFormattedString('cat.opac.record_marked_for_overlay.record_id.alert',[ g.data.marked_record  ]));
690         xulG.set_statusbar(
691             1,
692             $("offlineStrings").getFormattedString('staff.cat.z3950.marked_record_for_overlay_indicator.record_id.label',[g.data.marked_record]),
693             '',
694             gen_statusbar_click_handler('marked_record')
695         );
696     }
697 }
698
699 function mark_for_hold_transfer() {
700     g.data.marked_record_for_hold_transfer = docid;
701     g.data.stash('marked_record_for_hold_transfer');
702     var robj = g.network.simple_request('MODS_SLIM_RECORD_RETRIEVE.authoritative',[docid]);
703     if (typeof robj.ilsevent == 'undefined') {
704         g.data.marked_record_for_hold_transfer_mvr = robj;
705     } else {
706         g.data.marked_record_for_hold_transfer_mvr = null;
707         g.error.standard_unexpected_error_alert('in mark_for_hold_transfer',robj);
708     }
709     g.data.stash('marked_record_for_hold_transfer_mvr');
710     if (g.data.marked_record_mvr) {
711         var m = $("offlineStrings").getFormattedString('staff.cat.opac.marked_record_for_hold_transfer_indicator.tcn.label',[g.data.marked_record_for_hold_transfer_mvr.tcn()]);
712         alert(m);
713         xulG.set_statusbar(
714             3,
715             m,
716             '',
717             gen_statusbar_click_handler('marked_record_for_hold_transfer')
718         );
719     } else {
720         var m = $("offlineStrings").getFormattedString('staff.cat.opac.marked_record_for_hold_transfer_indicator.record_id.label',[g.data.marked_record_for_hold_transfer]);
721         alert(m);
722         xulG.set_statusbar(
723             3,
724             m,
725             '',
726             gen_statusbar_click_handler('marked_record_for_hold_transfer')
727         );
728     }
729 }
730
731 function transfer_title_holds() {
732     g.data.stash_retrieve();
733     var target = g.data.marked_record_for_hold_transfer;
734     if (!target) {
735         var m = $("offlineStrings").getString('staff.cat.opac.title_for_hold_transfer.destination_needed.label');
736         alert(m);
737         return;
738     }
739     var robj = g.network.simple_request('TRANSFER_TITLE_HOLDS',[ ses(), target, [ docid ] ]);
740     if (robj == 1) {
741         var m = $("offlineStrings").getString('staff.cat.opac.title_for_hold_transfer.success.label');
742         alert(m);
743     } else {
744         var m = $("offlineStrings").getString('staff.cat.opac.title_for_hold_transfer.failure.label');
745         alert(m);
746     }
747     hold_browser_reset = true;
748     if (g.view == 'hold_browser') { set_hold_browser(); };
749 }
750
751 function delete_record() {
752     if (g.error.yns_alert(
753         document.getElementById('offlineStrings').getFormattedString('cat.opac.delete_record.confirm', [docid]),
754         document.getElementById('offlineStrings').getString('cat.opac.delete_record'),
755         document.getElementById('offlineStrings').getString('cat.opac.delete'),
756         document.getElementById('offlineStrings').getString('cat.opac.cancel'),
757         null,
758         document.getElementById('offlineStrings').getString('cat.opac.record_deleted.confirm')) == 0) {
759         var robj = g.network.simple_request('FM_BRE_DELETE',[ses(),docid]);
760         if (typeof robj.ilsevent != 'undefined') {
761             alert(document.getElementById('offlineStrings').getFormattedString('cat.opac.record_deleted.error',  [docid, robj.textcode, robj.desc]) + '\n');
762         } else {
763             alert(document.getElementById('offlineStrings').getString('cat.opac.record_deleted'));
764             refresh_display(docid);
765         }
766     }
767 }
768
769 function undelete_record() {
770     if (g.error.yns_alert(
771         document.getElementById('offlineStrings').getFormattedString('cat.opac.undelete_record.confirm', [docid]),
772         document.getElementById('offlineStrings').getString('cat.opac.undelete_record'),
773         document.getElementById('offlineStrings').getString('cat.opac.undelete'),
774         document.getElementById('offlineStrings').getString('cat.opac.cancel'),
775         null,
776         document.getElementById('offlineStrings').getString('cat.opac.record_undeleted.confirm')) == 0) {
777
778         var robj = g.network.simple_request('FM_BRE_UNDELETE',[ses(),docid]);
779         if (typeof robj.ilsevent != 'undefined') {
780             alert(document.getElementById('offlineStrings').getFormattedString('cat.opac.record_undeleted.error',  [docid, robj.textcode, robj.desc]) + '\n');
781         } else {
782             alert(document.getElementById('offlineStrings').getString('cat.opac.record_undeleted'));
783             refresh_display(docid);
784         }
785     }
786 }
787
788 function refresh_display(id) {
789     try { 
790         marc_view_reset = true;
791         marc_edit_reset = true;
792         copy_browser_reset = true;
793         hold_browser_reset = true;
794         manage_parts_reset = true;
795         manage_multi_home_reset = true;
796         serctrl_view_reset = true;
797         while(top_pane.node.lastChild) top_pane.node.removeChild( top_pane.node.lastChild );
798         var children = bottom_pane.node.childNodes;
799         for (var i = 0; i < children.length; i++) {
800             if (children[i] != browser_frame) bottom_pane.node.removeChild(children[i]);
801         }
802
803         set_brief_view();
804         $('nav').setAttribute('hidden','false');
805         var settings = g.network.simple_request(
806             'FM_AUS_RETRIEVE',
807             [ ses(), g.data.list.au[0].id() ]
808         );
809         var view = settings['staff_client.catalog.record_view.default'];
810         if (g.view_override) {
811             view = g.view_override;
812             g.view_override = null;
813         }
814         switch(view) {
815             case 'marc_view' : set_marc_view(); break;
816             case 'marc_edit' : set_marc_edit(); break;
817             case 'copy_browser' : set_copy_browser(); break;
818             case 'hold_browser' : set_hold_browser(); break;
819             case 'serctrl_view' : set_serctrl_view(); break;
820             case 'opac' :
821             default: set_opac(); break;
822         }
823         opac_wrapper_set_help_context(); 
824     } catch(E) {
825         g.error.standard_unexpected_error_alert('in refresh_display',E);
826     }
827 }
828
829 function set_default() {
830     var robj = g.network.simple_request(
831         'FM_AUS_UPDATE',
832         [ ses(), g.data.list.au[0].id(), { 'staff_client.catalog.record_view.default' : g.view } ]
833     )
834     if (typeof robj.ilsevent != 'undefined') {
835         if (robj.ilsevent != 0) g.error.standard_unexpected_error_alert(document.getElementById('offlineStrings').getString('cat.preference.error'), robj);
836     }
837 }
838
839 function add_volumes() {
840     try {
841         var edit = 0;
842         try {
843             edit = g.network.request(
844                 api.PERM_MULTI_ORG_CHECK.app,
845                 api.PERM_MULTI_ORG_CHECK.method,
846                 [ 
847                     ses(), 
848                     ses('staff_id'), 
849                     [ ses('ws_ou') ],
850                     [ 'CREATE_VOLUME', 'CREATE_COPY' ]
851                 ]
852             ).length == 0 ? 1 : 0;
853         } catch(E) {
854             g.error.sdump('D_ERROR','batch permission check: ' + E);
855         }
856
857         if (edit==0) {
858             alert(document.getElementById('offlineStrings').getString('staff.circ.copy_status.add_volumes.perm_failure'));
859             return; // no read-only view for this interface
860         }
861
862         var title = document.getElementById('offlineStrings').getFormattedString('staff.circ.copy_status.add_volumes.title', [docid]);
863
864         var url;
865         var unified_interface = String( g.data.hash.aous['ui.unified_volume_copy_editor'] ) == 'true';
866         if (unified_interface) {
867             var horizontal_interface = String( g.data.hash.aous['ui.cat.volume_copy_editor.horizontal'] ) == 'true';
868             url = window.xulG.url_prefix( horizontal_interface ? urls.XUL_VOLUME_COPY_CREATOR_HORIZONTAL : urls.XUL_VOLUME_COPY_CREATOR );
869         } else {
870             url = window.xulG.url_prefix( urls.XUL_VOLUME_COPY_CREATOR_ORIGINAL );
871         }
872
873         var w = xulG.new_tab(
874             url,
875             { 'tab_name' : title },
876             { 'doc_id' : docid, 'ou_ids' : [ ses('ws_ou') ] }
877         );
878     } catch(E) {
879         alert('Error in chrome/content/cat/opac.js, add_volumes(): ' + E);
880     }
881 }
882
883 function manage_parts() {
884     try {
885         g.view = 'manage_parts';
886         var loc = urls.XUL_BROWSER + "?url=" + window.escape(
887             window.xulG.url_prefix(urls.CONIFY_MANAGE_PARTS) + '?r=' + docid
888         );
889         if (manage_parts_reset) {
890             bottom_pane.reset_iframe( loc,{},xulG);
891             manage_parts_reset =false;
892         } else {
893             bottom_pane.set_iframe( loc,{},xulG);
894         }
895         opac_wrapper_set_help_context();
896         bottom_pane.get_contentWindow().addEventListener('load',opac_wrapper_set_help_context,false);
897     } catch(E) {
898         alert('Error in chrome/content/cat/opac.js, manage_parts(): ' + E);
899     }
900 }
901
902 function manage_multi_home_items() {
903     try {
904         g.view = 'manage_multi_home';
905         var loc = window.xulG.url_prefix(urls.MANAGE_MULTI_HOME_ITEMS);
906         if (manage_multi_home_reset) {
907             bottom_pane.reset_iframe( loc,{},{'docid':docid,'no_bib_summary':true,'url_prefix':xulG.url_prefix,'new_tab':xulG.new_tab});
908             manage_multi_home_reset =false;
909         } else {
910             bottom_pane.set_iframe( loc,{},{'docid':docid,'no_bib_summary':true,'url_prefix':xulG.url_prefix,'new_tab':xulG.new_tab});
911         }
912         opac_wrapper_set_help_context();
913         bottom_pane.get_contentWindow().addEventListener('load',opac_wrapper_set_help_context,false);
914     } catch(E) {
915         alert('Error in chrome/content/cat/opac.js, manage_multi_home_items(): ' + E);
916     }
917 }
918
919 function mark_for_multi_home() {
920     g.data.marked_multi_home_record = docid;
921     g.data.stash('marked_multi_home_record');
922     var robj = g.network.simple_request('MODS_SLIM_RECORD_RETRIEVE.authoritative',[docid]);
923     if (typeof robj.ilsevent == 'undefined') {
924         g.data.marked_multi_home_record_mvr = robj;
925     } else {
926         g.data.marked_multi_home_record_mvr = null;
927         g.error.standard_unexpected_error_alert('in mark_for_multi_home',robj);
928     }
929     g.data.stash('marked_multi_home_record_mvr');
930
931     if (g.data.marked_multi_home_record_mvr) {
932         alert(document.getElementById('offlineStrings').getFormattedString('cat.opac.record_marked_for_multi_home.tcn.alert',[ g.data.marked_multi_home_record_mvr.tcn() ]));
933         xulG.set_statusbar(
934             2,
935             $("offlineStrings").getFormattedString('staff.cat.copy_browser.marked_record_for_multi_home_indicator.tcn.label',[g.data.marked_multi_home_record_mvr.tcn()]),
936             $("offlineStrings").getFormattedString('staff.cat.copy_browser.marked_record_for_multi_home_indicator.record_id.label',[g.data.marked_multi_home_record]),
937             gen_statusbar_click_handler('marked_multi_home_record')
938         );
939     } else {
940         alert(document.getElementById('offlineStrings').getFormattedString('cat.opac.record_marked_for_multi_home.record_id.alert',[ g.data.marked_multi_home_record ]));
941         xulG.set_statusbar(
942             2,
943             $("offlineStrings").getFormattedString('staff.cat.copy_browser.marked_record_for_multi_home_indicator.record_id.label',[g.data.marked_multi_home_record]),
944             '',
945             gen_statusbar_click_handler('marked_multi_home_record')
946         );
947     }
948 }
949
950 function gen_statusbar_click_handler(data_key) {
951     return function (ev) {
952
953         if (! g.data[data_key]) {
954             return;
955         }
956
957         if (ev.button == 0 /* left click, spawn opac */) {
958             var opac_url = xulG.url_prefix( urls.opac_rdetail ) + '?r=' + g.data[data_key];
959             var content_params = {
960                 'session' : ses(),
961                 'authtime' : ses('authtime'),
962                 'opac_url' : opac_url,
963             };
964             xulG.new_tab(
965                 xulG.url_prefix(urls.XUL_OPAC_WRAPPER),
966                 {'tab_name':'Retrieving title...'},
967                 content_params
968             );
969         }
970
971         if (ev.button == 2 /* right click, remove mark */) {
972             if ( window.confirm( document.getElementById('offlineStrings').getString('cat.opac.clear_statusbar') ) ) {
973                 g.data[data_key] = null;
974                 g.data.stash(data_key);
975                 ev.target.setAttribute('label','');
976                 if (ev.target.hasAttribute('tooltiptext')) {
977                     ev.target.removeAttribute('tooltiptext');
978                 }
979             }
980         }
981     }
982 }
983
984