]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/xul/staff_client/server/patron/user_editor.js
060b1325b90121cc2237770d7ae8e8eefc2de16c
[Evergreen.git] / Open-ILS / xul / staff_client / server / patron / user_editor.js
1
2 var cgi                                                 = null;
3 var patron                                              = null;
4 var advanced                                    = false;
5 var SC_FETCH_ALL                                = 'open-ils.circ:open-ils.circ.stat_cat.actor.retrieve.all';
6 var SC_CREATE_MAP                               = 'open-ils.circ:open-ils.circ.stat_cat.actor.user_map.create';
7 var SV_FETCH_ALL                                = 'open-ils.circ:open-ils.circ.survey.retrieve.all';
8 var FETCH_ID_TYPES                      = 'open-ils.actor:open-ils.actor.user.ident_types.retrieve';
9 var FETCH_GROUPS                                = 'open-ils.actor:open-ils.actor.groups.tree.retrieve';
10 var UPDATE_PATRON                               = 'open-ils.actor:open-ils.actor.patron.update';
11 var identTypes                                  = {};
12 var groupTree                                   = null;
13 var cachedSurveys                               = {};
14 var cachedSurveyQuestions       = {};
15 var cachedSurveyAnswers         = {};
16 var ERRORS                                              = ""; /* global set of errors */
17 var cachedStatCats                      = {};
18 var deletedStatCats                     = {};
19 var cachedAddresses                     = {};
20 var deletedAddresses                    = {};
21
22 var myPerms             = [ 'CREATE_USER', 'UPDATE_USER', 'CREATE_PATRON_STAT_CAT_ENTRY_MAP' ];
23
24 var pages               = [ 
25         'uedit_userid', 
26         'uedit_contact_info', 
27         'uedit_addresses', 
28         'uedit_groups', 
29         'uedit_stat_cats', 
30         'uedit_surveys',
31         'uedit_finalize',
32         ];
33
34 /* ID's of objects that should be focused when their page is made visible */
35 var pageFocus   = [
36         'ue_barcode',
37         'ue_email1',
38         'ue_addr_label_1',
39         'ue_profile',
40         'ue_stat_cat_selector_1',
41         'ue_survey_selector_1',
42         'ue_view_summary'
43 ];
44
45 var regexes             = {};
46 regexes.phone   = /\d{3}-\d{3}-\d{4}/;
47 regexes.email   = /\w+\@\w+\.\w+/;
48 regexes.date    = /^\d{4}-\d{2}-\d{2}/;
49 regexes.isnum   = /^\d+$/;
50
51 /* fetch the necessary data to start off */
52 function uEditInit() {
53
54         cgi             = new CGI();
55         session = cgi.param('ses');
56         if(cgi.param('adv')) advanced = true 
57         if(!session) throw "User session is not defined";
58
59         fetchUser(session);
60         $('uedit_user').appendChild(text(USER.usrname()));
61         uEditShowPage('uedit_userid');
62
63         setTimeout( 
64                 function() { 
65
66                         /* these can be asynch */
67                         fetchHighestPermOrgs( SESSION, USER.id(), myPerms );
68                         uEditFetchSurveys();
69
70                         /* these have to be synchronous */
71                         uEditBuildLibSelector();
72                         uEditFetchIDTypes();
73                         uEditBuildAddrs();
74                         uEditFetchGroups();
75                         uEditFetchStatCats();
76
77                         uEditDrawUser(fetchFleshedUser(cgi.param('usr')));
78
79                 }, 20 
80         );
81 }
82
83 /* UI code ---------------------------------------------------- */
84
85 function uEditNext() {
86         var i = _findActive();
87         if( i < (pages.length - 1)) uEditShowPage(pages[i+1]);
88 }
89
90 function uEditPrev() {
91         var i = _findActive();
92         if( i > 0 ) uEditShowPage(pages[i-1]);
93 }
94
95 function uEditFetchError(id) { if($(id)) return $(id).innerHTML + "\n"; return "";}
96
97 function uEditShowPage(id) {
98         if( id == null ) return;
99
100         for( var p in pages ) {
101                 var page = pages[p];
102                 hideMe($(page));
103                 removeCSSClass($(page+'_label'), 'label_active');
104         }
105
106         unHideMe($(id));
107         addCSSClass($(id+'_label'), 'label_active');
108         var idx = _findPageIdx(id);
109         var fpage = pageFocus[idx];
110         if(fpage) { $(fpage).focus(); try{$(fpage).select()}catch(e){} }
111
112         unHideMe($('ue_back'));
113         unHideMe($('ue_fwd'));
114
115         if(idx == 0) hideMe($('ue_back'));
116         if(idx == (pages.length-1)) hideMe($('ue_fwd'));
117 }
118
119
120 function _findActive() {
121         for( var p in pages ) {
122                 if(! $(pages[p]).className.match(/hide_me/) )
123                         return parseInt(p);
124         }
125         return null;
126 }
127 function _findPageIdx(name) {
128         for( var i in pages ) {
129                 var page = pages[i];
130                 if( page == name ) return i;
131         }
132         return -1;
133 }
134
135 function uEditAddrHighlight( node, type ) {
136         var tbody = $('ue_address_tbody');
137         for( var c in tbody.childNodes ) {
138                 var row = tbody.childNodes[c];
139                 if(row.nodeType != XML_ELEMENT_NODE ) continue;
140                 var div = $n(row,'ue_addr_'+type+'_yes').parentNode;
141                 removeCSSClass(div, 'addr_info_checked');
142         }
143         addCSSClass(node.parentNode, 'addr_info_checked');
144 }
145
146
147 /* ------------------------------------------------------------------------------ */
148 /* Fetch code
149 /* ------------------------------------------------------------------------------ */
150 function uEditFetchIDTypes() {
151         var req = new Request(FETCH_ID_TYPES);
152         //req.callback(uEditDrawIDTypes);
153         req.send(true);
154         uEditDrawIDTypes(req.request);
155 }
156
157 function uEditFetchStatCats() {
158         var req = new Request(SC_FETCH_ALL, SESSION);
159         //req.callback(uEditDrawStatCats);
160         req.send(true);
161         uEditDrawStatCats(req.request);
162 }
163
164 function uEditFetchSurveys() {
165         var req = new Request(SV_FETCH_ALL, SESSION);
166         req.callback(uEditDrawSurveys);
167         req.send();
168 }
169
170
171 /* ------------------------------------------------------------------------------ */
172 /* Save the user
173 /* ------------------------------------------------------------------------------ */
174 var uEditExistingStatEntries;
175 var uEditExistingSurveyResponses;
176
177 function uEditSaveUser() {
178         uEditCollectData();
179
180         if(ERRORS) { 
181                 alert(ERRORS); 
182                 ERRORS = ""; 
183                 return;
184         }
185
186         //alert(js2JSON(patron));
187         //return;
188
189         var req = new Request(UPDATE_PATRON, SESSION, patron);
190         req.send(true);
191         var result = req.result();
192         if( checkILSEvent(result) ) alert(js2JSON(result));
193         else alert($('ue_success').innerHTML);
194
195 }
196
197 function uEditCollectData() {
198
199         var card                = null;
200
201         if(patron == null) { 
202                 patron = new au(); 
203                 patron.isnew(1);
204                 patron.id(-1);
205                 card = new ac();
206                 patron.card(-1); /* attach to the virtual id of the card */
207                 patron.cards([card]);
208
209         } else { 
210
211                 /* if this function is called again, patron will exist */
212                 if(!patron.isnew()) { 
213                         patron.ischanged(1); 
214                         patron.isnew(0);
215                         if(!uEditExistingStatEntries)
216                                 uEditExistingStatEntries = patron.stat_cat_entries();
217                         if(!uEditExistingSurveyResponses)
218                                 uEditExistingSurveyResponses = patron.survey_responses();
219                 }
220         }
221
222         patron.stat_cat_entries([]);
223         patron.survey_responses([]);
224
225         uEditFleshCard(card);
226         uEditAddBasicPatronInfo(patron);
227         uEditAddPhones(patron);
228         uEditAddIdents(patron);
229         uEditAddAddresses(patron);
230         uEditAddGroupsAndPerms(patron);
231         uEditReapStatCats(patron);
232         uEditReapSurveys(patron);
233
234 }
235
236
237
238 /* ------------------------------------------------------------------------------ */
239 /* Draw the user
240 /* ------------------------------------------------------------------------------ */
241 function uEditDrawUser(p) {
242
243         hideMe($('uedit_loading'));
244         unHideMe($('ue_maintd'));
245
246         if(!p) return;
247         patron = p;
248
249         $('ue_barcode').value                   = patron.card().barcode();
250         $('ue_username').value                  = patron.usrname();
251         $('ue_firstname').value                 = patron.first_given_name();
252         $('ue_middlename').value                = patron.second_given_name();
253         $('ue_lastname').value                  = patron.family_name();
254         $('ue_suffix').value                            = patron.suffix();
255         $('ue_dob').value                                       = patron.dob();
256         $('ue_primary_ident').value     = patron.ident_value();
257         $('ue_secondary_ident').value   = patron.ident_value2();
258         $('ue_email1').value                            = patron.email();
259         $('ue_email2').value                            = patron.email();
260         $('ue_expire').value                            = patron.expire_date();
261         $('ue_active').value                            = patron.active();
262         $('ue_barred').value                            = patron.barred();
263         $('ue_claims_returned').value   = patron.claims_returned_count();
264         $('ue_alert_message').value     = patron.alert_message();
265
266         setSelector( $('ue_primary_ident_type'), patron.ident_type() );
267         setSelector( $('ue_secondary_ident_type'), patron.ident_type2() );
268         setSelector( $('ue_org_selector'), patron.home_ou() );
269         setSelector( $('ue_profile'), patron.profile() );
270         
271         /* flesh out the phone numbers ------------------------- */
272         var dp = patron.day_phone();
273         var np = patron.evening_phone();
274         var op = patron.other_phone();
275
276         if(dp) {
277                 var daynums = dp.split('-');
278                 $('ue_day_phone_area').value            = daynums[0];
279                 $('ue_day_phone_prefix').value  = daynums[1];
280                 $('ue_day_phone_suffix').value  = daynums[2];
281         }
282
283         if(np) {
284                 var nightnums = np.split('-');
285                 $('ue_night_phone_area').value  = nightnums[0];
286                 $('ue_night_phone_prefix').value        = nightnums[1];
287                 $('ue_night_phone_suffix').value        = nightnums[2];
288         }
289
290         if(op) {
291                 var othernums = op.split('-');
292                 $('ue_other_phone_area').value  = othernums[0];
293                 $('ue_other_phone_prefix').value        = othernums[1];
294                 $('ue_other_phone_suffix').value        = othernums[2];
295         }
296
297
298         /* Flesh the addresses ------------------------------------ */
299         var i = 0;
300         var tbody = $('ue_address_tbody');      
301         for( var i = 0; i != patron.addresses().length; i++ ) {
302                 var addr = patron.addresses()[i];
303                 cachedAddresses[addr.id()] = addr;
304                 var row;
305                 if( i == 0 ) row = getElementsByTagNameFlat(tbody, 'tr')[0];
306                 else row = $('ue_address_new').onclick(); /* create a new row if necessary */
307
308                 row.setAttribute('exists', addr.id() );
309
310                 if( patron.mailing_address().id() == addr.id())
311                         $n(row, 'ue_addr_mailing_yes').checked = true;
312
313                 if( patron.billing_address().id() == addr.id())
314                         $n(row, 'ue_addr_billing_yes').checked = true;
315                 
316                 if( addr.valid() ) $n(row, 'ue_addr_valid_yes').checked = true;
317
318         
319                 $n(row, 'ue_addr_label').value  = addr.address_type();
320                 $n(row, 'ue_addr_street1').value        = addr.street1();
321                 $n(row, 'ue_addr_street2').value = addr.street2();
322                 $n(row, 'ue_addr_city').value           = addr.city();
323                 $n(row, 'ue_addr_county').value = addr.county();
324                 $n(row, 'ue_addr_state').value  = addr.state();
325                 $n(row, 'ue_addr_zip').value            = addr.post_code();
326                 $n(row, 'ue_addr_country').value        = addr.country();
327
328         }
329
330
331
332         var stattbody = $('ue_stat_cat_tbody');
333         for( var m in patron.stat_cat_entries() ) {
334                 var map = patron.stat_cat_entries()[m];
335                 var row = grep( getElementsByTagNameFlat( stattbody, 'tr' ), 
336                         function(a) { return a.getAttribute('statcat') == map.stat_cat() })[0];
337                 $n(row, 'ue_stat_cat_newval').value = map.stat_cat_entry();
338                 setSelectorByName( $n(row, 'ue_stat_cat_selector'), map.stat_cat_entry() );
339         }
340 }
341
342
343
344
345
346 /* ------------------------------------------------------------------------------ */
347 /* Draw the ID types
348 /* ------------------------------------------------------------------------------ */
349 function uEditDrawIDTypes(r) {
350
351         var types       = r.getResultObject();
352         var pri_sel = $('ue_primary_ident_type');
353         var sec_sel = $('ue_secondary_ident_type');
354
355         var idx = 1;
356         for( var t in types ) {
357                 var type = types[t];
358                 identTypes[type.id()] = type;
359                 setSelectorVal( pri_sel, idx, type.name(), type.id() );
360
361                 if(patron && patron.ident_type() != null ) 
362                         setSelector( pri_sel, patron.ident_type() );
363
364                 setSelectorVal( sec_sel, idx++, type.name(), type.id() );
365                 if(patron && patron.ident_type2() != null ) 
366                         setSelector( sec_sel, patron.ident_type2() );
367         }
368 }
369
370
371
372 /* ------------------------------------------------------------------------------ */
373 /* Stat Cat handling code
374 /* ------------------------------------------------------------------------------ */
375 function uEditDrawStatCats(r) {
376         var cats = r.getResultObject();
377         var tbody = $('ue_stat_cat_tbody');
378         var templ = tbody.removeChild($('ue_stat_cat_row'));
379
380         for( var c in cats ) {
381                 var row = templ.cloneNode(true);
382                 uEditInsertCat( tbody, row, cats[c], c );
383                 tbody.appendChild(row);
384         }
385 }
386
387 /* fleshes the stat cat with entries in the dropdown */
388 function uEditInsertCat( tbody, row, cat, idx ) {
389
390         cat.entries().sort(  /* sort the entries by value */
391                 function( a, b ) { 
392                         if( a.value().toLowerCase() > b.value().toLowerCase()) return 1;
393                         if( a.value().toLowerCase() < b.value().toLowerCase()) return -1;
394                         return 0;
395                 }
396         );
397
398         cachedStatCats[cat.id()] = cat;
399
400         row.setAttribute('statcat', cat.id());
401         var newval = $n(row, 'ue_stat_cat_newval');
402         newval.onchange = function(){ 
403                 findParentByNodeName(newval,'tr').setAttribute('changed', '1'); }
404
405         var selector = $n(row, 'ue_stat_cat_selector');
406         selector.onchange = function(){ 
407                 findParentByNodeName(selector, 'tr').setAttribute('changed', '1'); 
408                 newval.value = getSelectorName(selector);
409                 newval.setAttribute('entry', getSelectorVal(selector));
410         }
411
412         if( idx == 0 ) selector.id = 'ue_stat_cat_selector_1'; 
413
414         $n(row, 'ue_stat_cat_name').appendChild(text(cat.name()));
415         $n(row, 'ue_stat_cat_owner').appendChild(
416                 text(fetchOrgUnit(cat.owner()).shortname()));
417
418         var idx = 1;
419         for( var e in cat.entries() ) {
420                 var entry = cat.entries()[e];
421                 setSelectorVal( selector, idx++, entry.value(), entry.id() );
422         }
423 }
424
425 /* finds all the changed/new stat entries and updates the patron object*/
426 function uEditReapStatCats(patron) {
427    var tbody = $('ue_stat_cat_tbody');
428         for( var r in tbody.childNodes ) {
429                 var row = tbody.childNodes[r];
430                 if( !row || row.nodeName != 'tr' ) continue;
431                 if( row.getAttribute('changed') ) {
432                         var val = $n( row, 'ue_stat_cat_newval' );
433                         uEditCreateStatMap( patron, row.getAttribute('statcat'), 
434                                 val.value, val.getAttribute('entry') );
435                 }
436         }
437 }
438
439
440 function uEditCreateStatMap( patron, catid, newval, entryid ) {
441
442         if( ! patron.isnew() ) {
443
444                 /* if the patron exists and we're editing an entry that's 
445                 already been created for this user... */
446                 for( var m in uEditExistingStatEntries ) {
447                         var map = uEditExistingStatEntries[m];
448                         if( map.stat_cat() == catid ) {
449                                 if( newval ) map.ischanged(1);
450                                 else map.isdeleted(1); 
451                                 patron.stat_cat_entries().push(map);
452                                 return;
453                         }
454                 }
455         }
456
457         var map = new actscecm();
458         map.isnew(1);
459         map.stat_cat_entry(newval);
460         map.stat_cat(catid);
461         map.target_usr(patron.id());
462         patron.stat_cat_entries().push(map);
463 }
464
465
466
467 /* ------------------------------------------------------------------------------ */
468 /* Survey handling code
469 /* ------------------------------------------------------------------------------ */
470 function uEditDrawSurveys(r) {
471
472         var surveys = r.getResultObject();
473         var div = $('uedit_surveys');
474         var table = div.removeChild($('ue_survey_table'));
475
476         var x = 0;
477         for( var s in surveys ) {
478                 var survey = surveys[s];
479                 cachedSurveys[survey.id()] = survey;
480                 var clone = table.cloneNode(true);
481                 uEditInsertSurvey( div, clone, survey, x++ );
482                 div.appendChild(clone);
483         }
484 }
485
486 function uEditInsertSurvey( div, table, survey, sidx ) {
487         $n(table, 'ue_survey_name').appendChild(text(survey.name()));
488         $n(table, 'ue_survey_desc').appendChild(text(survey.description()));
489         var tbody = $n(table, 'ue_survey_tbody');
490         var templ = tbody.removeChild($n(table, 'ue_survey_row'));
491
492         var polldiv             = $('ue_survey_answer_poll');
493
494         var idx = 1;
495         for( var q in survey.questions() ) {
496                 var row = templ.cloneNode(true);
497                 var quest = survey.questions()[q];
498                 cachedSurveyQuestions[quest.id()] = quest;
499                 uEditInsertSurveyQuestion( div, table, tbody, row, survey, quest, sidx );
500                 tbody.appendChild(row);
501         }
502 }
503
504 function uEditInsertSurveyQuestion( div, table, tbody, row, survey, question, sidx ) {
505
506         $n(row, 'ue_survey_question').appendChild(text(question.question()));
507
508         var selector    = $n(row, 'ue_survey_answer');
509         var polldiv             = $n(row, 'ue_survey_answer_poll');
510         var idx                 = 1;
511         var polltbody   = $n(row, 'ue_survey_answer_poll_tbody');
512         var pollrow             = polltbody.removeChild($n(polltbody, 'ue_survey_answer_poll_row'));
513
514         table.setAttribute('survey', survey.id());
515         row.setAttribute('question', question.id());
516
517         selector.onchange = function() {
518                 row.setAttribute('answer', getSelectorVal(selector));
519                 row.setAttribute('changed', '1');
520         }
521
522         if( sidx == 0 ) selector.id = 'ue_survey_selector_1'; 
523
524         for( var a in question.answers() ) {
525
526                 var answer = question.answers()[a];
527                 cachedSurveyAnswers[answer.id()] = answer;
528
529                 if( survey.poll() ) {
530
531                         unHideMe(polldiv);
532                         var prow = pollrow.cloneNode(true);
533
534
535                         $n(prow, 'ue_survey_answer_poll_answer').appendChild(text(answer.answer()));
536
537
538                         var input = elem('input', { 
539                                         type    : 'radio', 
540                                         name    : 'survey_poll_answer_'+survey.id(),
541                                         id              :  answer.id()
542                                 });
543
544                         input.onchange  = function() {
545                                 row.setAttribute('answer', answer.id());
546                                 row.setAttribute('changed', '1');
547                         }
548
549                         $n(prow, 'ue_survey_answer_poll_radio').appendChild(input);
550                         polltbody.appendChild(prow);
551
552                 } else {
553
554                         unHideMe(selector.parentNode);
555                         setSelectorVal( selector, idx++, answer.answer(), answer.id() );
556                 }
557         }
558 }
559
560
561 function uEditReapSurveys(patron) {
562
563         var div = $('uedit_surveys');
564         var tables = getElementsByTagNameFlat(div, 'table');
565
566         for( var t in tables ) {
567
568                 var table               = tables[t];
569                 var survey              = cachedSurveys[table.getAttribute('survey')];
570                 var tbody               = getElementsByTagNameFlat( table, 'tbody' )[0];
571                 var rows                        = getElementsByTagNameFlat( tbody, 'tr' );
572
573                 for( var r in rows ) {
574                         var row = rows[r];
575                         if(!row.getAttribute('changed')) continue;
576
577                         var resp        = new asvr();
578                         resp.isnew(1);
579                         resp.survey(survey.id());
580                         resp.usr(patron.id());
581                         resp.question(row.getAttribute('question'));
582                         resp.answer(row.getAttribute('answer'));
583                         patron.survey_responses().push( resp );
584                 }
585         }
586 }
587
588
589
590
591
592
593 /* returns true if an error occurred */
594 function uEditSetVal( obj, func, val, regxtype, errtype ) {
595
596         var error = uEditFetchError(errtype);
597         var iserr = false;
598
599         while(1) {
600
601                 if( val == null ) { iserr = true; break; }
602
603                 if(!instanceOf(val, String)) {
604                         try { val = val.value; } catch(e) { return; }
605                 }
606
607                 if(val == "" ) { iserr = true; break; }
608
609                 if(regxtype && regexes[regxtype] 
610                         && !val.match(regexes[regxtype]) ) { iserr = true; break; }
611
612                 try { obj[func](val); } catch(e) {
613                         alert("Error running function: " +func);
614                 }
615
616                 break;
617         }
618
619         if(iserr) { ERRORS += error; return true; }
620         return false;
621 }
622
623
624 function uEditAddBasicPatronInfo(patron) {
625
626
627
628         /* make sure passwords match */
629         var p1 = $('ue_password1').value;
630         var p2 = $('ue_password1').value;
631
632         if( p1 || patron.isnew() ) { /* existing patrons will have a blank password */
633                 if( p1 != p2 || uEditSetVal( patron, "passwd", p1 )) 
634                         ERRORS += uEditFetchError('ue_bad_password');
635         }
636         
637         uEditSetVal(patron, "usrname", $('ue_username'), null, 'ue_bad_username' );
638         uEditSetVal(patron, "first_given_name", $('ue_firstname'), null, 'ue_bad_firstname' );
639         uEditSetVal(patron, "second_given_name", $('ue_middlename'), null, 'ue_bad_middlename' ); 
640         uEditSetVal(patron, "family_name", $('ue_lastname'), null, 'ue_bad_lastname' ); 
641         uEditSetVal(patron, "dob", $('ue_dob'), 'date', 'ue_bad_dob' );
642
643         patron.suffix($('ue_suffix').value); /* suffis isn't required */
644
645
646         /* make sure emails match */
647         var email       = $('ue_email1').value;
648         var email2      = $('ue_email2').value;
649         if( email != email2 || uEditSetVal(patron, "email", email, 'email' ))
650                 ERRORS += uEditFetchError('ue_bad_email');
651
652         patron.home_ou(getSelectorVal($('ue_org_selector')));
653 }
654
655 function uEditAddPhones(patron) {
656
657
658         /* verifies the phone numbers are formatted correctly */
659         var verify = function(n1, n2, n3) {
660                 var a = n1.value;
661                 var p = n2.value;
662                 var s = n3.value;
663                 if( !a || !p || !s ) return false;
664                 return a + '-' + p + '-' + s;
665         }
666
667
668         var er = 'ue_bad_phone'
669
670         uEditSetVal( patron, "day_phone", 
671                 verify($('ue_day_phone_area'), 
672                 $('ue_day_phone_prefix'), 
673                 $('ue_day_phone_suffix')), 'phone', er );
674
675         uEditSetVal( patron, "evening_phone", 
676                 verify($('ue_night_phone_area'), 
677                 $('ue_night_phone_prefix'), 
678                 $('ue_night_phone_suffix')), 'phone', er );
679
680         if( $('ue_other_phone_prefix').value ) {
681                 uEditSetVal( patron, "other_phone", 
682                         verify($('ue_other_phone_area'), 
683                         $('ue_other_phone_prefix'), 
684                         $('ue_other_phone_suffix')), 'phone', er );
685         }
686
687 }
688
689 function uEditFleshCard(card) {
690         if(!card) return "";
691
692         if(uEditSetVal( card, "barcode", $('ue_barcode'), null, 'ue_bad_barcode' ))
693                 return; 
694
695         card.id(-1);
696         card.active(1);
697         return "";
698 }
699
700 function uEditAddIdents(patron) {
701
702         var err = 'ue_no_ident';
703
704         uEditSetVal( patron, "ident_type", 
705                 getSelectorVal($('ue_primary_ident_type')), 'isnum', err );
706
707         uEditSetVal( patron, "ident_type2", 
708                 getSelectorVal($('ue_secondary_ident_type')), 'isnum', err );
709
710         uEditSetVal( patron, "ident_value", 
711                 $('ue_primary_ident'), null, err );
712
713         uEditSetVal( patron, "ident_value2", 
714                 $('ue_secondary_ident'), null, err );
715
716 }
717
718
719 function uEditBuildLibSelector( node, depth, selector ) {
720         if(!selector) selector = $('ue_org_selector');
721         if(!node) { depth = 0; node = globalOrgTree; }
722         
723         var opt = insertSelectorVal( selector, -1, node.name(), node.id(), null, depth++ );
724
725         /* allow these orgs to be selectable via permission? */
726         if(!findOrgType(node.ou_type()).can_have_vols()) opt.disabled = true; 
727
728         if( node.id() == USER.home_ou() ) setSelector(selector, node.id());
729         for( var c in node.children() ) 
730                 uEditBuildLibSelector(node.children()[c], depth, selector);
731 }
732
733 function uEditFetchGroups() {
734         var req = new Request(FETCH_GROUPS);
735         //req.callback(uEditDrawGroups);
736         req.send(true);
737         uEditDrawGroups(req.request);
738 }
739
740 function uEditDrawGroups(r, tree, depth, selector) {
741
742         if(!tree) {
743                 tree = r.getResultObject();     
744                 depth = 0;
745                 groupTree = tree;
746                 selector = $('ue_profile');
747         }
748
749         insertSelectorVal( selector, -1, tree.name(), tree.id(), null, depth++ );       
750         for( var c in tree.children() ) 
751                 uEditDrawGroups( null, tree.children()[c], depth, selector );
752 }
753
754
755
756 function uEditAddGroupsAndPerms(patron) {
757
758         uEditSetVal( patron, "profile", 
759                 getSelectorVal($('ue_profile')), 'isnum', 'ue_no_profile');
760
761         var expire = $('ue_expire').value;
762         if(expire) 
763                 uEditSetVal( patron, "expire_date", expire, 'date', 'ue_bad_expire' );
764
765         if($('ue_active').checked) patron.active(1);
766         if($('ue_barred').checked) patron.barred(1);
767         if($('ue_group_lead').checked) patron.master_account(1);
768
769         uEditSetVal( patron, "claims_returned_count", 
770                 $('ue_claims_returned'), 'isnum', 'ue_bad_claims_returned');
771
772         if($('ue_alert_message').value) 
773                 uEditSetVal(patron, "alert_message", $('ue_alert_message'));
774 }
775
776
777
778 function uEditAddAddresses(patron) {
779         var tbody = $('ue_address_tbody');      
780         patron.addresses([]);
781
782         /* shove the addresses living in the page into the patron */
783         for( var r in tbody.childNodes ) {
784                 var row = tbody.childNodes[r];
785                 if(!(row && row.nodeName == 'tr')) continue;
786                 patron.addresses().push( uEditBuildAddress( patron, tbody, row ));      
787         }
788         for( var a in deletedAddresses ) {
789                 var addr = deletedAddresses[a];
790                 patron.addresses().push(addr);
791         }
792 }
793
794 /* extracts a single address from the page */
795 var uEditVirtualAddrId = -1;
796 function uEditBuildAddress( patron, tbody, row ) {
797
798         var addr = new aua();
799         var id = row.getAttribute('exists');
800
801         if(id) {
802                 addr.id(id)
803                 addr.ischanged(1);
804                 addr.isnew(0);
805         } else {
806                 addr.id(uEditVirtualAddrId--);
807                 addr.isnew(1);
808         }
809
810         if($n(row, 'ue_addr_mailing_yes').checked) patron.mailing_address(addr.id());
811         if($n(row, 'ue_addr_billing_yes').checked) patron.billing_address(addr.id());
812         if($n(row, 'ue_addr_valid_yes').checked) addr.valid(1);
813         if($n(row, 'ue_addr_street2').value) addr.street2($n(row, 'ue_addr_street2').value);
814
815         uEditSetVal(addr, "address_type",       $n(row, 'ue_addr_label'),                       null, 'ue_bad_addr_label' );
816         uEditSetVal(addr, "street1",                    $n(row, 'ue_addr_street1'),             null, 'ue_bad_addr_street' );
817         uEditSetVal(addr, "city",                               $n(row, 'ue_addr_city'),                        null, 'ue_bad_addr_city' );
818         uEditSetVal(addr, "county",                     $n(row, 'ue_addr_county'),                      null, 'ue_bad_addr_county' );
819         uEditSetVal(addr, "state",                              $n(row, 'ue_addr_state'),                       null, 'ue_bad_addr_state' );
820         uEditSetVal(addr, "post_code",          $n(row, 'ue_addr_zip'),                         null, 'ue_bad_addr_zip' );
821         uEditSetVal(addr, "country",                    $n(row, 'ue_addr_country'),             null, 'ue_bad_addr_country' );
822
823         return addr;
824 }
825
826 function uEditRemoveAddress(node) {
827         if( confirm($("ue_delete_addr_warn").innerHTML) ) {
828                 var td      = node.parentNode.parentNode;
829                 var mytab   = td.parentNode.parentNode.parentNode;
830                 var row                 = mytab.parentNode.parentNode;
831                 if( row.getAttribute('exists') ) {
832                         var a =  cachedAddresses[row.getAttribute('exists')];
833                         a.isdeleted(1);
834                         deletedAddresses[a.id()] = a;
835                 }
836                 var tbody   = row.parentNode;
837                 tbody.removeChild(mytab.parentNode.parentNode);
838         }
839
840 }
841
842
843 var uEditAddrTemplate;
844 var uEditOrigAddrRow;
845 function uEditBuildAddrs() {
846
847         var tbody = $('ue_address_tbody');
848         uEditAddrTemplate = tbody.removeChild($('ue_address_template'));
849
850         $('ue_address_new').onclick = 
851                 function() { 
852                         /* we have to retain the mailing/billing radio input values */
853                         var rows = getElementsByTagNameFlat(tbody,'tr');
854                         var mailrow;
855                         var billrow;
856                         for( var r in rows ) {
857                                 var row = rows[r];
858                                 if($n(row,'ue_addr_mailing_yes').checked) mailrow = row;
859                                 if($n(row,'ue_addr_billing_yes').checked) billrow = row;
860                         }
861                         var newrow = uEditAddrTemplate.cloneNode(true);
862                         tbody.appendChild(newrow); 
863                         $n(newrow, 'ue_addr_label').focus();
864                         if(mailrow) $n(mailrow,'ue_addr_mailing_yes').checked = true;
865                         if(billrow) $n(billrow,'ue_addr_billing_yes').checked = true;
866                         return newrow;
867                 }
868
869         /* go ahead and add a blank addr */
870         if(!patron) {
871                 var row = uEditAddrTemplate.cloneNode(true);
872                 uEditOrigAddrRow = row;
873                 $n( row, 'ue_addr_label').id = 'ue_addr_label_1';
874                 tbody.appendChild(row); 
875                 return;
876         }
877 }
878
879
880 function uEditShowSummary() {
881         uEditCollectData();
882         var table = $('ue_summary_table').cloneNode(true);;
883         uEditFleshSummaryTable(table);
884         var win = window.open("", $('ue_summary_window').innerHTML );   
885         win.document.body.innerHTML = "";
886         win.document.body.appendChild(table);
887         ERRORS = "";
888 }
889
890 function uEditFleshSummaryTable(table) {
891
892         var yes = $('yes').innerHTML;
893         var no = $('no').innerHTML;
894
895         var identt1 = "";
896         var identt2 = "";
897         var homeorg = "";
898         var profile     = "";
899
900         if( patron.ident_type() != null) 
901                 identt1 = identTypes[patron.ident_type()].name();
902         if( patron.ident_type2() != null ) 
903                 identt2 = identTypes[patron.ident_type2()].name();
904         if( patron.home_ou() != null )
905                 homeorg = findOrgUnit(patron.home_ou()).name();
906         if( patron.profile() != null )
907                 profile = findTreeItemById(groupTree, patron.profile()).name();
908
909
910         $n(table, 'ue_summary_username').appendChild(text(patron.usrname()));
911         $n(table, 'ue_summary_firstname').appendChild(text(patron.first_given_name()));
912         $n(table, 'ue_summary_middlename').appendChild(text(patron.second_given_name()));
913         $n(table, 'ue_summary_lastname').appendChild(text(patron.family_name()));
914         $n(table, 'ue_summary_suffix').appendChild(text(patron.suffix()));
915         $n(table, 'ue_summary_dob').appendChild(text(patron.dob()));
916         $n(table, 'ue_summary_primary_ident_type').appendChild(text(identt1));
917         $n(table, 'ue_summary_primary_ident').appendChild(text(patron.ident_value()));
918         $n(table, 'ue_summary_secondary_ident_type').appendChild(text(identt2));
919         $n(table, 'ue_summary_secondary_ident').appendChild(text(patron.ident_value2()));
920         $n(table, 'ue_summary_email').appendChild(text(patron.email()));
921         $n(table, 'ue_summary_dayphone').appendChild(text(patron.day_phone()));
922         $n(table, 'ue_summary_nightphone').appendChild(text(patron.evening_phone()));
923         $n(table, 'ue_summary_otherphone').appendChild(text(patron.other_phone()));
924         $n(table, 'ue_summary_home_lib').appendChild(text(homeorg));
925         $n(table, 'ue_summary_profile').appendChild(text(profile));
926         $n(table, 'ue_summary_expire').appendChild(text(patron.expire_date()));
927         $n(table, 'ue_summary_family_lead').appendChild(text( (patron.master_account()) ? yes : no ));
928         $n(table, 'ue_summary_claims_returned').appendChild(text(patron.claims_returned_count()));
929         $n(table, 'ue_summary_alert_message').appendChild(text(patron.alert_message()));
930
931         uEditFleshSummaryAddresses( table, patron );
932         uEditFleshSummaryStatCats( table, patron );
933         uEditFleshSummarySurveys( table, patron );
934         uEditFleshSummaryErrors( table );
935
936
937 }
938
939 function uEditFleshSummaryAddresses( table, patron ) {
940
941         var addrtbody = $n(table, 'ue_summary_addr_tbody');
942         var rowtmpl = addrtbody.removeChild($n(addrtbody, 'ue_summary_addr_row'));
943
944         for( var a in patron.addresses() ) {
945                 var address = patron.addresses()[a];
946                 var row = rowtmpl.cloneNode(true);
947                 uEditFleshSummaryAddr( address, patron, row );
948                 addrtbody.appendChild(row);
949                 if(address.isdeleted()) addCSSClass(row, 'deleted');
950         }
951 }
952
953
954 function uEditFleshSummaryAddr( address, patron, row ) {
955         var yes = $('yes').innerHTML;
956         var no = $('no').innerHTML;
957
958         $n(row, 'label').appendChild(text(address.address_type()));
959         $n(row, 'street1').appendChild(text(address.street1()));
960         $n(row, 'street2').appendChild(text(address.street2()));
961         $n(row, 'city').appendChild(text(address.city()));
962         $n(row, 'county').appendChild(text(address.county()));
963         $n(row, 'state').appendChild(text(address.state()));
964         $n(row, 'country').appendChild(text(address.country()));
965         $n(row, 'zip').appendChild(text(address.post_code()));
966         $n(row, 'valid').appendChild(text( (address.valid()) ? yes : no ));
967
968         $n(row, 'mailing').appendChild(text( 
969                 (patron.mailing_address() == address.id()) ? yes : no ));
970
971         $n(row, 'billing').appendChild(text( 
972                 (patron.billing_address() == address.id()) ? yes : no ));
973 }
974
975
976 function uEditFleshSummaryStatCats( table, patron ) {
977         var tbody = $n(table, 'ue_summary_stats_tbody');
978         var rowtmpl = tbody.removeChild($n(tbody, 'ue_summary_stats_row'));
979
980         for( var s in patron.stat_cat_entries() ) {
981                 row = rowtmpl.cloneNode(true);
982                 var entry = patron.stat_cat_entries()[s];
983                 var cat = cachedStatCats[entry.stat_cat()];
984                 $n(row, 'ue_summary_stat_name').appendChild(text(cat.name()));
985                 $n(row, 'ue_summary_stat_value').appendChild(text(entry.stat_cat_entry()));
986                 row.setAttribute('statcat', entry.stat_cat());
987                 if( entry.isdeleted() ) addCSSClass(row, 'deleted'); 
988                 tbody.appendChild(row);
989         }
990
991         for( var s in uEditExistingStatEntries ) {
992
993                 var entry = uEditExistingStatEntries[s]; 
994                 var rows = getElementsByTagNameFlat( tbody, 'tr' );
995                 var test = function(a) { return a.getAttribute('statcat') == entry.stat_cat() };
996
997                 if( ! grep( rows, test ) ) {
998
999                         row = rowtmpl.cloneNode(true);
1000                         var cat = cachedStatCats[entry.stat_cat()];
1001                         $n(row, 'ue_summary_stat_name').appendChild(text(cat.name()));
1002                         $n(row, 'ue_summary_stat_value').appendChild(text(entry.stat_cat_entry()));
1003                         row.setAttribute('statcat', entry.stat_cat());
1004                         tbody.appendChild(row);
1005                 }
1006         }
1007
1008
1009         if( ! getElementsByTagNameFlat( tbody, 'tr' )[1] )
1010                 unHideMe($n(tbody, 'ue_summary_stat_cat_none'));
1011 }
1012
1013
1014 function uEditFleshSummarySurveys( table, patron ) {
1015
1016         var tbody       = $n(table, 'ue_summary_survey_tbody');
1017         var rowtmpl = tbody.removeChild($n(tbody, 'ue_summary_survey_row'));
1018
1019         for( var r in patron.survey_responses() ) {
1020                 var row         = rowtmpl.cloneNode(rowtmpl);
1021                 var resp                = patron.survey_responses()[r];
1022                 var survey      = cachedSurveys[resp.survey()];
1023                 var quest       = cachedSurveyQuestions[resp.question()];
1024                 var answer      = cachedSurveyAnswers[resp.answer()];
1025                 $n(row, 'ue_summary_survey_name').appendChild(text(survey.name()));
1026                 $n(row, 'ue_summary_survey_question').appendChild(text(quest.question()));
1027                 $n(row, 'ue_summary_survey_answer').appendChild(text(answer.answer()));
1028                 tbody.appendChild(row);
1029         }
1030
1031         if( ! getElementsByTagNameFlat(tbody, 'tr')[1])
1032                 unHideMe($n(tbody, 'ue_summary_survey_none'))
1033 }
1034
1035
1036 function uEditFleshSummaryErrors( table ) {
1037         if(ERRORS) {
1038                 unHideMe($n(table, 'ue_summary_errors_row'));
1039                 var errors = ERRORS.replace(/\n/g, "<br/>");
1040                 $n(table, 'ue_summary_errors').innerHTML += errors;
1041         }
1042 }