testing commit, please ignore
[kcls-web.git] / opac / skin / condense_js / js / holds.js
1 var holdsOrgSelectorBuilt = false;\r
2 var holdArgs;\r
3 \r
4 /* \r
5 note: metarecord holds have a holdable_formats field that contains\r
6 item_type(s)-item_forms(s)-language\r
7 item_form and language are optional - if language exist and no \r
8 item_form is specified, use item_type(s)--language\r
9 */\r
10 \r
11 var noEmailMessage;\r
12 var noEmailMessageXUL;\r
13 \r
14 function hideResultsPage(bool) {\r
15         if(!bool) {\r
16                 unHideMe($('result_header'));\r
17                 unHideMe($('tehSideBar'));\r
18                 //unHideMe($('facetSidebarContainer'));\r
19                 unHideMe($('sidebar_div'));\r
20                 unHideMe($('statusbar'));\r
21                 unHideMe($('tips'));\r
22                 unHideMe($('result_table_div'));\r
23                 if($('rresults_page')) $('rresults_page').style.width="500px";\r
24         } else {\r
25                 hideMe($('result_header'));\r
26                 hideMe($('tehSideBar'));\r
27                 hideMe($('facetSidebarContainer'));\r
28                 hideMe($('sidebar_div'));\r
29                 hideMe($('statusbar'));\r
30                 hideMe($('tips'));\r
31                 hideMe($('result_table_div'));\r
32                 hideMe($('anonListTable'));\r
33                 if($('rresults_page')) $('rresults_page').style.width="690px";\r
34         }\r
35 }\r
36 \r
37 function holdsHandleStaff() {\r
38 \r
39     // if we know the recipient's barcode, use it\r
40     if(xulG.patron_barcode) return _holdsHandleStaff();\r
41 \r
42         swapCanvas($('xulholds_box'));\r
43         $('xul_recipient_barcode').focus();\r
44         $('xul_recipient_barcode').onkeypress = function(evt) \r
45                 {if(userPressedEnter(evt)) { _holdsHandleStaff(); } };\r
46         $('xul_recipient_barcode_submit').onclick = _holdsHandleStaff;\r
47         $('xul_recipient_me').onclick = _holdsHandleStaffMe;\r
48 \r
49         $('xul_recipient_barcode').onkeyup = function(evt) {\r
50         if($('xul_recipient_barcode').value == '') \r
51             $('xul_recipient_me').disabled = false;\r
52         else\r
53             $('xul_recipient_me').disabled = true;\r
54     };\r
55 }\r
56 \r
57 $('holds_frozen_thaw_input').onchange = function(){holdsVerifyThawDateUI('holds_frozen_thaw_input');}\r
58 $('holds_frozen_thaw_input').onkeyup = function(){holdsVerifyThawDateUI('holds_frozen_thaw_input');}\r
59 \r
60 function _holdsHandleStaffMe() {\r
61         holdArgs.recipient = G.user;\r
62         holdsDrawEditor();\r
63 }\r
64 \r
65 function _holdsHandleStaff() {\r
66         var barcode = xulG.patron_barcode || $('xul_recipient_barcode').value;\r
67         var user = grabUserByBarcode( G.user.session, barcode );\r
68 \r
69         var evt;\r
70         if(evt = checkILSEvent(user)) {\r
71                 alertILSEvent(user);\r
72                 return;\r
73         }\r
74 \r
75         if(!barcode || !user) {\r
76                 alertId('holds_invalid_recipient', barcode);\r
77                 return\r
78         }\r
79 \r
80         grabUserPrefs(user);\r
81 \r
82         holdArgs.recipient = user;\r
83         holdsDrawEditor();\r
84 }\r
85 \r
86 \r
87 \r
88 /** args:\r
89   * record, volume, copy (ids)\r
90   * request, recipient, editHold (objects)\r
91   */\r
92 \r
93 function holdsDrawEditor(args) {\r
94         holdArgs = (args) ? args : holdArgs;\r
95 \r
96     if(!noEmailMessage) noEmailMessage = $('holds_email').removeChild($('holds.no_email'));\r
97     if(!noEmailMessageXUL) noEmailMessageXUL = $('holds_email').removeChild($('holds.no_email.xul'));\r
98 \r
99         if(isXUL() && holdArgs.recipient == null && holdArgs.editHold == null) {\r
100                 holdsHandleStaff();\r
101                 return;\r
102         }\r
103 \r
104         if(!holdArgs.recipient) holdArgs.recipient = G.user;\r
105         if(!holdArgs.requestor) holdArgs.requestor = G.user;\r
106 \r
107         if(!(holdArgs.requestor && holdArgs.requestor.session)) {\r
108                 alert("Please login first before placing a hold");\r
109                 setCacheValue('returnURL',{href:window.location.href, record:holdArgs.record, type:holdArgs.type});\r
110                 goTo(buildOPACLink({page:MYOPAC}, false, true));\r
111                 return;\r
112                 //detachAllEvt('common','locationChanged');\r
113                 //attachEvt('common','loggedIn', holdsDrawEditor);\r
114                 //initLogin();\r
115                 //return;\r
116         }\r
117 // flesh the args with the existing hold \r
118         if(holdArgs.editHold) holdArgsFromHold(holdArgs.editHold, holdArgs);\r
119 \r
120         hideResultsPage(true);\r
121         holdsDrawWindow();\r
122 }\r
123 \r
124 \r
125 // updates the edit window with the existing hold's data \r
126 function _holdsUpdateEditHold() {\r
127 \r
128         var hold = holdArgs.editHold;\r
129         var qstats = holdArgs.status;\r
130 \r
131         var orgsel = $('holds_org_selector');\r
132     var frozenbox = $('holds_frozen_chkbox');\r
133 \r
134         setSelector(orgsel, hold.pickup_lib());\r
135 \r
136         if( hold.capture_time() || qstats.status > 2 ) {\r
137         frozenbox.disabled = true;\r
138         $('holds_frozen_thaw_input').disabled = true;\r
139         if(qstats.status == 3) {\r
140             // no pickup lib changes while in-transit\r
141                     orgsel.disabled = true;\r
142         } else {\r
143             var orgs = fetchPermOrgs('UPDATE_PICKUP_LIB_FROM_HOLDS_SHELF');\r
144             if(orgs[0] == -1)\r
145                         orgsel.disabled = true;\r
146         }\r
147     } else {\r
148                 orgsel.disabled = false;\r
149         frozenbox.disabled = false;\r
150     }\r
151 \r
152 \r
153         $('holds_submit').onclick = holdsEditHold;\r
154         $('holds_update').onclick = holdsEditHold;\r
155 \r
156         if(hold.phone_notify()) {\r
157                 $('holds_enable_phone').checked = true;\r
158                 $('holds_phone').value = hold.phone_notify();\r
159 \r
160         } else {\r
161                 $('holds_phone').disabled = true;\r
162                 $('holds_enable_phone').checked = false;\r
163         }\r
164 \r
165         if(isTrue(hold.email_notify())) {\r
166                 $('holds_enable_email').checked = true;\r
167 \r
168         } else {\r
169                 $('holds_enable_email').checked = false;\r
170         }\r
171 \r
172     //$('holds_expire_time').setValue(dojo.date.stamp.fromISOString(hold.expire_time()));\r
173 \r
174     /* populate the hold freezing info */\r
175     if(!frozenbox.disabled && isTrue(hold.frozen())) {\r
176         frozenbox.checked = true;\r
177         unHideMe($('hold_frozen_thaw_row'));\r
178         if(hold.thaw_date()) {\r
179             $('holds_frozen_thaw_input').value=dojo.date.stamp.fromISOString(hold.thaw_date());\r
180         } else {\r
181             $('holds_frozen_thaw_input').value='';\r
182         }\r
183     } else {\r
184         frozenbox.checked = false;\r
185         $('holds_frozen_thaw_input').value='';\r
186         hideMe($('hold_frozen_thaw_row'));\r
187     }\r
188 }\r
189 \r
190 function holdsEditHold() {\r
191         var hold = holdsBuildHoldFromWindow();\r
192         if(!hold) return;\r
193         holdsUpdate(hold);\r
194         showCanvas();\r
195         if(holdArgs.onComplete)\r
196                 holdArgs.onComplete(hold);\r
197 }\r
198 \r
199 function holdArgsFromHold(hold, oargs) {\r
200         var args = (oargs) ? oargs : {};\r
201         args.type = hold.hold_type();\r
202         var target = hold.target();\r
203 \r
204         switch(args.type) {\r
205                 case 'M':\r
206                         args.metarecord = target;\r
207                         break;\r
208                 case 'T':\r
209                         args.record = target;\r
210                         break;\r
211                 case 'V':\r
212                         args.volume = target;\r
213                         break;\r
214                 case 'C':\r
215                         args.copy = target;\r
216                         break;\r
217         }\r
218         return args;\r
219 }\r
220 \r
221 function holdFetchObjects(hold, doneCallback) {\r
222         var args = (hold) ? holdArgsFromHold(hold) : holdArgs;\r
223         var type = args.type;\r
224 \r
225         if( type == 'C' ) {\r
226                 if( args.copyObject ) {\r
227 \r
228                         args.copy = args.copyObject.id();\r
229                         args.volume = args.copyObject.call_number();\r
230                         _h_set_vol(args, doneCallback);\r
231 \r
232                 } else {\r
233                         var creq = new Request(FETCH_COPY, args.copy);\r
234 \r
235                         creq.callback(\r
236                                 function(r) {\r
237                                         var cp = r.getResultObject();\r
238                                         args.copyObject = cp;\r
239                                         args.volume = args.copyObject.call_number();\r
240                                         _h_set_vol(args, doneCallback);\r
241                                 }\r
242                         );\r
243                         creq.send();\r
244                 }\r
245         } else {\r
246                 if( type == 'V' ) {\r
247                         _h_set_vol(args, doneCallback);\r
248 \r
249                 } else {\r
250                         if( type == 'T' ) {\r
251                                 _h_set_rec(args, doneCallback);\r
252                         } else {\r
253                                 _h_set_rec_descriptors(args, doneCallback);\r
254                         }\r
255                 }\r
256         }\r
257 \r
258         return args;\r
259 }\r
260 \r
261 function _h_set_vol(args, doneCallback) {\r
262 \r
263         if( args.volumeObject ) {\r
264                 args.volume = args.volumeObject.id();\r
265                 args.record = args.volumeObject.record();\r
266                 _h_set_rec(args, doneCallback);\r
267 \r
268         } else {\r
269 \r
270                 var vreq = new Request(FETCH_VOLUME, args.volume);\r
271                 vreq.callback(\r
272                         function(r) {\r
273                                 var vol = r.getResultObject();\r
274                                 args.volumeObject = vol;\r
275                                 args.record = vol.record();\r
276                                 _h_set_rec(args, doneCallback);\r
277                         }\r
278                 );\r
279                 vreq.send();\r
280         }\r
281 }\r
282 \r
283 function _h_set_rec(args, doneCallback) {\r
284 \r
285         if(args.recordObject) \r
286                 args.record = args.recordObject.doc_id();\r
287         else \r
288                 args.recordObject = findRecord( args.record, 'T' );\r
289         \r
290         if( args.type == 'T' || args.type == 'M' ) \r
291                 _h_set_rec_descriptors(args, doneCallback);\r
292         else \r
293                 if(doneCallback) doneCallback(args);\r
294 }\r
295 \r
296 \r
297 function _h_set_rec_descriptors(args, doneCallback) {\r
298 \r
299         // grab the list of record desciptors attached to this records metarecord \r
300         if( ! args.recordDescriptors )  {\r
301                 var params = { record: args.record };\r
302 \r
303                 if( ! args.record ) {\r
304                         if( args.metarecord )\r
305                                 params = { metarecord : args.metarecord };\r
306                         else \r
307                                 params = { metarecord : args.metarecordObject.doc_id() };\r
308                 }\r
309 \r
310                 var req = new Request(FETCH_MR_DESCRIPTORS, params );\r
311                 req.callback(\r
312                         function(r) {\r
313                                 var data = r.getResultObject();\r
314                                 args.recordDescriptors = data.descriptors;\r
315                                 args.metarecord = data.metarecord;\r
316                                 if( args.type == 'M' && ! args.metarecordObject) \r
317                                         args.metarecordObject = findRecord(args.metarecord, 'M');       \r
318                                  \r
319                                 if(doneCallback) doneCallback(args);\r
320                         }\r
321                 );\r
322                 req.send();\r
323 \r
324         } else {\r
325                 if(doneCallback) doneCallback(args);\r
326         }\r
327 \r
328         return args;\r
329 }\r
330 \r
331 \r
332 \r
333 function holdsDrawWindow(bool) {\r
334         swapCanvas($('holds_box'));\r
335         $('holds_cancel').onclick = function(){\r
336                 hideResultsPage(false);\r
337                 hideMe($('holds_box'));\r
338                 unHideMe($('canvas_main'));\r
339                 //runEvt('common', 'holdUpdateCanceled'), showCanvas() \r
340         };\r
341         $('holds_submit').onclick = function(){holdsPlaceHold(holdsBuildHoldFromWindow())};\r
342         $('holds_update').onclick = function(){holdsPlaceHold(holdsBuildHoldFromWindow())};\r
343         holdFetchObjects(null, \r
344                 function(){\r
345                         __holdsDrawWindow();\r
346 \r
347                         if(holdArgs.editHold) {\r
348                                 //hideMe($('holds_submit'));\r
349                                 unHideMe($('holds_update'));\r
350                                 var req = new Request(FETCH_HOLD_STATUS, \r
351                                         G.user.session, holdArgs.editHold.id());\r
352                                 req.send(true);\r
353                                 holdArgs.status = req.result();\r
354                                 _holdsUpdateEditHold();\r
355                         }  \r
356                 }\r
357         );\r
358 }\r
359 \r
360 function selOrgChange(e) {\r
361         \r
362         $('holds_pickup_lib').innerHTML = this.options[this.selectedIndex].text;\r
363 }\r
364 \r
365 function __holdsDrawWindow() {\r
366 \r
367         var rec = holdArgs.recordObject;\r
368         var vol = holdArgs.volumeObject;\r
369         var copy = holdArgs.copyObject;\r
370         var mr = holdArgs.metarecordObject;\r
371 \r
372         rec = (rec) ? rec : mr;\r
373 \r
374         if(!holdsOrgSelectorBuilt) {\r
375                 holdsBuildOrgSelector(null,0);\r
376                 holdsOrgSelectorBuilt = true;\r
377                 var selector = $('holds_org_selector');\r
378 \r
379                 /*\r
380                 var o_loc = findOrgUnit(getOrigLocation());\r
381                 var t = findOrgType(o_loc.ou_type());\r
382                 if( t.can_have_users() ) \r
383                         setSelector(selector, o_loc.id());\r
384                 else \r
385                 */\r
386                 selector.onchange = selOrgChange;\r
387                 setSelector(selector, holdArgs.recipient.home_ou());\r
388         }\r
389         \r
390         var obj = findOrgUnit(holdArgs.recipient.home_ou());\r
391         $('holds_pickup_lib').innerHTML = obj.name();\r
392 \r
393         /*\r
394         if(isXUL()) {\r
395                 var dsel = $('holds_depth_selector');\r
396                 unHideMe($('holds_depth_selector_row'));\r
397                 if(dsel.getElementsByTagName('option').length == 0) {\r
398                         var types = globalOrgTypes;\r
399                         var depth = findOrgDepth(G.user.ws_ou());\r
400                         iterate(types, \r
401                                 function(t) {\r
402                                         if(t.depth() > depth) return;\r
403                                         insertSelectorVal(dsel, -1, t.opac_label(), t.depth());\r
404                                 }\r
405                         );\r
406                 }\r
407         }\r
408         */\r
409 \r
410         appendClear($('holds_recipient'), text(\r
411                 holdArgs.recipient.family_name() + ', ' +  \r
412                         holdArgs.recipient.first_given_name()));\r
413         appendClear($('holds_title'), text(rec.title()));\r
414         appendClear($('holds_author'), text(rec.author()));\r
415 \r
416         if( holdArgs.type == 'V' || holdArgs.type == 'C' ) {\r
417 \r
418                 unHideMe($('holds_type_row'));\r
419                 unHideMe($('holds_cn_row'));\r
420                 appendClear($('holds_cn'), text(holdArgs.volumeObject.label()));\r
421 \r
422                 if( holdArgs.type == 'V'  ) {\r
423                         unHideMe($('holds_is_cn'));\r
424                         hideMe($('holds_is_copy'));\r
425 \r
426                 } else {\r
427                         hideMe($('holds_is_cn'));\r
428                         unHideMe($('holds_is_copy'));\r
429                         unHideMe($('holds_copy_row'));\r
430                         appendClear($('holds_copy'), text(holdArgs.copyObject.barcode()));\r
431                 }\r
432 \r
433         } else {\r
434                 hideMe($('holds_type_row'));\r
435                 hideMe($('holds_copy_row'));\r
436                 hideMe($('holds_cn_row'));\r
437         }\r
438 \r
439         removeChildren($('holds_format'));\r
440 \r
441         var mods_formats = rec.types_of_resource();\r
442         var formats;\r
443 \r
444         if(holdArgs.recordDescriptors)\r
445                 formats = holdArgs.recordDescriptors[0].item_type();\r
446 \r
447         if( holdArgs.type == 'T' ) {\r
448                 var desc = grep( holdArgs.recordDescriptors,\r
449                         function(i) {\r
450                                 return (i.record() == holdArgs.record); \r
451                         }\r
452                 );\r
453                 formats = desc[0].item_type();\r
454         }\r
455 \r
456         if( holdArgs.type == 'M' ) {\r
457                 var data = holdsParseMRFormats(holdArgs.editHold.holdable_formats());\r
458                 mods_formats = data.mods_formats;\r
459                 formats = data.formats;\r
460         }\r
461 \r
462 \r
463         for( var i in mods_formats ) {\r
464                 var res = mods_formats[i];\r
465                 var img = elem("img");\r
466                 setResourcePic(img, res);\r
467                 $('holds_format').appendChild(img);\r
468                 if(formats)\r
469                         $('holds_format').appendChild(text(' '+ MARCTypeToFriendly(formats[i]) +' '));\r
470                 else\r
471                         $('holds_format').appendChild(text(' '+ mods_formats[i] +' '));\r
472                 $('holds_format').appendChild(elem('br'));\r
473         }\r
474 \r
475 \r
476         $('holds_phone').value = (holdArgs.recipient.day_phone())?holdArgs.recipient.day_phone():"";\r
477         appendClear( $('holds_email'), text(holdArgs.recipient.email()));\r
478 \r
479         var pref = holdArgs.recipient.prefs[PREF_HOLD_NOTIFY];\r
480 \r
481         if(pref) {\r
482                 if( ! pref.match(/email/i) ) {\r
483                         $('holds_enable_email').checked = false;\r
484                 } else {\r
485                         $('holds_enable_email').checked = true;\r
486                 }\r
487 \r
488                 if( ! pref.match(/phone/i) ) {\r
489                         $('holds_phone').disabled = true;\r
490                         $('holds_enable_phone').checked = false;\r
491                 } else {\r
492                         $('holds_phone').disabled = false;\r
493                         $('holds_enable_phone').checked = true;\r
494                 }\r
495         }\r
496 \r
497     if(!holdArgs.recipient.email()) {\r
498                 $('holds_enable_email').checked = false;        \r
499                 $('holds_enable_email').disabled = true;\r
500         var message;\r
501         if(isXUL()) {\r
502             message = noEmailMessageXUL.cloneNode(true);\r
503                 appendClear($('holds_email'), message);\r
504         } else {\r
505             message = noEmailMessage.cloneNode(true);\r
506                 appendClear($('holds_email'), message);\r
507             $('holds.no_email.my_account').setAttribute('href', buildOPACLink({page:MYOPAC},null,true));\r
508         }\r
509         unHideMe(message);\r
510     }\r
511 \r
512         if(!$('holds_phone').value) \r
513                 $('holds_enable_phone').checked = false;        \r
514 \r
515         appendClear($('holds_physical_desc'), text(rec.physical_description()));\r
516 \r
517         if(holdArgs.type == 'M') hideMe($('hold_physical_desc_row'));\r
518 \r
519         holdsSetFormatSelector();\r
520 \r
521     $('holds_frozen_chkbox').checked = false;\r
522     hideMe($('hold_frozen_thaw_row'));\r
523 \r
524     var interval = fetchOrgSettingDefault(holdArgs.recipient.home_ou(), 'circ.hold_expire_interval');\r
525     var secs = 0;\r
526     if(interval) {\r
527         secs = interval_to_seconds(interval);\r
528         var expire = new Date();\r
529         expire.setTime(expire.getTime() + Number(secs + '000'));\r
530         if(dijit.byId('holds_expire_time')) dijit.byId('holds_expire_time').setValue(expire);\r
531     }\r
532 }\r
533 \r
534 function holdsParseMRFormats(str) {\r
535         var data = str.split(/-/);      \r
536 \r
537         var formats = [];\r
538         var mods_formats = [];\r
539 \r
540         for( var i = 0; i < data[0].length; i++ ) {\r
541                 formats.push( data[0].charAt(i) );\r
542                 mods_formats.push( MARCFormatToMods( formats[i] ) );\r
543         }\r
544         \r
545         formats = uniquify(formats);\r
546         mods_formats = uniquify(mods_formats);\r
547 \r
548         return {\r
549                 formats                 : formats,\r
550                 mods_formats    : mods_formats,\r
551                 lang                            : data[2],\r
552                 largeprint              : data[1]\r
553         };\r
554 }\r
555 \r
556 \r
557 function holdsSetFormatSelector() {\r
558         var type = holdArgs.type;\r
559         if( type == 'C' || type == 'V' || holdArgs.editHold ) return;\r
560 \r
561         var data                                = holdsGetFormats();\r
562         var avail_formats       = data.avail_formats;\r
563         var sel_formats = data.sel_formats;\r
564         holdArgs.language = data.lang;\r
565 \r
566         unHideMe($('holds_alt_formats_row_extras'));\r
567         var selector = $('hold_alt_form_selector');\r
568 \r
569         for( var i = 0; i < avail_formats.length; i++ ) {\r
570                 var form = avail_formats[i];\r
571                 unHideMe(findSelectorOptByValue(selector, form));\r
572         }\r
573 }\r
574 \r
575 \r
576 function holdsGetFormats() {\r
577 \r
578         var lang;\r
579         var formats = [];\r
580         var sformats = []; // selected formats \r
581 \r
582         var type = holdArgs.type;\r
583         var desc = holdArgs.recordDescriptors;\r
584         var rec = holdArgs.record;\r
585         var mrec = holdArgs.metarecord;\r
586 \r
587         if( type == 'T' ) {\r
588 \r
589                 for( var i = 0; i < desc.length; i++ ) {\r
590                         var d = desc[i];\r
591                         if( d.record() == holdArgs.record ) {\r
592                                 lang = d.item_lang();\r
593                                 holdArgs.myFormat =  _t_f_2_format(d.item_type(), d.item_form());\r
594                                 sformats.push(holdArgs.myFormat);\r
595                                 break;\r
596                         }\r
597                 }\r
598         }\r
599 \r
600         for( var i = 0; i < desc.length; i++ ) {\r
601                 var d = desc[i];\r
602                 if( d.item_lang() != lang ) continue;\r
603                 formats.push( _t_f_2_format(d.item_type(), d.item_form()));\r
604         }\r
605 \r
606         formats = uniquify(formats);\r
607 \r
608         return {\r
609                 lang : lang,\r
610                 avail_formats : formats, \r
611                 sel_formats : sformats\r
612         };\r
613 }\r
614 \r
615 \r
616 \r
617 function _t_f_2_format(type, form) {\r
618         if( form == 'd' ) return 'at-d';\r
619         return (type == 'a' || type == 't') ? 'at' : \r
620                 ( type == 'i' || type == 'g' || type == 'j' ) ? type : null;\r
621 }\r
622 \r
623 function holdsSetSelectedFormats() {\r
624 \r
625         var cn = $('holds_alt_formats_row').className;\r
626         if( cn && cn.match(/hide_me/) ) return;\r
627 \r
628         var selector = $('hold_alt_form_selector');\r
629         var vals = getSelectedList(selector);\r
630 \r
631         if(vals.length == 0) return;\r
632 \r
633         var fstring = "";\r
634 \r
635         if( contains(vals, 'at-d') ) {\r
636                 if( contains(vals, 'at') )\r
637                         fstring = 'at';\r
638                 else \r
639                         fstring = 'at-d';\r
640         } else {\r
641                 if( contains(vals, 'at') )\r
642                         fstring = 'at';\r
643         }\r
644 \r
645         for( var i = 0; i < vals.length; i++ ) {\r
646                 var val = vals[i];\r
647                 if( !val.match(/at/) ) fstring = val + fstring;\r
648         }\r
649 \r
650         if( holdArgs.language ) {\r
651                 if( fstring.match(/-/) )\r
652                         fstring = fstring + '-' + holdArgs.language;\r
653                 else\r
654                         fstring = fstring + '--' + holdArgs.language;\r
655         }\r
656         return fstring;\r
657 }\r
658 \r
659 \r
660 function holdsCheckPossibility(pickuplib, hold, recurse) {\r
661 \r
662         var args = { \r
663                 titleid : holdArgs.record,\r
664                 volume_id : holdArgs.volume,\r
665                 copy_id : holdArgs.copy,\r
666                 hold_type : holdArgs.type,\r
667                 patronid : holdArgs.recipient.id(),\r
668                 depth : 0, \r
669                 pickup_lib : pickuplib \r
670         };\r
671 \r
672         if(recurse) {\r
673                 /* if we're calling create again (recursing), \r
674                         we know that the hold possibility check already succeeded */\r
675                 holdHandleCreateResponse({_recurse:true, _hold:hold}, true );\r
676 \r
677         } else {\r
678                 _debug("hold possible args = "+js2JSON(args));\r
679         \r
680                 var req = new Request(CHECK_HOLD_POSSIBLE, G.user.session, args );\r
681         \r
682                 req.request.alertEvent = false;\r
683                 req.request._hold = hold;\r
684                 req.request._recurse = recurse;\r
685                 req.callback(holdHandleCreateResponse);\r
686                 req.send();\r
687         }\r
688 }\r
689 \r
690 \r
691 function holdsBuildOrgSelector(node, sel) {\r
692 \r
693         if(!node) node = globalOrgTree;\r
694     if(!isTrue(node.opac_visible())) return;\r
695 \r
696         var selector = sel?sel:$('holds_org_selector');\r
697         var index = selector.options.length;\r
698 \r
699         var type = findOrgType(node.ou_type());\r
700         var indent = type.depth() - 1;\r
701         var opt = setSelectorVal( selector, index, node.name(), node.id(), null, indent );\r
702         if(!type.can_have_users()) {\r
703                 opt.disabled = true;\r
704                 addCSSClass(opt, 'disabled_option');\r
705         }\r
706         \r
707         for( var i in node.children() ) {\r
708                 var child = node.children()[i];\r
709                 if(child) holdsBuildOrgSelector(child);\r
710         }\r
711 }\r
712 \r
713 function holdsBuildHoldFromWindow() {\r
714 \r
715         var org = getSelectorVal($('holds_org_selector'));\r
716         var node = findOrgUnit(org);\r
717         var ntype = findOrgType(node.ou_type());\r
718         if(!ntype.can_have_users()) {\r
719                 alertId('holds_pick_good_org');\r
720                 return;\r
721         }\r
722 \r
723         var hold = new ahr();\r
724         if(holdArgs.editHold) {\r
725                 hold = holdArgs.editHold;\r
726                 holdArgs.editHold = null;\r
727         }\r
728 \r
729         if( $('holds_enable_phone').checked ) {\r
730                 var phone = $('holds_phone').value;\r
731                 if( !phone || !phone.match(REGEX_PHONE) ) {\r
732                         alert($('holds_bad_phone').innerHTML);\r
733                         return null;\r
734                 }\r
735                 hold.phone_notify(phone);\r
736 \r
737         } else {\r
738                 hold.phone_notify("");\r
739         }\r
740 \r
741         if( $('holds_enable_email').checked ) \r
742                 hold.email_notify(1);\r
743         else\r
744                 hold.email_notify(0);\r
745 \r
746         var target;\r
747 \r
748         switch(holdArgs.type) {\r
749                 case 'M':\r
750                         target = holdArgs.metarecord; break;\r
751                 case 'T':\r
752                         target = holdArgs.record; break;\r
753                 case 'V':\r
754                         target = holdArgs.volume; break;\r
755                 case 'C':\r
756                         target = holdArgs.copy; break;\r
757         }\r
758 \r
759 \r
760 \r
761         hold.pickup_lib(org); \r
762         //hold.request_lib(org); \r
763         hold.requestor(holdArgs.requestor.id());\r
764         hold.usr(holdArgs.recipient.id());\r
765         hold.target(target);\r
766         hold.hold_type(holdArgs.type);\r
767 \r
768     try{var expDate = dijit.byId('holds_expire_time').getValue();} catch(e){}\r
769     if(expDate) {\r
770         var expireDate = dojo.date.stamp.toISOString(expDate);\r
771         expireDate = holdsVerifyThawDate(expireDate); \r
772         if(expireDate)\r
773             hold.expire_time(expireDate);\r
774         else \r
775             return;\r
776     }\r
777 \r
778     // see if this hold should be frozen and for how long\r
779     if($('holds_frozen_chkbox').checked) {\r
780         hold.frozen('t');\r
781         unHideMe($('hold_frozen_thaw_row'));\r
782         thawDate = dojo.date.stamp.toISOString(dijit.byId('holds_frozen_thaw_input').getValue());\r
783         if(thawDate) {\r
784             thawDate = holdsVerifyThawDate(thawDate); \r
785             if(thawDate) \r
786                 hold.thaw_date(thawDate);\r
787             else\r
788                 return;\r
789         } else {\r
790             hold.thaw_date(null);\r
791         }\r
792     } else {\r
793         hold.frozen('f');\r
794         hold.thaw_date(null);\r
795     }\r
796 \r
797         //check for alternate hold formats \r
798         var fstring = holdsSetSelectedFormats();\r
799         if(fstring) { \r
800                 hold.hold_type('M'); \r
801                 hold.holdable_formats(fstring);\r
802                 hold.target(holdArgs.metarecord);\r
803         }\r
804         return hold;\r
805 }\r
806         \r
807 function holdsPlaceHold(hold, recurse) {\r
808         if(!hold) return;\r
809         swapCanvas($('check_holds_box'));\r
810         holdsCheckPossibility(hold.pickup_lib(), hold, recurse);\r
811 }\r
812 \r
813 \r
814 function holdHandleCreateResponse(r, recurse) {\r
815 \r
816         if(!recurse) {\r
817                 var res = r.getResultObject();\r
818                 if(checkILSEvent(res) || res.success != 1) {\r
819                         if(res.success != 1) {\r
820                                 alert($('hold_not_allowed').innerHTML+(!res.last_event.desc?"":"\n\nHold failure description:\n"+res.last_event.desc));\r
821                         } else {\r
822                                 if( res.textcode == 'PATRON_BARRED' ) {\r
823                                         alertId('hold_failed_patron_barred');\r
824                                 } else {\r
825                                         alert($('hold_not_allowed').innerHTML+(!res.last_event.desc?"":"\n\nHold failure description:\n"+res.last_event.desc));\r
826                                 }\r
827                         }\r
828                         swapCanvas($('holds_box'));\r
829                         return;\r
830                 }\r
831         r._hold.selection_depth(res.depth);\r
832         }       \r
833 \r
834         holdCreateHold(r._recurse, r._hold);\r
835         hideResultsPage(false);\r
836 }\r
837 \r
838 \r
839 function holdCreateHold( recurse, hold ) {\r
840         var method = CREATE_HOLD;\r
841         if(recurse) method = CREATE_HOLD_OVERRIDE;\r
842         var req = new Request( method, holdArgs.requestor.session, hold );\r
843         req.request.alertEvent = false;\r
844         req.send(true);\r
845         var res = req.result();\r
846         holdProcessResult(hold, res, recurse);\r
847 \r
848         showCanvas();\r
849 \r
850         runEvt('common', 'holdUpdated');\r
851 }\r
852 \r
853 \r
854 function holdProcessResult( hold, res, recurse ) {\r
855 \r
856         if( res && res > -1 ) {\r
857                 alert($('holds_success').innerHTML);\r
858                 holdArgs = null;\r
859         if(isXUL() && typeof xulG.opac_hold_placed == 'function')\r
860             xulG.opac_hold_placed(res);\r
861 \r
862         } else {\r
863 \r
864                 if( recurse ) {\r
865                         alert($('holds_failure').innerHTML);\r
866                         return;\r
867                 }\r
868 \r
869                 if( grep(res, function(e) { return (e.textcode == 'HOLD_EXISTS'); }) ) {\r
870                         if( fetchPermOrgs('HOLD_EXISTS.override')[0] != -1 ) {\r
871                                 if( confirm($('hold_dup_exists_override').innerHTML) ) {\r
872                                         return holdsPlaceHold(hold, true);\r
873                                 }\r
874                 return;\r
875 \r
876                         } else {\r
877                                 return alert($('hold_dup_exists').innerHTML);\r
878                         }\r
879                 }\r
880 \r
881                 if( grep(res, function(e) { return (e.textcode == 'HOLD_ITEM_CHECKED_OUT'); }) ) {\r
882                         if( fetchPermOrgs('HOLD_ITEM_CHECKED_OUT.override')[0] != -1 ) {\r
883                                 if( confirm($('hold_checked_out_override').innerHTML) ) {\r
884                                         return holdsPlaceHold(hold, true);\r
885                                 }\r
886                 return;\r
887 \r
888                         } else {\r
889                                 return alert($('hold_checked_out').innerHTML);\r
890                         }\r
891                 }\r
892 \r
893 \r
894                 alert($('holds_failure').innerHTML);\r
895         }\r
896 }\r
897 \r
898 \r
899 function holdsCancel(holdid, user) {\r
900         if(!user) user = G.user;\r
901         var req = new Request(CANCEL_HOLD, user.session, holdid, /* Patron via OPAC */ 6);\r
902         req.send(true);\r
903         return req.result();\r
904         runEvt('common', 'holdUpdated');\r
905 }\r
906 \r
907 function holdsUpdate(hold, user) {\r
908         if(!user) user = G.user;\r
909         var req = new Request(UPDATE_HOLD, user.session, hold);\r
910         req.send(true);\r
911         var x = req.result(); // cause an exception if there is one \r
912         runEvt('common', 'holdUpdated');\r
913 }\r
914 \r
915 /* verify that the thaw date is valid and after today */\r
916 function holdsVerifyThawDate(dateString, isGreater) {\r
917     thawDate = dojo.date.stamp.fromISOString(dateString);\r
918     if(thawDate) {\r
919         if(isGreater) {\r
920             if(dojo.date.compare(thawDate) > 0) {\r
921                 return dojo.date.stamp.toISOString(thawDate);\r
922             }\r
923         } else {\r
924             return dojo.date.stamp.toISOString(thawDate);\r
925         }\r
926     }\r
927     return null;\r
928 }\r
929 \r
930 function holdsVerifyThawDateUI(element) {\r
931     value = dojo.date.stamp.toISOString(dijit.byId(element).getValue());\r
932 \r
933     if(!value) {\r
934         removeCSSClass($(element), 'invalid_field');\r
935         return;\r
936     }\r
937 \r
938     if(!holdsVerifyThawDate(value, true)) {\r
939         addCSSClass($(element), 'invalid_field');\r
940     } else {\r
941         removeCSSClass($(element), 'invalid_field');\r
942     }\r
943 }\r
944 \r
945 \r
946 function editHold(h) {\r
947         var row = $('myopac_holds_row_'+h);\r
948         var objs = [];\r
949         \r
950         objs['hold_pickup_lib'] = $n(row,'hold_pickup_lib');\r
951         objs['hold_pickup_lib_sel'] = $n(row,'hold_pickup_lib_sel');\r
952         objs['hold_active'] = $n(row,'hold_active');\r
953         objs['activate_label'] = $n(row,'activate_label');\r
954         objs['activate_date'] = $n(row,'activate_date');\r
955         objs['activate_box'] = $n(row,'activate_box');\r
956         objs['hold_expires_label'] = $n(row,'hold_expires_label');\r
957         objs['hold_expires'] = $n(row,'hold_expires');\r
958         objs['hold_expires_box'] = $n(row,'hold_expires_box');\r
959         objs['hold_active_sel'] = $n(row,'hold_active_sel');\r
960         objs['hold_edit_link'] = $n(row,'hold_edit_link');\r
961         objs['hold_save_link'] = $n(row,'hold_save_link');\r
962         objs['hold_cancel_link'] = $n(row,'hold_cancel_link');\r
963                 \r
964         for(var i in objs) unHideMe(objs[i]);\r
965         \r
966         hideMe(objs['activate_date']);\r
967         hideMe(objs['hold_active']);\r
968         hideMe(objs['hold_expires']);\r
969         hideMe(objs['hold_pickup_lib']);\r
970         hideMe(objs['hold_edit_link']);\r
971 }\r
972 \r
973 function cancelHold(h) {\r
974         var row = $('myopac_holds_row_'+h);\r
975         var objs = [];\r
976         \r
977         objs['hold_pickup_lib'] = $n(row,'hold_pickup_lib');\r
978         objs['hold_pickup_lib_sel'] = $n(row,'hold_pickup_lib_sel');\r
979         objs['hold_active'] = $n(row,'hold_active');\r
980         objs['activate_label'] = $n(row,'activate_label');\r
981         objs['activate_date'] = $n(row,'activate_date');\r
982         objs['activate_box'] = $n(row,'activate_box');\r
983         objs['hold_expires_label'] = $n(row,'hold_expires_label');\r
984         objs['hold_expires'] = $n(row,'hold_expires');\r
985         objs['hold_expires_box'] = $n(row,'hold_expires_box');\r
986         objs['hold_active_sel'] = $n(row,'hold_active_sel');\r
987         objs['hold_edit_link'] = $n(row,'hold_edit_link');\r
988         objs['hold_save_link'] = $n(row,'hold_save_link');\r
989         objs['hold_cancel_link'] = $n(row,'hold_cancel_link');\r
990                 \r
991         for(var i in objs) hideMe(objs[i]);\r
992         \r
993         unHideMe(objs['hold_edit_link']);\r
994         unHideMe(objs['hold_pickup_lib']);\r
995         unHideMe(objs['holds_active']);\r
996         unHideMe(objs['hold_active']);\r
997         unHideMe(objs['activate_date']);\r
998         unHideMe(objs['hold_expires']);\r
999         if(objs['hold_expires'].innerHTML) unHideMe(objs['hold_expires_label']);\r
1000         if(objs['activate_date'].innerHTML) unHideMe(objs['activate_label']);\r
1001 }\r
1002 \r
1003 function saveHold(h) {\r
1004         var row = $('myopac_holds_row_'+h);\r
1005         var hold = holdsCache[holdsCacheMap[h]].hold;\r
1006         \r
1007         var activateDataBox = $n(row,'activate_box');\r
1008         var expireDateBox = $n(row,'hold_expires_box');\r
1009         var pickupLibSel = $n(row,'hold_pickup_lib_sel');\r
1010         var activateSel = $n(row,'hold_active_sel');\r
1011         var expireTime = dojo.date.stamp.toISOString(new Date(Date.parse(expireDateBox.value)),null);\r
1012         var activateTime = dojo.date.stamp.toISOString(new Date(Date.parse(activateDataBox.value)),null);\r
1013         if(parseInt(expireTime)) hold.expire_time(expireTime);\r
1014         if(parseInt(activateTime)) hold.thaw_date(activateTime);\r
1015         hold.frozen(activateSel.options[activateSel.selectedIndex].value);\r
1016         hold.pickup_lib(pickupLibSel.options[pickupLibSel.selectedIndex].value);\r
1017         row.style.background= isTrue(hold.frozen())?"#ebf9ff":"";\r
1018         \r
1019         fieldmapper.standardRequest(['open-ils.circ','open-ils.circ.hold.update'],{params:[G.user.session,hold],oncomplete:refreshHold});\r
1020 }\r
1021 \r
1022 function updateHoldInfo(holdid,holdrow) {\r
1023         var h = holdsCache[holdsCacheMap[holdid]].hold;\r
1024         if(!h) return;\r
1025         var row = holdrow?holdrow:$('myopac_holds_row_'+holdid);\r
1026         if(!row) return;\r
1027         \r
1028         $n(row,'hold_pickup_lib').innerHTML = findOrgUnit(h.pickup_lib()).name();\r
1029         $n(row,'hold_active').innerHTML = isTrue(h.frozen())?"Suspended":"Active";\r
1030         \r
1031         if(h.thaw_date()) {\r
1032                 var d = dojo.date.stamp.fromISOString(h.thaw_date());\r
1033                 $n(row, 'activate_date').innerHTML = dojo.date.locale.format(d, {selector: 'date', fullYear: true});\r
1034                 unHideMe($n(row,'activate_label'));\r
1035                 $n(row,'activate_box').value = dojo.date.locale.format(d, {selector:'date', fullYear: true});\r
1036         }\r
1037         \r
1038         if(h.expire_time()) {\r
1039                 var exp_date = dojo.date.stamp.fromISOString(h.expire_time());\r
1040                 $n(row, 'hold_expires').innerHTML = dojo.date.locale.format(exp_date, {selector:'date', fullYear: true});\r
1041                 unHideMe($n(row,'hold_expires_label'));\r
1042                 $n(row,'hold_expires_box').value = dojo.date.locale.format(exp_date, {selector:'date', fullYear: true});\r
1043         }\r
1044 }\r
1045 \r
1046 function refreshHold(r) {\r
1047         var hold = r.recv().content();\r
1048         if(!parseInt(hold)) return;\r
1049         updateHoldInfo(hold);\r
1050         cancelHold(hold);\r
1051 }\r