]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/opac/skin/default/js/holds.js
plugged in hold freezing and thaw date logic. changed display to show a green check...
[working/Evergreen.git] / Open-ILS / web / opac / skin / default / js / holds.js
1 var holdsOrgSelectorBuilt = false;
2 var holdArgs;
3
4 /* 
5 note: metarecord holds have a holdable_formats field that contains
6 item_type(s)-item_forms(s)-language
7 item_form and language are optional - if language exist and no 
8 item_form is specified, use item_type(s)--language
9 */
10
11 var noEmailMessage;
12 var noEmailMessageXUL;
13
14 function holdsHandleStaff() {
15         swapCanvas($('xulholds_box'));
16         $('xul_recipient_barcode').focus();
17         $('xul_recipient_barcode').onkeypress = function(evt) 
18                 {if(userPressedEnter(evt)) { _holdsHandleStaff(); } };
19         $('xul_recipient_barcode_submit').onclick = _holdsHandleStaff;
20         $('xul_recipient_me').onclick = _holdsHandleStaffMe;
21 }
22
23 function _holdsHandleStaffMe() {
24         holdArgs.recipient = G.user;
25         holdsDrawEditor();
26 }
27
28 function _holdsHandleStaff() {
29         var barcode = $('xul_recipient_barcode').value;
30         var user = grabUserByBarcode( G.user.session, barcode );
31
32         var evt;
33         if(evt = checkILSEvent(user)) {
34                 alertILSEvent(user);
35                 return;
36         }
37
38         if(!barcode || !user) {
39                 alertId('holds_invalid_recipient', barcode);
40                 return
41         }
42
43         holdArgs.recipient = user;
44         holdsDrawEditor();
45 }
46
47
48
49 /** args:
50   * record, volume, copy (ids)
51   * request, recipient, editHold (objects)
52   */
53
54 function holdsDrawEditor(args) {
55
56         holdArgs = (args) ? args : holdArgs;
57
58     if(!noEmailMessage)
59         noEmailMessage = $('holds_email').removeChild($('holds.no_email'));
60
61     if(!noEmailMessageXUL)
62         noEmailMessageXUL = $('holds_email').removeChild($('holds.no_email.xul'));
63
64         if(isXUL() && holdArgs.recipient == null 
65                         && holdArgs.editHold == null) {
66                 holdsHandleStaff();
67                 return;
68         }
69
70         if(!holdArgs.recipient) holdArgs.recipient = G.user;
71         if(!holdArgs.requestor) holdArgs.requestor = G.user;
72
73         if(!(holdArgs.requestor && holdArgs.requestor.session)) {
74                 detachAllEvt('common','locationChanged');
75                 attachEvt('common','loggedIn', holdsDrawEditor)
76                 initLogin();
77                 return;
78         }
79
80         if(holdArgs.editHold) // flesh the args with the existing hold 
81                 holdArgsFromHold(holdArgs.editHold, holdArgs);
82
83         holdsDrawWindow();
84 }
85
86
87 // updates the edit window with the existing hold's data 
88 function _holdsUpdateEditHold() {
89
90         var hold = holdArgs.editHold;
91         var status = holdArgs.status;
92
93         var orgsel = $('holds_org_selector');
94     var frozenbox = $('holds_frozen_chkbox');
95
96         setSelector(orgsel, hold.pickup_lib());
97
98         if( hold.capture_time() || status > 2 ) {
99                 orgsel.disabled = true;
100         frozenbox.disabled = true;
101         $('holds_frozen_thaw_input').disabled = true;
102
103     } else {
104                 orgsel.disabled = false;
105         frozenbox.disabled = false;
106     }
107
108
109         $('holds_submit').onclick = holdsEditHold;
110         $('holds_update').onclick = holdsEditHold;
111
112         if(hold.phone_notify()) {
113                 $('holds_enable_phone').checked = true;
114                 $('holds_phone').value = hold.phone_notify();
115
116         } else {
117                 $('holds_phone').disabled = true;
118                 $('holds_enable_phone').checked = false;
119         }
120
121         if(isTrue(hold.email_notify())) {
122                 $('holds_enable_email').checked = true;
123
124         } else {
125                 $('holds_enable_email').checked = false;
126         }
127
128     /* populate the hold freezing info */
129     if(!frozenbox.disabled && isTrue(hold.frozen())) {
130         frozenbox.checked = true;
131         unHideMe($('hold_frozen_thaw_row'));
132         if(hold.thaw_date()) {
133             $('holds_frozen_thaw_input').value = hold.thaw_date();
134         } else {
135             $('holds_frozen_thaw_input').value = '';
136         }
137     } else {
138         frozenbox.checked = false;
139         $('holds_frozen_thaw_input').value = '';
140         hideMe($('hold_frozen_thaw_row'));
141     }
142 }
143
144 function holdsEditHold() {
145         var hold = holdsBuildHoldFromWindow();
146         if(!hold) return;
147         holdsUpdate(hold);
148         showCanvas();
149         if(holdArgs.onComplete)
150                 holdArgs.onComplete(hold);
151 }
152
153 function holdArgsFromHold(hold, oargs) {
154         var args = (oargs) ? oargs : {};
155         args.type = hold.hold_type();
156         var target = hold.target();
157
158         switch(args.type) {
159                 case 'M':
160                         args.metarecord = target;
161                         break;
162                 case 'T':
163                         args.record = target;
164                         break;
165                 case 'V':
166                         args.volume = target;
167                         break;
168                 case 'C':
169                         args.copy = target;
170                         break;
171         }
172         return args;
173 }
174
175 function holdFetchObjects(hold, doneCallback) {
176
177         var args = (hold) ? holdArgsFromHold(hold) : holdArgs;
178
179         var type = args.type;
180
181         if( type == 'C' ) {
182
183                 if( args.copyObject ) {
184
185                         args.copy = args.copyObject.id();
186                         args.volume = args.copyObject.call_number();
187                         _h_set_vol(args, doneCallback);
188
189                 } else {
190                         var creq = new Request(FETCH_COPY, args.copy);
191
192                         creq.callback(
193                                 function(r) {
194                                         var cp = r.getResultObject();
195                                         args.copyObject = cp;
196                                         args.volume = args.copyObject.call_number();
197                                         _h_set_vol(args, doneCallback);
198                                 }
199                         );
200                         creq.send();
201                 }
202         } else {
203                 if( type == 'V' ) {
204                         _h_set_vol(args, doneCallback);
205
206                 } else {
207                         if( type == 'T' ) {
208                                 _h_set_rec(args, doneCallback);
209                         } else {
210                                 _h_set_rec_descriptors(args, doneCallback);
211                         }
212                 }
213         }
214
215         return args;
216 }
217
218 function _h_set_vol(args, doneCallback) {
219
220         if( args.volumeObject ) {
221                 args.volume = args.volumeObject.id();
222                 args.record = args.volumeObject.record();
223                 _h_set_rec(args, doneCallback);
224
225         } else {
226
227                 var vreq = new Request(FETCH_VOLUME, args.volume);
228                 vreq.callback(
229                         function(r) {
230                                 var vol = r.getResultObject();
231                                 args.volumeObject = vol;
232                                 args.record = vol.record();
233                                 _h_set_rec(args, doneCallback);
234                         }
235                 );
236                 vreq.send();
237         }
238 }
239
240 function _h_set_rec(args, doneCallback) {
241
242         if(args.recordObject) 
243                 args.record = args.recordObject.doc_id();
244         else 
245                 args.recordObject = findRecord( args.record, 'T' );
246         
247         if( args.type == 'T' || args.type == 'M' ) 
248                 _h_set_rec_descriptors(args, doneCallback);
249         else 
250                 if(doneCallback) doneCallback(args);
251 }
252
253
254 function _h_set_rec_descriptors(args, doneCallback) {
255
256         // grab the list of record desciptors attached to this records metarecord 
257         if( ! args.recordDescriptors )  {
258                 var params = { record: args.record };
259
260                 if( ! args.record ) {
261                         if( args.metarecord )
262                                 params = { metarecord : args.metarecord };
263                         else 
264                                 params = { metarecord : args.metarecordObject.doc_id() };
265                 }
266
267                 var req = new Request(FETCH_MR_DESCRIPTORS, params );
268                 req.callback(
269                         function(r) {
270                                 var data = r.getResultObject();
271                                 args.recordDescriptors = data.descriptors;
272                                 args.metarecord = data.metarecord;
273                                 if( args.type == 'M' && ! args.metarecordObject) 
274                                         args.metarecordObject = findRecord(args.metarecord, 'M');       
275                                  
276                                 if(doneCallback) doneCallback(args);
277                         }
278                 );
279                 req.send();
280
281         } else {
282                 if(doneCallback) doneCallback(args);
283         }
284
285         return args;
286 }
287
288
289
290 function holdsDrawWindow() {
291         swapCanvas($('holds_box'));
292         $('holds_cancel').onclick = function(){ runEvt('common', 'holdUpdateCanceled'), showCanvas() };
293         $('holds_submit').onclick = function(){holdsPlaceHold(holdsBuildHoldFromWindow())};
294         $('holds_update').onclick = function(){holdsPlaceHold(holdsBuildHoldFromWindow())};
295         holdFetchObjects(null, 
296                 function(){
297                         __holdsDrawWindow();
298
299                         if(holdArgs.editHold) {
300                                 hideMe($('holds_submit'));
301                                 unHideMe($('holds_update'));
302                                 var req = new Request(FETCH_HOLD_STATUS, 
303                                         G.user.session, holdArgs.editHold.id());
304                                 req.send(true);
305                                 holdArgs.status = req.result();
306                                 _holdsUpdateEditHold();
307                         }  
308                 }
309         );
310 }
311
312 function __holdsDrawWindow() {
313
314         var rec = holdArgs.recordObject;
315         var vol = holdArgs.volumeObject;
316         var copy = holdArgs.copyObject;
317         var mr = holdArgs.metarecordObject;
318
319         rec = (rec) ? rec : mr;
320
321         if(!holdsOrgSelectorBuilt) {
322                 holdsBuildOrgSelector(null,0);
323                 holdsOrgSelectorBuilt = true;
324                 var selector = $('holds_org_selector');
325
326                 /*
327                 var o_loc = findOrgUnit(getOrigLocation());
328                 var t = findOrgType(o_loc.ou_type());
329                 if( t.can_have_users() ) 
330                         setSelector(selector, o_loc.id());
331                 else 
332                 */
333
334                 setSelector(selector, holdArgs.recipient.home_ou());
335         
336         }
337
338         /*
339         if(isXUL()) {
340                 var dsel = $('holds_depth_selector');
341                 unHideMe($('holds_depth_selector_row'));
342                 if(dsel.getElementsByTagName('option').length == 0) {
343                         var types = globalOrgTypes;
344                         var depth = findOrgDepth(G.user.ws_ou());
345                         iterate(types, 
346                                 function(t) {
347                                         if(t.depth() > depth) return;
348                                         insertSelectorVal(dsel, -1, t.opac_label(), t.depth());
349                                 }
350                         );
351                 }
352         }
353         */
354
355         appendClear($('holds_recipient'), text(
356                 holdArgs.recipient.family_name() + ', ' +  
357                         holdArgs.recipient.first_given_name()));
358         appendClear($('holds_title'), text(rec.title()));
359         appendClear($('holds_author'), text(rec.author()));
360
361         if( holdArgs.type == 'V' || holdArgs.type == 'C' ) {
362
363                 unHideMe($('holds_type_row'));
364                 unHideMe($('holds_cn_row'));
365                 appendClear($('holds_cn'), text(holdArgs.volumeObject.label()));
366
367                 if( holdArgs.type == 'V'  ) {
368                         unHideMe($('holds_is_cn'));
369                         hideMe($('holds_is_copy'));
370
371                 } else {
372                         hideMe($('holds_is_cn'));
373                         unHideMe($('holds_is_copy'));
374                         unHideMe($('holds_copy_row'));
375                         appendClear($('holds_copy'), text(holdArgs.copyObject.barcode()));
376                 }
377
378         } else {
379                 hideMe($('holds_type_row'));
380                 hideMe($('holds_copy_row'));
381                 hideMe($('holds_cn_row'));
382         }
383
384         removeChildren($('holds_format'));
385
386         var mods_formats = rec.types_of_resource();
387         var formats;
388
389         if(holdArgs.recordDescriptors)
390                 formats = holdArgs.recordDescriptors[0].item_type();
391
392         if( holdArgs.type == 'T' ) {
393                 var desc = grep( holdArgs.recordDescriptors,
394                         function(i) {
395                                 return (i.record() == holdArgs.record); 
396                         }
397                 );
398                 formats = desc[0].item_type();
399         }
400
401         if( holdArgs.type == 'M' ) {
402                 var data = holdsParseMRFormats(holdArgs.editHold.holdable_formats());
403                 mods_formats = data.mods_formats;
404                 formats = data.formats;
405         }
406
407
408         for( var i in mods_formats ) {
409                 var res = mods_formats[i];
410                 var img = elem("img");
411                 setResourcePic(img, res);
412                 $('holds_format').appendChild(img);
413                 if(formats)
414                         $('holds_format').appendChild(text(' '+ MARCTypeToFriendly(formats[i]) +' '));
415                 else
416                         $('holds_format').appendChild(text(' '+ mods_formats[i] +' '));
417                 $('holds_format').appendChild(elem('br'));
418         }
419
420
421         $('holds_phone').value = holdArgs.recipient.day_phone();
422         appendClear( $('holds_email'), text(holdArgs.recipient.email()));
423
424         var pref = G.user.prefs[PREF_HOLD_NOTIFY];
425
426         if(pref) {
427                 if( ! pref.match(/email/i) ) 
428                         $('holds_enable_email').checked = false;
429
430                 if( ! pref.match(/phone/i) ) {
431                         $('holds_phone').disabled = true;
432                         $('holds_enable_phone').checked = false;
433                 }
434         }
435
436     //if(!G.user.email()) {
437     if(!holdArgs.recipient.email()) {
438                 $('holds_enable_email').checked = false;        
439                 $('holds_enable_email').disabled = true;
440         var message;
441         if(isXUL()) {
442             message = noEmailMessageXUL.cloneNode(true);
443                 appendClear($('holds_email'), message);
444         } else {
445             message = noEmailMessage.cloneNode(true);
446                 appendClear($('holds_email'), message);
447             $('holds.no_email.my_account').setAttribute('href', buildOPACLink({page:MYOPAC},null,true));
448         }
449         unHideMe(message);
450     }
451
452         if(!$('holds_phone').value) 
453                 $('holds_enable_phone').checked = false;        
454
455         appendClear($('holds_physical_desc'), text(rec.physical_description()));
456
457         if(holdArgs.type == 'M') hideMe($('hold_physical_desc_row'));
458
459         holdsSetFormatSelector();
460 }
461
462 function holdsParseMRFormats(str) {
463         var data = str.split(/-/);      
464
465         var formats = [];
466         var mods_formats = [];
467
468         for( var i = 0; i < data[0].length; i++ ) {
469                 formats.push( data[0].charAt(i) );
470                 mods_formats.push( MARCFormatToMods( formats[i] ) );
471         }
472         
473         formats = uniquify(formats);
474         mods_formats = uniquify(mods_formats);
475
476         return {
477                 formats                 : formats,
478                 mods_formats    : mods_formats,
479                 lang                            : data[2],
480                 largeprint              : data[1]
481         };
482 }
483
484
485 function holdsSetFormatSelector() {
486         var type = holdArgs.type;
487         if( type == 'C' || type == 'V' || holdArgs.editHold ) return;
488
489         var data                                = holdsGetFormats();
490         var avail_formats       = data.avail_formats;
491         var sel_formats = data.sel_formats;
492         holdArgs.language = data.lang;
493
494         unHideMe($('holds_alt_formats_row_extras'));
495         var selector = $('hold_alt_form_selector');
496
497         for( var i = 0; i < avail_formats.length; i++ ) {
498                 var form = avail_formats[i];
499                 unHideMe(findSelectorOptByValue(selector, form));
500         }
501 }
502
503
504 function holdsGetFormats() {
505
506         var lang;
507         var formats = [];
508         var sformats = []; // selected formats 
509
510         var type = holdArgs.type;
511         var desc = holdArgs.recordDescriptors;
512         var rec = holdArgs.record;
513         var mrec = holdArgs.metarecord;
514
515         if( type == 'T' ) {
516
517                 for( var i = 0; i < desc.length; i++ ) {
518                         var d = desc[i];
519                         if( d.record() == holdArgs.record ) {
520                                 lang = d.item_lang();
521                                 holdArgs.myFormat =  _t_f_2_format(d.item_type(), d.item_form());
522                                 sformats.push(holdArgs.myFormat);
523                                 break;
524                         }
525                 }
526         }
527
528         for( var i = 0; i < desc.length; i++ ) {
529                 var d = desc[i];
530                 if( d.item_lang() != lang ) continue;
531                 formats.push( _t_f_2_format(d.item_type(), d.item_form()));
532         }
533
534         formats = uniquify(formats);
535
536         return {
537                 lang : lang,
538                 avail_formats : formats, 
539                 sel_formats : sformats
540         };
541 }
542
543
544
545 function _t_f_2_format(type, form) {
546         if( form == 'd' ) return 'at-d';
547         return (type == 'a' || type == 't') ? 'at' : 
548                 ( type == 'i' || type == 'g' || type == 'j' ) ? type : null;
549 }
550
551 function holdsSetSelectedFormats() {
552
553         var cn = $('holds_alt_formats_row').className;
554         if( cn && cn.match(/hide_me/) ) return;
555
556         var selector = $('hold_alt_form_selector');
557         var vals = getSelectedList(selector);
558
559         if(vals.length == 0) return;
560
561         var fstring = "";
562
563         if( contains(vals, 'at-d') ) {
564                 if( contains(vals, 'at') )
565                         fstring = 'at';
566                 else 
567                         fstring = 'at-d';
568         } else {
569                 if( contains(vals, 'at') )
570                         fstring = 'at';
571         }
572
573         for( var i = 0; i < vals.length; i++ ) {
574                 var val = vals[i];
575                 if( !val.match(/at/) ) fstring = val + fstring;
576         }
577
578         if( holdArgs.language ) {
579                 if( fstring.match(/-/) )
580                         fstring = fstring + '-' + holdArgs.language;
581                 else
582                         fstring = fstring + '--' + holdArgs.language;
583         }
584
585
586         return fstring;
587 }
588
589
590 function holdsCheckPossibility(pickuplib, hold, recurse) {
591
592         var args = { 
593                 titleid : holdArgs.record,
594                 volume_id : holdArgs.volume,
595                 copy_id : holdArgs.copy,
596                 hold_type : holdArgs.type,
597                 patronid : holdArgs.recipient.id(),
598                 depth : 0, 
599                 pickup_lib : pickuplib 
600         };
601
602         if(recurse) {
603                 /* if we're calling create again (recursing), 
604                         we know that the hold possibility check already succeeded */
605                 holdHandleCreateResponse({_recurse:true, _hold:hold}, true );
606
607         } else {
608                 _debug("hold possible args = "+js2JSON(args));
609         
610                 var req = new Request(CHECK_HOLD_POSSIBLE, G.user.session, args );
611         
612                 req.request.alertEvent = false;
613                 req.request._hold = hold;
614                 req.request._recurse = recurse;
615                 req.callback(holdHandleCreateResponse);
616                 req.send();
617         }
618 }
619
620
621 function holdsBuildOrgSelector(node) {
622
623         if(!node) node = globalOrgTree;
624
625         var selector = $('holds_org_selector');
626         var index = selector.options.length;
627
628         var type = findOrgType(node.ou_type());
629         var indent = type.depth() - 1;
630         var opt = setSelectorVal( selector, index, node.name(), node.id(), null, indent );
631         if(!type.can_have_users()) {
632                 opt.disabled = true;
633                 addCSSClass(opt, 'disabled_option');
634         }
635         
636         for( var i in node.children() ) {
637                 var child = node.children()[i];
638                 if(child) holdsBuildOrgSelector(child);
639         }
640 }
641
642 function holdsBuildHoldFromWindow() {
643
644         var org = getSelectorVal($('holds_org_selector'));
645         var node = findOrgUnit(org);
646         var ntype = findOrgType(node.ou_type());
647         if(!ntype.can_have_users()) {
648                 alertId('holds_pick_good_org');
649                 return;
650         }
651
652         var hold = new ahr();
653         if(holdArgs.editHold) {
654                 hold = holdArgs.editHold;
655                 holdArgs.editHold = null;
656         }
657
658         if( $('holds_enable_phone').checked ) {
659                 var phone = $('holds_phone').value;
660                 if( !phone || !phone.match(REGEX_PHONE) ) {
661                         alert($('holds_bad_phone').innerHTML);
662                         return null;
663                 }
664                 hold.phone_notify(phone);
665
666         } else {
667                 hold.phone_notify("");
668         }
669
670         if( $('holds_enable_email').checked ) 
671                 hold.email_notify(1);
672         else
673                 hold.email_notify(0);
674
675         var target;
676
677         switch(holdArgs.type) {
678                 case 'M':
679                         target = holdArgs.metarecord; break;
680                 case 'T':
681                         target = holdArgs.record; break;
682                 case 'V':
683                         target = holdArgs.volume; break;
684                 case 'C':
685                         target = holdArgs.copy; break;
686         }
687
688
689
690         hold.pickup_lib(org); 
691         //hold.request_lib(org); 
692         hold.requestor(holdArgs.requestor.id());
693         hold.usr(holdArgs.recipient.id());
694         hold.target(target);
695         hold.hold_type(holdArgs.type);
696
697     // see if this hold should be frozen and for how long
698     if($('holds_frozen_chkbox').checked) {
699         hold.frozen('t');
700         unHideMe($('hold_frozen_thaw_row'));
701         thawDate = $('holds_frozen_thaw_input').value;
702         if(thawDate) 
703             hold.thaw_date(thawDate);
704         else
705             hold.thaw_date(null);
706     }
707
708         //check for alternate hold formats 
709         var fstring = holdsSetSelectedFormats();
710         if(fstring) { 
711                 hold.hold_type('M'); 
712                 hold.holdable_formats(fstring);
713                 hold.target(holdArgs.metarecord);
714         }
715         return hold;
716 }
717         
718 function holdsPlaceHold(hold, recurse) {
719         if(!hold) return;
720         swapCanvas($('check_holds_box'));
721         holdsCheckPossibility(hold.pickup_lib(), hold, recurse);
722 }
723
724
725 function holdHandleCreateResponse(r, recurse) {
726
727         if(!recurse) {
728                 var res = r.getResultObject();
729                 if(!res || checkILSEvent(res) ) {
730                         if(!res) {
731                                 alert($('hold_not_allowed').innerHTML);
732                         } else {
733                                 if( res.textcode == 'PATRON_BARRED' ) {
734                                         alertId('hold_failed_patron_barred');
735                         } else {
736                                         alert($('hold_not_allowed').innerHTML);
737                                 }
738                         }
739                         swapCanvas($('holds_box'));
740                         return;
741                 }
742         }       
743
744         holdCreateHold(r._recurse, r._hold);
745 }
746
747
748 function holdCreateHold( recurse, hold ) {
749         var method = CREATE_HOLD;
750         if(recurse) method = CREATE_HOLD_OVERRIDE;
751         var req = new Request( method, holdArgs.requestor.session, hold );
752         req.request.alertEvent = false;
753         req.send(true);
754         var res = req.result();
755         holdProcessResult(hold, res, recurse);
756         
757         showCanvas();
758
759         runEvt('common', 'holdUpdated');
760 }
761
762
763 function holdProcessResult( hold, res, recurse ) {
764
765         if( res == '1' ) {
766                 alert($('holds_success').innerHTML);
767                 holdArgs = null;
768
769         } else {
770
771                 if( recurse ) {
772                         alert($('holds_failure').innerHTML);
773                         return;
774                 }
775
776                 if( grep(res, function(e) { return (e.textcode == 'HOLD_EXISTS'); }) ) {
777                         if( fetchPermOrgs('HOLD_EXISTS.override')[0] != -1 ) {
778                                 if( confirm($('hold_dup_exists_override').innerHTML) ) {
779                                         return holdsPlaceHold(hold, true);
780                                 }
781
782                         } else {
783                                 return alert($('hold_dup_exists').innerHTML);
784                         }
785                 }
786
787                 alert($('holds_failure').innerHTML);
788         }
789 }
790
791
792 function holdsCancel(holdid, user) {
793         if(!user) user = G.user;
794         var req = new Request(CANCEL_HOLD, user.session, holdid);
795         req.send(true);
796         return req.result();
797         runEvt('common', 'holdUpdated');
798 }
799
800 function holdsUpdate(hold, user) {
801         if(!user) user = G.user;
802         var req = new Request(UPDATE_HOLD, user.session, hold);
803         req.send(true);
804         var x = req.result(); // cause an exception if there is one 
805         runEvt('common', 'holdUpdated');
806 }
807
808