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