removed some more field requirements and fixed a bug with the ident_type2
[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 /* if they don't have these perms, they shouldn't be here */
23 //var myPerms = [ 'CREATE_USER', 'UPDATE_USER', 'CREATE_PATRON_STAT_CAT_ENTRY_MAP' ];
24
25 var pages               = [ 
26         'uedit_userid', 
27         'uedit_contact_info', 
28         'uedit_addresses', 
29         'uedit_groups', 
30         'uedit_stat_cats', 
31         'uedit_surveys',
32         'uedit_finalize',
33         ];
34
35 /* ID's of objects that should be focused when their page is made visible */
36 var pageFocus   = [
37         'ue_barcode',
38         'ue_email1',
39         'ue_addr_label_1',
40         'ue_profile',
41         'ue_stat_cat_selector_1',
42         'ue_survey_selector_1',
43         'ue_view_summary'
44 ];
45
46 var regexes             = {};
47 regexes.phone   = /\d{3}-\d{3}-\d{4}/;
48 regexes.email   = /.+\@.+\..+/;
49 regexes.date    = /^\d{4}-\d{2}-\d{2}/;
50 regexes.isnum   = /^\d+$/;
51
52 /* fetch the necessary data to start off */
53 function uEditInit() {
54
55         cgi             = new CGI();
56         session = cgi.param('ses');
57         if(cgi.param('adv')) advanced = true 
58         if(!session) throw "User session is not defined";
59
60         fetchUser(session);
61         $('uedit_user').appendChild(text(USER.usrname()));
62         uEditShowPage('uedit_userid');
63
64         setTimeout( 
65                 function() { 
66
67                         /* these can be asynch */
68                         /*fetchHighestPermOrgs( SESSION, USER.id(), myPerms );*/
69                         uEditFetchSurveys();
70
71                         /* these have to be synchronous */
72                         uEditBuildLibSelector();
73                         uEditFetchIDTypes();
74                         uEditBuildAddrs();
75                         uEditFetchGroups();
76                         uEditFetchStatCats();
77
78                         uEditDrawUser(fetchFleshedUser(cgi.param('usr')));
79
80                 }, 20 
81         );
82 }
83
84 /* UI code ---------------------------------------------------- */
85
86 function uEditNext() {
87         var i = _findActive();
88         if( i < (pages.length - 1)) uEditShowPage(pages[i+1]);
89 }
90
91 function uEditPrev() {
92         var i = _findActive();
93         if( i > 0 ) uEditShowPage(pages[i-1]);
94 }
95
96 function uEditFetchError(id) { if($(id)) return $(id).innerHTML + "\n"; return "";}
97
98 function uEditShowPage(id) {
99         if( id == null ) return;
100
101         for( var p in pages ) {
102                 var page = pages[p];
103                 hideMe($(page));
104                 removeCSSClass($(page+'_label'), 'label_active');
105         }
106
107         unHideMe($(id));
108         addCSSClass($(id+'_label'), 'label_active');
109         var idx = _findPageIdx(id);
110         var fpage = pageFocus[idx];
111         if(fpage) { $(fpage).focus(); try{$(fpage).select()}catch(e){} }
112
113         unHideMe($('ue_back'));
114         unHideMe($('ue_fwd'));
115
116         if(idx == 0) hideMe($('ue_back'));
117         if(idx == (pages.length-1)) hideMe($('ue_fwd'));
118 }
119
120
121 function _findActive() {
122         for( var p in pages ) {
123                 if(! $(pages[p]).className.match(/hide_me/) )
124                         return parseInt(p);
125         }
126         return null;
127 }
128 function _findPageIdx(name) {
129         for( var i in pages ) {
130                 var page = pages[i];
131                 if( page == name ) return i;
132         }
133         return -1;
134 }
135
136 function uEditAddrHighlight( node, type ) {
137         var tbody = $('ue_address_tbody');
138         for( var c in tbody.childNodes ) {
139                 var row = tbody.childNodes[c];
140                 if(row.nodeType != XML_ELEMENT_NODE ) continue;
141                 var div = $n(row,'ue_addr_'+type+'_yes').parentNode;
142                 removeCSSClass(div, 'addr_info_checked');
143         }
144         addCSSClass(node.parentNode, 'addr_info_checked');
145 }
146
147
148 /* ------------------------------------------------------------------------------ */
149 /* Fetch code
150 /* ------------------------------------------------------------------------------ */
151 function uEditFetchIDTypes() {
152         var req = new Request(FETCH_ID_TYPES);
153         //req.callback(uEditDrawIDTypes);
154         req.send(true);
155         uEditDrawIDTypes(req.request);
156 }
157
158 function uEditFetchStatCats() {
159         var req = new Request(SC_FETCH_ALL, SESSION);
160         //req.callback(uEditDrawStatCats);
161         req.send(true);
162         uEditDrawStatCats(req.request);
163 }
164
165 function uEditFetchSurveys() {
166         var req = new Request(SV_FETCH_ALL, SESSION);
167         req.callback(uEditDrawSurveys);
168         req.send();
169 }
170
171
172 /* ------------------------------------------------------------------------------ */
173 /* Save the user
174 /* ------------------------------------------------------------------------------ */
175 var uEditExistingStatEntries;
176 var uEditExistingSurveyResponses;
177
178 function uEditSaveUser() {
179         uEditCollectData();
180
181         if(ERRORS) { 
182                 alert(ERRORS); 
183                 ERRORS = ""; 
184                 return;
185         }
186
187         //alert(js2JSON(patron));
188         //return;
189
190         var req = new Request(UPDATE_PATRON, SESSION, patron);
191         req.send(true);
192         var result = req.result();
193         if( checkILSEvent(result) ) alert(js2JSON(result));
194         else alert($('ue_success').innerHTML);
195
196 }
197
198 function uEditCollectData() {
199
200         var card        = null;
201
202         if(patron == null) { 
203                 patron = new au(); 
204                 patron.isnew(1);
205                 patron.id(-1);
206                 card = new ac();
207                 patron.card(-1); /* attach to the virtual id of the card */
208                 patron.cards([card]);
209
210         } else { 
211
212                 /* if this function is called again, patron will exist */
213                 if(!patron.isnew()) { 
214                         patron.ischanged(1); 
215                         patron.isnew(0);
216                         if(!uEditExistingStatEntries)
217                                 uEditExistingStatEntries = patron.stat_cat_entries();
218                         if(!uEditExistingSurveyResponses)
219                                 uEditExistingSurveyResponses = patron.survey_responses();
220                 }
221         }
222
223         patron.stat_cat_entries([]);
224         patron.survey_responses([]);
225
226         uEditFleshCard(card);
227         uEditAddBasicPatronInfo(patron);
228         uEditAddPhones(patron);
229         uEditAddIdents(patron);
230         uEditAddAddresses(patron);
231         uEditAddGroupsAndPerms(patron);
232         uEditReapStatCats(patron);
233         uEditReapSurveys(patron);
234
235 }
236
237
238
239 /* ------------------------------------------------------------------------------ */
240 /* Draw the user
241 /* ------------------------------------------------------------------------------ */
242 function uEditDrawUser(p) {
243
244         hideMe($('uedit_loading'));
245         unHideMe($('ue_maintd'));
246
247         if(!p) return;
248         patron = p;
249
250         $('ue_barcode').value                   = patron.card().barcode();
251         $('ue_username').value                  = patron.usrname();
252         $('ue_firstname').value                 = patron.first_given_name();
253         $('ue_middlename').value                = patron.second_given_name();
254         $('ue_lastname').value                  = patron.family_name();
255         $('ue_suffix').value                            = patron.suffix();
256         $('ue_dob').value                                       = patron.dob();
257         $('ue_primary_ident').value     = patron.ident_value();
258         $('ue_secondary_ident').value   = patron.ident_value2();
259         $('ue_email1').value                            = patron.email();
260         $('ue_email2').value                            = patron.email();
261         $('ue_expire').value                            = patron.expire_date();
262         $('ue_active').value                            = patron.active();
263         $('ue_barred').value                            = patron.barred();
264         $('ue_claims_returned').value   = patron.claims_returned_count();
265         $('ue_alert_message').value     = patron.alert_message();
266
267         setSelector( $('ue_primary_ident_type'), patron.ident_type() );
268         setSelector( $('ue_secondary_ident_type'), patron.ident_type2() );
269         setSelector( $('ue_org_selector'), patron.home_ou() );
270         setSelector( $('ue_profile'), patron.profile() );
271         
272         /* flesh out the phone numbers ------------------------- */
273         var dp = patron.day_phone();
274         var np = patron.evening_phone();
275         var op = patron.other_phone();
276
277         if(dp) {
278                 var daynums = dp.split('-');
279                 $('ue_day_phone_area').value            = daynums[0];
280                 $('ue_day_phone_prefix').value  = daynums[1];
281                 $('ue_day_phone_suffix').value  = daynums[2];
282         }
283
284         if(np) {
285                 var nightnums = np.split('-');
286                 $('ue_night_phone_area').value  = nightnums[0];
287                 $('ue_night_phone_prefix').value        = nightnums[1];
288                 $('ue_night_phone_suffix').value        = nightnums[2];
289         }
290
291         if(op) {
292                 var othernums = op.split('-');
293                 $('ue_other_phone_area').value  = othernums[0];
294                 $('ue_other_phone_prefix').value        = othernums[1];
295                 $('ue_other_phone_suffix').value        = othernums[2];
296         }
297
298
299         /* Flesh the addresses ------------------------------------ */
300         var i = 0;
301         var tbody = $('ue_address_tbody');      
302         for( var i = 0; i != patron.addresses().length; i++ ) {
303                 var addr = patron.addresses()[i];
304                 cachedAddresses[addr.id()] = addr;
305                 var row;
306                 if( i == 0 ) row = getElementsByTagNameFlat(tbody, 'tr')[0];
307                 else row = $('ue_address_new').onclick(); /* create a new row if necessary */
308
309                 row.setAttribute('exists', addr.id() );
310
311                 if( patron.mailing_address().id() == addr.id())
312                         $n(row, 'ue_addr_mailing_yes').checked = true;
313
314                 if( patron.billing_address().id() == addr.id())
315                         $n(row, 'ue_addr_billing_yes').checked = true;
316                 
317                 if( addr.valid() ) $n(row, 'ue_addr_valid_yes').checked = true;
318
319         
320                 $n(row, 'ue_addr_label').value  = addr.address_type();
321                 $n(row, 'ue_addr_street1').value        = addr.street1();
322                 $n(row, 'ue_addr_street2').value = addr.street2();
323                 $n(row, 'ue_addr_city').value           = addr.city();
324                 $n(row, 'ue_addr_county').value = addr.county();
325                 $n(row, 'ue_addr_state').value  = addr.state();
326                 $n(row, 'ue_addr_zip').value            = addr.post_code();
327                 $n(row, 'ue_addr_country').value        = addr.country();
328
329         }
330
331
332
333         var stattbody = $('ue_stat_cat_tbody');
334         for( var m in patron.stat_cat_entries() ) {
335                 var map = patron.stat_cat_entries()[m];
336                 var row = grep( getElementsByTagNameFlat( stattbody, 'tr' ), 
337                         function(a) { return a.getAttribute('statcat') == map.stat_cat() })[0];
338                 $n(row, 'ue_stat_cat_newval').value = map.stat_cat_entry();
339                 setSelectorByName( $n(row, 'ue_stat_cat_selector'), map.stat_cat_entry() );
340         }
341 }
342
343
344
345
346
347 /* ------------------------------------------------------------------------------ */
348 /* Draw the ID types
349 /* ------------------------------------------------------------------------------ */
350 function uEditDrawIDTypes(r) {
351
352         var types       = r.getResultObject();
353         var pri_sel = $('ue_primary_ident_type');
354         var sec_sel = $('ue_secondary_ident_type');
355
356         var idx = 1;
357         for( var t in types ) {
358                 var type = types[t];
359                 identTypes[type.id()] = type;
360                 setSelectorVal( pri_sel, idx, type.name(), type.id() );
361
362                 if(patron && patron.ident_type() != null ) 
363                         setSelector( pri_sel, patron.ident_type() );
364
365                 setSelectorVal( sec_sel, idx++, type.name(), type.id() );
366                 if(patron && patron.ident_type2() != null ) 
367                         setSelector( sec_sel, patron.ident_type2() );
368         }
369 }
370
371
372
373 /* ------------------------------------------------------------------------------ */
374 /* Stat Cat handling code
375 /* ------------------------------------------------------------------------------ */
376 function uEditDrawStatCats(r) {
377         var cats = r.getResultObject();
378         var tbody = $('ue_stat_cat_tbody');
379         var templ = tbody.removeChild($('ue_stat_cat_row'));
380
381         for( var c in cats ) {
382                 var row = templ.cloneNode(true);
383                 uEditInsertCat( tbody, row, cats[c], c );
384                 tbody.appendChild(row);
385         }
386 }
387
388 /* fleshes the stat cat with entries in the dropdown */
389 function uEditInsertCat( tbody, row, cat, idx ) {
390
391         cat.entries().sort(  /* sort the entries by value */
392                 function( a, b ) { 
393                         if( a.value().toLowerCase() > b.value().toLowerCase()) return 1;
394                         if( a.value().toLowerCase() < b.value().toLowerCase()) return -1;
395                         return 0;
396                 }
397         );
398
399         cachedStatCats[cat.id()] = cat;
400
401         row.setAttribute('statcat', cat.id());
402         var newval = $n(row, 'ue_stat_cat_newval');
403         newval.onchange = function(){ 
404                 findParentByNodeName(newval,'tr').setAttribute('changed', '1'); }
405
406         var selector = $n(row, 'ue_stat_cat_selector');
407         selector.onchange = function(){ 
408                 findParentByNodeName(selector, 'tr').setAttribute('changed', '1'); 
409                 newval.value = getSelectorName(selector);
410                 newval.setAttribute('entry', getSelectorVal(selector));
411         }
412
413         if( idx == 0 ) selector.id = 'ue_stat_cat_selector_1'; 
414
415         $n(row, 'ue_stat_cat_name').appendChild(text(cat.name()));
416         $n(row, 'ue_stat_cat_owner').appendChild(
417                 text(fetchOrgUnit(cat.owner()).shortname()));
418
419         var idx = 1;
420         for( var e in cat.entries() ) {
421                 var entry = cat.entries()[e];
422                 setSelectorVal( selector, idx++, entry.value(), entry.id() );
423         }
424 }
425
426 /* finds all the changed/new stat entries and updates the patron object*/
427 function uEditReapStatCats(patron) {
428    var tbody = $('ue_stat_cat_tbody');
429         for( var r in tbody.childNodes ) {
430                 var row = tbody.childNodes[r];
431                 if( !row || row.nodeName != 'tr' ) continue;
432                 if( row.getAttribute('changed') ) {
433                         var val = $n( row, 'ue_stat_cat_newval' );
434                         uEditCreateStatMap( patron, row.getAttribute('statcat'), 
435                                 val.value, val.getAttribute('entry') );
436                 }
437         }
438 }
439
440
441 function uEditCreateStatMap( patron, catid, newval, entryid ) {
442
443         if( ! patron.isnew() ) {
444
445                 /* if the patron exists and we're editing an entry that's 
446                 already been created for this user... */
447                 for( var m in uEditExistingStatEntries ) {
448                         var map = uEditExistingStatEntries[m];
449                         if( map.stat_cat() == catid ) {
450                                 if( newval ) map.ischanged(1);
451                                 else map.isdeleted(1); 
452                                 patron.stat_cat_entries().push(map);
453                                 return;
454                         }
455                 }
456         }
457
458         var map = new actscecm();
459         map.isnew(1);
460         map.stat_cat_entry(newval);
461         map.stat_cat(catid);
462         map.target_usr(patron.id());
463         patron.stat_cat_entries().push(map);
464 }
465
466
467
468 /* ------------------------------------------------------------------------------ */
469 /* Survey handling code
470 /* ------------------------------------------------------------------------------ */
471 function uEditDrawSurveys(r) {
472
473         var surveys = r.getResultObject();
474         var div = $('uedit_surveys');
475         var table = div.removeChild($('ue_survey_table'));
476
477         var x = 0;
478         for( var s in surveys ) {
479                 var survey = surveys[s];
480                 cachedSurveys[survey.id()] = survey;
481                 var clone = table.cloneNode(true);
482                 uEditInsertSurvey( div, clone, survey, x++ );
483                 div.appendChild(clone);
484         }
485 }
486
487 function uEditInsertSurvey( div, table, survey, sidx ) {
488         $n(table, 'ue_survey_name').appendChild(text(survey.name()));
489         $n(table, 'ue_survey_desc').appendChild(text(survey.description()));
490         var tbody = $n(table, 'ue_survey_tbody');
491         var templ = tbody.removeChild($n(table, 'ue_survey_row'));
492
493         var polldiv             = $('ue_survey_answer_poll');
494
495         var idx = 1;
496         for( var q in survey.questions() ) {
497                 var row = templ.cloneNode(true);
498                 var quest = survey.questions()[q];
499                 cachedSurveyQuestions[quest.id()] = quest;
500                 uEditInsertSurveyQuestion( div, table, tbody, row, survey, quest, sidx );
501                 tbody.appendChild(row);
502         }
503 }
504
505 function uEditInsertSurveyQuestion( div, table, tbody, row, survey, question, sidx ) {
506
507         $n(row, 'ue_survey_question').appendChild(text(question.question()));
508
509         var selector    = $n(row, 'ue_survey_answer');
510         var polldiv             = $n(row, 'ue_survey_answer_poll');
511         var idx                 = 1;
512         var polltbody   = $n(row, 'ue_survey_answer_poll_tbody');
513         var pollrow             = polltbody.removeChild($n(polltbody, 'ue_survey_answer_poll_row'));
514
515         table.setAttribute('survey', survey.id());
516         row.setAttribute('question', question.id());
517
518         selector.onchange = function() {
519                 row.setAttribute('answer', getSelectorVal(selector));
520                 row.setAttribute('changed', '1');
521         }
522
523         if( sidx == 0 ) selector.id = 'ue_survey_selector_1'; 
524
525         for( var a in question.answers() ) {
526
527                 var answer = question.answers()[a];
528                 cachedSurveyAnswers[answer.id()] = answer;
529
530                 if( survey.poll() ) {
531
532                         unHideMe(polldiv);
533                         var prow = pollrow.cloneNode(true);
534
535
536                         $n(prow, 'ue_survey_answer_poll_answer').appendChild(text(answer.answer()));
537
538
539                         var input = elem('input', { 
540                                         type    : 'radio', 
541                                         name    : 'survey_poll_answer_'+survey.id(),
542                                         id              :  answer.id()
543                                 });
544
545                         input.onchange  = function() {
546                                 row.setAttribute('answer', answer.id());
547                                 row.setAttribute('changed', '1');
548                         }
549
550                         $n(prow, 'ue_survey_answer_poll_radio').appendChild(input);
551                         polltbody.appendChild(prow);
552
553                 } else {
554
555                         unHideMe(selector.parentNode);
556                         setSelectorVal( selector, idx++, answer.answer(), answer.id() );
557                 }
558         }
559 }
560
561
562 function uEditReapSurveys(patron) {
563
564         var div = $('uedit_surveys');
565         var tables = getElementsByTagNameFlat(div, 'table');
566
567         for( var t in tables ) {
568
569                 var table               = tables[t];
570                 var survey              = cachedSurveys[table.getAttribute('survey')];
571                 var tbody               = getElementsByTagNameFlat( table, 'tbody' )[0];
572                 var rows                        = getElementsByTagNameFlat( tbody, 'tr' );
573
574                 for( var r in rows ) {
575                         var row = rows[r];
576                         if(!row.getAttribute('changed')) continue;
577
578                         var resp        = new asvr();
579                         resp.isnew(1);
580                         resp.survey(survey.id());
581                         resp.usr(patron.id());
582                         resp.question(row.getAttribute('question'));
583                         resp.answer(row.getAttribute('answer'));
584                         patron.survey_responses().push( resp );
585                 }
586         }
587 }
588
589
590
591
592
593
594 /* returns true if an error occurred */
595 function uEditSetVal( obj, func, val, regxtype, errtype ) {
596
597         var error = uEditFetchError(errtype);
598         var iserr = false;
599
600         while(1) {
601
602                 if( val == null ) { iserr = true; break; }
603
604                 if(!instanceOf(val, String)) {
605                         try { val = val.value; } catch(e) { return; }
606                 }
607
608                 if(val == "" ) { iserr = true; break; }
609
610                 if(regxtype && regexes[regxtype] 
611                         && !val.match(regexes[regxtype]) ) { iserr = true; break; }
612
613                 try { obj[func](val); } catch(e) {
614                         alert("Error running function: " +func);
615                 }
616
617                 break;
618         }
619
620         if(iserr) { ERRORS += error; return true; }
621         return false;
622 }
623
624
625 function uEditAddBasicPatronInfo(patron) {
626
627
628
629         /* make sure passwords match */
630         var p1 = $('ue_password1').value;
631         var p2 = $('ue_password1').value;
632
633         if( p1 || patron.isnew() ) { /* existing patrons will have a blank password */
634                 if( p1 != p2 || uEditSetVal( patron, "passwd", p1 )) 
635                         ERRORS += uEditFetchError('ue_bad_password');
636         }
637         
638         uEditSetVal(patron, "usrname", $('ue_username'), null, 'ue_bad_username' );
639         uEditSetVal(patron, "first_given_name", $('ue_firstname'), null, 'ue_bad_firstname' );
640         //uEditSetVal(patron, "second_given_name", $('ue_middlename'), null, 'ue_bad_middlename' ); 
641         uEditSetVal(patron, "family_name", $('ue_lastname'), null, 'ue_bad_lastname' ); 
642         uEditSetVal(patron, "dob", $('ue_dob'), 'date', 'ue_bad_dob' );
643
644         patron.second_given_name($('ue_middlename').value);
645         patron.suffix($('ue_suffix').value); /* suffis isn't required */
646
647
648         /* make sure emails match */
649         /*
650         var email       = $('ue_email1').value;
651         var email2      = $('ue_email2').value;
652         if( email != email2 || uEditSetVal(patron, "email", email, 'email' ))
653                 ERRORS += uEditFetchError('ue_bad_email');
654                 */
655
656         patron.email($('ue_email1').value);
657         patron.home_ou(getSelectorVal($('ue_org_selector')));
658 }
659
660 function uEditAddPhones(patron) {
661
662         /* verifies the phone numbers are formatted correctly */
663         var verify = function(n1, n2, n3) {
664                 if(!(a || p||s) ) return null;
665                 var a = n1.value;
666                 var p = n2.value;
667                 var s = n3.value;
668                 if( !a || !p || !s ) return false;
669                 return a + '-' + p + '-' + s;
670         }
671
672         var er = 'ue_bad_phone'
673
674         var r1 = verify($('ue_day_phone_area'), $('ue_day_phone_prefix'),$('ue_day_phone_suffix'));
675         var r2 = verify($('ue_night_phone_area'), $('ue_night_phone_prefix'),$('ue_night_phone_suffix'));
676         var r3 = verify($('ue_other_phone_area'), $('ue_other_phone_prefix'),$('ue_other_phone_suffix'));
677
678         if(r1 != null) 
679                 uEditSetVal( patron, "day_phone", r1, 'phone', er);
680
681         if(r2 != null) 
682                 uEditSetVal( patron, "evening_phone", r2, 'phone', er);
683
684         if(r3 != null) 
685                 uEditSetVal( patron, "other_phone", r3, 'phone', er);
686 }
687
688 function uEditFleshCard(card) {
689         if(!card) return "";
690
691         if(uEditSetVal( card, "barcode", $('ue_barcode'), null, 'ue_bad_barcode' ))
692                 return; 
693
694         card.id(-1);
695         card.active(1);
696         card.isnew(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         uEditSetVal( patron, "ident_value", $('ue_primary_ident'), null, err );
707
708         var val = getSelectorVal($('ue_secondary_ident_type'));
709         if( val && val.match(/^\d+$/) ) {
710                 patron.ident_type2(getSelectorVal($('ue_secondary_ident_type')));
711                 patron.ident_value2($('ue_secondary_ident').value);
712         } else {
713                 patron.ident_type2(null);
714                 patron.ident_value2(null);
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( identt1 = identTypes[patron.ident_type()]) 
901                 identt1 = identt1.name();
902         if( identt2 = identTypes[patron.ident_type2()] ) 
903                 identt2 = identt2.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 }