]> git.evergreen-ils.org Git - Evergreen.git/blob - Evergreen/xul/staff_client/server/patron/ue.js
firing onchange events for cloned phone numbers to make sure they propogate
[Evergreen.git] / Evergreen / xul / staff_client / server / patron / ue.js
1 var cgi                                                 = null;
2 var clone                                               = false;
3 var patron                                              = null;
4 var counter                                             = 0;
5 var identTypesCache                     = {};
6 var statCatsCache                               = {};
7 var surveysCache                                = {};
8 var surveyQuestionsCache        = {};
9 var surveyAnswersCache          = {};
10 var userCache                                   = {};
11 var groupsCache                         = {};
12 var netLevelsCache                      = {};
13 //var guardianNote                              = null; 
14
15 /* fetch the necessary data to start off */
16 function uEditInit() {
17
18         _debug('uEditInit(): ' + location.search);
19
20         cgi             = new CGI();
21         session = cgi.param('ses');
22         clone           = cgi.param('clone');
23         if(!session) throw "User session is not defined";
24
25         fetchUser(session);
26         $('uedit_user').appendChild(text(USER.usrname()));
27
28         setTimeout( function() { 
29                 uEditBuild(); uEditShowPage('uedit_userid'); }, 20 );
30 }
31
32 function uEditSetUnload() {
33    _debug('setting window unload event');
34    /*
35    window.onbeforeunload = function(evt) { 
36       return $('ue_unsaved_changes').innerHTML; 
37    };
38    */
39 }
40
41 function uEditClearUnload() {
42    _debug('clearing window unload event');
43    /*
44    window.onbeforeunload = null;
45    */
46 }
47
48 /* ------------------------------------------------------------------------------ */
49 /* Fetch code
50 /* ------------------------------------------------------------------------------ */
51 function uEditFetchIdentTypes() {
52         _debug("uEditFetchIdentTypes()");
53         var req = new Request(FETCH_ID_TYPES);
54         req.send(true);
55         return req.result();
56 }
57
58 function uEditFetchStatCats() {
59         _debug("uEditFetchStatCats()");
60         var req = new Request(SC_FETCH_ALL, SESSION);
61         req.send(true);
62         return req.result();
63 }
64
65 function uEditFetchSurveys() {
66         _debug("uEditFetchSurveys()");
67         var req = new Request(SV_FETCH_ALL, SESSION);
68         req.send(true);
69         return req.result();
70 }
71
72 function uEditFetchGroups() {
73         _debug("uEditFetchGroups()");
74         var req = new Request(FETCH_GROUPS);
75         req.send(true);
76         return req.result();
77 }
78
79 function uEditFetchNetLevels() {
80         _debug("uEditFetchNetLevels()");
81         var req = new Request(FETCH_NET_LEVELS, SESSION);
82         req.send(true);
83         return req.result();
84 }
85
86 /* ------------------------------------------------------------------------------ */
87
88
89
90 /* fetches necessary and builds the UI */
91 function uEditBuild() {
92         fetchHighestPermOrgs( SESSION, USER.id(), myPerms );
93
94         uEditBuildLibSelector();
95         patron = fetchFleshedUser(cgi.param('usr'));
96         if(!patron) patron = uEditNewPatron(); 
97         
98         uEditDraw( 
99                 uEditFetchIdentTypes(),
100                 uEditFetchGroups(),
101                 uEditFetchStatCats(),
102                 uEditFetchSurveys(),
103                 uEditFetchNetLevels()
104                 );
105
106         if(patron.isnew()) {
107                 if(clone) uEditClone(clone);
108                 else uEditCreateNewAddr();
109
110         } else {
111
112                 /* do we need to display the parent / gurdian field? */
113                 uEditCheckDOB(uEditFindFieldByKey('dob'));
114
115                 $('ue_barcode').disabled = true;
116                 unHideMe($('ue_mark_card_lost'));
117                 unHideMe($('ue_reset_pw'));
118                 uEditCheckEditPerm();
119         }
120
121         if(PERMS['BAR_PATRON'] == -1) 
122                 $('ue_barred').disabled = true;
123 }
124
125
126 /* if this user does not have permission to put users into
127         the edited users group, they do not have permission to 
128         edit this user */
129 function uEditCheckEditPerm() {
130
131         var perm = uEditFindGroupPerm(groupsCache[patron.profile()]);   
132         /*
133         _debug("editing user with group app perm "+patron.profile()+' : '+
134                 groupsCache[patron.profile()].name() +', and perm = ' + perm);
135                 */
136
137         if(PERMS[perm] != -1) return;
138
139         /* we can edit our own account, but not others in our group */
140         if( patron.id() != USER.id() ){
141                 _debug("we are not allowed to edit this user");
142         
143                 $('ue_save').disabled = true;
144                 $('ue_save_clone').disabled = true;
145                 $('ue_mark_card_lost').disabled = true;
146                 $('ue_reset_pw').disabled = true;
147         
148                 uEditIterateFields(
149                         function(f) {
150                                 if( f && f.widget && f.widget.node )
151                                         f.widget.node.disabled = true;
152                         }       
153                 );      
154
155         }
156
157         var node = $('ue_profile').parentNode;
158         node.removeChild($('ue_profile'));
159         node.appendChild(elem('span',null,groupsCache[patron.profile()].name()));
160
161         var field = uEditFindFieldByKey('profile');
162         field.required = false;
163         removeCSSClass(field.widget.node, CSS_INVALID_DATA);
164         uEditCheckErrors();
165 }
166
167
168 /* creates a new patron object with card attached */
169 var uEditCardVirtId = -1;
170 function uEditNewPatron() {
171         var patron = new au(); 
172         patron.isnew(1);
173         patron.id(-1);
174         card = new ac();
175         card.id(uEditCardVirtId--);
176         card.isnew(1);
177         patron.card(card);
178         patron.cards([card]);
179         patron.stat_cat_entries([]);
180         patron.survey_responses([]);
181         patron.addresses([]);
182         patron.home_ou(USER.ws_ou());
183         uEditMakeRandomPw(patron);
184         return patron;
185 }
186
187 function uEditMakeRandomPw(patron) {
188         var rand  = Math.random();
189         rand = parseInt(rand * 10000) + '';
190         while(rand.length < 4) rand += '0';
191         appendClear($('ue_password_plain'),text(rand));
192         unHideMe($('ue_password_gen'));
193         patron.passwd(rand);
194         return rand;
195 }
196
197 function uEditResetPw() { 
198         var pw = uEditMakeRandomPw(patron);     
199         $('ue_password1').value = pw;
200         $('ue_password2').value = pw;
201 }
202
203 function uEditClone(clone) {
204
205         var cloneUser = fetchFleshedUser(clone);
206         patron.usrgroup(cloneUser.usrgroup());
207
208         if( cloneUser.day_phone() ) {
209                 $('ue_day_phone').value = cloneUser.day_phone();
210             $('ue_day_phone').onchange();
211     }
212
213         if( cloneUser.evening_phone() ) {
214                 $('ue_night_phone').value = cloneUser.evening_phone();
215                 $('ue_night_phone').onchange();
216     }
217
218         if( cloneUser.other_phone() ) {
219                 $('ue_other_phone').value = cloneUser.other_phone();
220                 $('ue_other_phone').onchange();
221     }
222
223         setSelector($('ue_org_selector'), cloneUser.home_ou());
224         setSelector($('ue_profile'), cloneUser.profile());
225
226         /* force the expire date to be set */
227         $('ue_profile').onchange();
228         $('ue_org_selector').onchange();
229
230         for( var a in cloneUser.addresses() ) {
231                 var addr = cloneUser.addresses()[a];
232                 if( cloneUser.mailing_address && 
233                                 addr.id() == cloneUser.mailing_address().id() )
234                         patron.mailing_address(addr);
235                 if( cloneUser.billing_address() &&
236                                 addr.id() == cloneUser.billing_address().id() )
237                         patron.billing_address(addr);
238                 patron.addresses().push(addr);
239         }
240
241         uEditBuildAddrs(patron);
242 }
243
244
245 /* Creates a new blank address, 
246         adds it to the user and the fields array */
247 var uEditVirtualAddrId = -1;
248 function uEditCreateNewAddr() {
249         var addr = new aua();
250
251         addr.id(uEditVirtualAddrId--);
252         addr.isnew(1);
253         addr.usr(patron.id());
254         addr.country(defaultCountry);
255
256         if(!patron.addresses()) 
257                 patron.addresses([]);
258
259         if(patron.addresses().length == 0) {
260                 patron.mailing_address(addr);
261                 patron.billing_address(addr);
262         }
263
264         addr.valid(1);
265         addr.within_city_limits(1);
266
267         uEditBuildAddrFields(patron, addr);
268         patron.addresses().push(addr);
269         uEditIterateFields(function(f) { uEditCheckValid(f); });
270         uEditCheckErrors();
271 }
272
273
274 /* kicks off the UI drawing */
275 function uEditDraw(identTypes, groups, statCats, surveys, netLevels ) {
276         hideMe($('uedit_loading'));
277         unHideMe($('ue_maintd'));
278
279         dataFields = [];
280         uEditDrawIDTypes(identTypes);
281         uEditDrawGroups(groups, null, null, true);
282         uEditDrawStatCats(statCats);
283         uEditDrawSurveys(surveys);
284         uEditDrawNetLevels(netLevels);
285         uEditDefineData(patron);
286
287         uEditIterateFields(function(f) { uEditActivateField(f) });
288         uEditIterateFields(function(f) { uEditCheckValid(f); });
289         uEditCheckErrors();
290 }
291
292
293 /** Applies the event handlers and sets the data for the field */
294 function uEditActivateField(field) {
295
296         if( field.widget.id ) {
297                 field.widget.node = $(field.widget.id);
298
299         } else {
300                 field.widget.node = 
301                         $n(field.widget.base, field.widget.name);
302         }
303
304         uEditSetOnchange(field);
305
306         if(field.widget.onblur) {
307                 field.widget.node.onblur = 
308                         function() { field.widget.onblur(field); };
309         }
310
311         field.widget.node.disabled = field.widget.disabled;
312         if(field.object == null) return;
313         var val = field.object[field.key]();
314         if(val == null) return;
315
316         if( field.widget.type == 'input' )
317                 field.widget.node.value = val;
318
319         if( field.widget.type == 'select' )
320                 setSelector(field.widget.node, val);
321
322         if( field.widget.type == 'checkbox' )
323                 field.widget.node.checked = 
324                         (val && val != 'f') ? true : false;
325
326         if( field.widget.onload ) 
327                 field.widget.onload(val);
328 }
329
330
331 /* set up the onchange event for the field */
332 function uEditSetOnchange(field) {
333         var func = function() {uEditOnChange( field );}
334         field.widget.node.onchange = func;
335
336         if(field.widget.type != 'select')
337                 field.widget.node.onkeyup = func;
338 }
339
340 /* find the current value of the field object's widget */
341 function uEditNodeVal(field) {
342         if(field.widget.type == 'input')
343                 return field.widget.node.value;
344
345         if(field.widget.type == 'checkbox')
346                 return field.widget.node.checked;
347
348         if(field.widget.type == 'select')
349                 return getSelectorVal(field.widget.node);
350 }
351
352
353 /* update a field value */
354 function uEditOnChange(field) {
355
356         var newval = uEditNodeVal(field);
357         field.object[field.key](newval);
358         field.object.ischanged(1);
359
360         if(field.widget.onpostchange)
361                 field.widget.onpostchange(field, newval);
362
363         //_debug(field.key+' = '+newval);
364
365         uEditIterateFields(function(f) { uEditCheckValid(f); });
366         uEditCheckErrors();
367
368    uEditSetUnload();
369 }
370
371
372 function uEditCheckValid(field) {
373         var newval = uEditNodeVal(field);
374
375         if(newval) {
376
377                 if(field.widget.regex) { 
378                         if(newval.match(field.widget.regex)) 
379                                 removeCSSClass(field.widget.node, CSS_INVALID_DATA);
380                         else
381                                 addCSSClass(field.widget.node, CSS_INVALID_DATA);
382
383                 } else {
384                         removeCSSClass(field.widget.node, CSS_INVALID_DATA);
385                 }
386
387         } else {
388
389                 if(field.required) {
390                         addCSSClass(field.widget.node, CSS_INVALID_DATA);
391
392                 } else {
393                         removeCSSClass(field.widget.node, CSS_INVALID_DATA);
394                 }
395         }
396
397 }
398
399 /* find a field object by object key */
400 function uEditFindFieldByKey(key) {
401         var fields = grep( dataFields,
402                 function(item) { return (item.key == key); });
403         return (fields) ? fields[0] : null;
404 }
405
406 /* find a list of fields by object key */
407 function uEditFindFieldsByKey(key) {
408         return grep( dataFields,
409                 function(item) { return (item.key == key); });
410 }
411
412 /* find a field object by widget id */
413 function uEditFindFieldByWId(id) {
414         var fields = grep( dataFields,
415                 function(item) { return (item.widget.id == id); });
416         return (fields) ? fields[0] : null;
417 }
418
419
420 function uEditIterateFields(callback) {
421         for( var f in dataFields ) 
422                 callback(dataFields[f]);
423 }
424
425
426 function uEditGetErrorStrings() {
427         var errors = [];
428         uEditIterateFields(
429                 function(field) { 
430                         if(field.errkey) {
431                                 if( !field.object.isdeleted() ) {
432                                         if( field.widget.node.className.indexOf(CSS_INVALID_DATA) != -1) {
433                                                 var str = $(field.errkey).innerHTML;
434                                                 if(str) errors.push(str);
435                                         }
436                                 }
437                         }
438                 }
439         );
440
441         /* munge up something for all of the required surveys 
442                 (which are not registered with the fields) */
443         if( patron.isnew() ) {
444                 var sel = $('ue_survey_table');
445
446                 if( sel ) {
447                         var rows = sel.getElementsByTagName('tr');
448
449                         for( var r in rows ) {
450                 
451                                 var row = rows[r];
452                                 var sel = $n(row, 'ue_survey_answer');
453                                 if(!sel) continue;
454                                 var qstn = row.getAttribute('question');
455                 
456                                 if(qstn) {
457                                         qstn            = surveyQuestionsCache[qstn];
458                                         survey  = surveysCache[qstn.survey()];
459                                         var val = getSelectorVal(sel);
460                                         if(!val && isTrue(survey.required()))
461                                                 errors.push($('ue_bad_survey').innerHTML + ' : ' + qstn.question());
462                                 }
463                         }
464                 }
465         }
466
467         /* ------------------------------------------------------------ */
468
469         if(errors[0]) return errors;
470         return null;
471 }
472
473 function uEditAlertErrors() {
474         var errors = uEditGetErrorStrings();
475         if(!errors) return false;
476         alert(errors.join("\n"));
477         return true;
478 }
479
480
481 /* send the user to the database */
482 function uEditSaveUser(cloneme) {
483
484         if(uEditGetErrorStrings()) {
485                 uEditAlertErrors();
486                 return;
487         }
488
489         /* null is unique in the db, but '' is not */
490         if( ! patron.ident_value() ) patron.ident_value(null);
491         //if( ! patron.ident_type2() ) patron.ident_type2(null);
492         if( ! patron.ident_value2() ) patron.ident_value2(null);
493         patron.ident_type2(null);
494
495         if(! patron.dob() ) patron.dob(null);
496
497         _debug("Saving patron with card: " + js2JSON(patron.card()));
498         _debug("Saving full patron: " + js2JSON(patron));
499
500         //for( var c in patron
501
502         var req = new Request(UPDATE_PATRON, SESSION, patron);
503         req.alertEvent = false;
504         req.send(true);
505         var newuser = req.result();
506
507    uEditClearUnload();
508
509         var evt;
510         if( (evt = checkILSEvent(newuser)) || ! newuser ) {
511                 if(evt) {
512                         var j = js2JSON(newuser); 
513                         alert(j);
514                         _debug("USER UPDATE FAILED:\n" + j);
515                 }
516                 return;
517         } 
518
519         alert($('ue_success').innerHTML);
520
521         if(cloneme) {
522                 /* if the user we just created was a clone, and we want to clone it,
523                 we really want to clone the original */
524                 if( clone ) cloneme = clone;
525                 else cloneme = newuser.id();
526         }
527
528
529         if( cloneme ) {
530
531                 if(window.xulG &&
532                         typeof window.xulG.spawn_editor == 'function' && 
533
534                         !patron.isnew() ) {
535                                 _debug("xulG clone spawning new interface...");
536                                 window.xulG.spawn_editor({ses:cgi.param('ses'),clone:cloneme});
537                                 uEditRefresh();
538
539                 } else {
540
541                         var href = location.href;
542                         href = href.replace(/\&?usr=\d+/, '');
543                         href = href.replace(/\&?clone=\d+/, '');
544                         href += '&clone=' + cloneme;
545                         location.href = href;
546                 }
547
548         } else {
549
550                 uEditRefresh();
551         }
552
553         uEditRefreshXUL(newuser);
554 }
555
556
557 function uEditRefreshXUL(newuser) {
558         if (window.xulG && typeof window.xulG.on_save == 'function') 
559                 window.xulG.on_save(newuser);
560 }
561
562 function uEditRefresh() {
563         var href = location.href;
564         href = href.replace(/\&?clone=\d+/, '');
565         location.href = href;
566 }
567
568
569 function uEditCancel() {
570         var href = location.href;
571         href = href.replace(/\&?usr=\d+/, '');
572         href = href.replace(/\&?clone=\d+/, '');
573         var id = cgi.param('usr')
574         /* reload the current user if available */
575         if( id ) href += "&usr=" + id;
576         location.href = href;
577 }
578
579
580 var uEditDupHashes = {};
581 var uEditDupTemplate;
582
583 function uEditRunDupeSearch(type, search_hash) {
584
585         if(!patron.isnew()) return;
586
587         _debug('dup search: ' + js2JSON(search_hash));
588
589         var req = new Request(PATRON_SEARCH, SESSION, search_hash);
590
591         var container = $('dup_div_container');
592         if(!uEditDupTemplate)
593                 uEditDupTemplate = container.removeChild($('dup_div'));
594
595         /* clear any existing dups for this type */
596         iterate( container.getElementsByTagName('div'),
597                 function(d) {
598                         if( d.getAttribute('type') == type ) {
599                                 container.removeChild(d)
600                                 return;
601                         }
602                 }
603         );
604
605         req.callback(
606                 function(r) {
607                         uEditHandleDupResults( r.getResultObject(), search_hash, type, container );
608                 }
609         );
610         req.send();
611 }
612
613
614 function uEditHandleDupResults(ids, search_hash, type, container) {
615
616         _debug('dup search results: ' + js2JSON(ids));
617
618         if(!(ids && ids[0]))  /* no results */
619                 return uEditDupHashes[type] = null;
620
621         /* add a dup link to the UI and plug in the data */
622         var node = uEditDupTemplate.cloneNode(true);
623         container.appendChild(node);
624         node.setAttribute('type', type);
625
626         var link = $n(node, 'link');
627         link.setAttribute('type', type);
628         unHideMe(link);
629         $n(node,'count').appendChild(text(ids.length));
630
631         for( var o in search_hash ) 
632                 $n(node, 'data').appendChild(
633                         text(search_hash[o].value + ' '));
634
635         uEditDupHashes[type] = search_hash;
636
637         switch(type) {
638                 case 'ident' :
639                         if(confirm($('ue_dup_ident1').innerHTML)) 
640                                 uEditShowSearch(null, type);
641                         break;
642         }
643 }
644
645
646 function uEditShowSearch(link,type) {
647         if(!type) type = link.getAttribute('type');
648         if(window.xulG)
649                 window.xulG.spawn_search(uEditDupHashes[type]); 
650         else alert('Search would be:\n' + js2JSON(uEditDupHashes[type]));
651 }
652
653 function uEditMarkCardLost() {
654
655         for( var c in patron.cards() ) {
656
657                 var card = patron.cards()[c];
658                 if( patron.card().id() == card.id() ) {
659
660                         /* de-activite the current card */
661                         card.ischanged(1);
662                         card.active(0);
663
664                         if( !card.barcode() ) {
665                                 /* a card exists in the array with no barcode */
666                                 ueRemoveCard(card.id());
667
668                         } else if( card.isnew() && card.active() == 0 ) {
669                                 /* a new card was created, then never used, removing.. */
670                                 _debug("removing new inactive card "+card.barcode());
671                                 ueRemoveCard(card.id());
672                         }
673
674                         /* create a new card for the patron */
675                         var newcard = new ac();
676                         newcard.id(uEditCardVirtId--);
677                         newcard.isnew(1);
678                         patron.card(newcard);
679                         patron.cards().push(newcard);
680
681
682                         /* reset the widget */
683                         var field = uEditFindFieldByWId('ue_barcode');
684                         field.widget.node.disabled = false;
685                         field.widget.node.value = "";
686                         field.widget.node.onchange();
687                         field.object = newcard;
688                         _debug("uEditMarkCardLost(): created new card object for user");
689                 }
690         }
691 }
692
693
694 function ueRemoveCard(id) {
695         _debug("removing card from cards() array: " + id);
696         var cds = grep( patron.cards(), function(c){return (c.id() != id)});
697         if(!cds) cds = [];
698         for( var j = 0; j < cds.length; j++ )
699                 _debug("patron card array now has :  "+cds[j].id());
700         patron.cards(cds);
701 }
702
703
704
705 function compactArray(arr) {
706         var a = [];
707         for( var i = 0; arr && i < arr.length; i++ ) {
708                 if( arr[i] != null )
709                         a.push(arr[i]);
710         }
711         return a;
712 }