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