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