1 /* -----------------------------------------------------------------------
2 ----------------------------------------------------------------------- */
3 const SC_FETCH_ALL = 'open-ils.circ:open-ils.circ.stat_cat.actor.retrieve.all';
4 const SC_CREATE_MAP = 'open-ils.circ:open-ils.circ.stat_cat.actor.user_map.create';
5 const SV_FETCH_ALL = 'open-ils.circ:open-ils.circ.survey.retrieve.all';
6 const FETCH_ID_TYPES = 'open-ils.actor:open-ils.actor.user.ident_types.retrieve';
7 const FETCH_GROUPS = 'open-ils.actor:open-ils.actor.groups.tree.retrieve';
8 const UPDATE_PATRON = 'open-ils.actor:open-ils.actor.patron.update';
9 const PATRON_SEARCH = 'open-ils.actor:open-ils.actor.patron.search.advanced';
10 const ZIP_SEARCH = 'open-ils.search:open-ils.search.zip';
11 const FETCH_ADDR_MEMS = 'open-ils.actor:open-ils.actor.address.members';
12 const FETCH_GRP_MEMS = 'open-ils.actor:open-ils.actor.usergroup.members.retrieve';
13 const defaultState = 'GA';
14 const defaultCountry = 'USA';
15 const CSS_INVALID_DATA = 'invalid_value';
17 /* if they don't have these perms, they shouldn't be here */
18 var myPerms = [ 'CREATE_USER', 'UPDATE_USER', 'CREATE_PATRON_STAT_CAT_ENTRY_MAP' ];
21 const numRegex = /^\d+$/;
22 const wordRegex = /^\w+$/;
23 const ssnRegex = /^\d{3}-\d{2}-\d{4}$/;
24 const dlRegex = /^[a-zA-Z]{2}-\w+/; /* driver's license */
25 const phoneRegex = /\d{3}-\d{3}-\d{4}/;
26 const nonumRegex = /^[a-zA-Z]\D*$/; /* no numbers, no beginning whitespace */
27 const dateRegex = /^\d{4}-\d{2}-\d{2}/;
31 function uEditDefineData(patron) {
36 object : patron.card(),
38 errkey : 'ue_bad_barcode',
49 errkey : 'ue_bad_username',
57 required : (patron.isnew()) ? true : false,
60 errkey : 'ue_bad_password',
64 onpostchange : function(field, newval) {
65 var pw2 = uEditFindFieldByWId('ue_password2');
66 /* tell the second passsword input to re-validate */
67 pw2.widget.node.onchange();
73 required : (patron.isnew()) ? true : false,
76 errkey : 'ue_bad_password',
80 onpostchange : function(field, newval) {
81 var pw1f = uEditFindFieldByWId('ue_password1');
82 var pw1 = uEditNodeVal(pw1f);
84 removeCSSClass(field.widget.node, CSS_INVALID_DATA);
86 addCSSClass(field.widget.node, CSS_INVALID_DATA);
93 key : 'first_given_name',
94 errkey : 'ue_bad_firstname',
99 onblur : function(field) {
100 uEditCheckNamesDup('first', field );
108 key : 'second_given_name',
109 errkey : 'ue_bad_middlename',
111 id : 'ue_middlename',
120 errkey : 'ue_bad_lastname',
125 onblur : function(field) {
126 uEditCheckNamesDup('last', field );
137 onload : function(val) {
138 setSelector($('ue_suffix_selector'), val);
146 errkey : 'ue_bad_dob',
157 errkey : 'ue_no_ident',
159 id : 'ue_primary_ident_type',
162 onpostchange : function(field, newval)
163 { _uEditIdentPostchange('primary', field, newval); }
171 id : 'ue_primary_ident',
173 onblur : function(field) {
174 uEditCheckIdentDup(field);
183 id : 'ue_secondary_ident_type',
186 onpostchange : function(field, newval)
187 { _uEditIdentPostchange('secondary', field, newval); }
193 key : 'ident_value2',
195 id : 'ue_secondary_ident',
197 onblur : function(field) {
198 uEditCheckIdentDup(field);
206 errkey : 'ue_bad_email',
210 regex : /.+\@.+\..+/, /* make me better */
211 onblur : function(field) {
212 var val = uEditNodeVal(field);
213 if( val && val != field.oldemail ) {
214 uEditRunDupeSearch('email',
215 { email : { value : val, group : 0 } });
216 field.oldemail = val;
225 errkey : 'ue_bad_phone',
235 key : 'evening_phone',
236 errkey : 'ue_bad_phone',
238 id : 'ue_night_phone',
247 errkey : 'ue_bad_phone',
249 id : 'ue_other_phone',
259 id : 'ue_org_selector',
268 errkey : 'ue_bad_expire',
297 errkey : 'ue_no_profile',
302 onpostchange : function(field, value) {
303 var type = groupsCache[value];
304 var interval = type.perm_interval();
305 var intsecs = parseInt(util.date.interval_to_seconds(interval));
307 var expdate = new Date();
308 var exptime = expdate.getTime();
309 exptime += intsecs * 1000;
310 expdate.setTime(exptime);
312 var year = expdate.getYear() + 1900;
313 var month = (expdate.getMonth() + 1) + '';
314 var day = (expdate.getDate() + 1) + '';
316 if(!month.match(/\d{2}/)) month = '0' + month;
317 if(!day.match(/\d{2}/)) day = '0' + day;
319 var node = $('ue_expire');
320 node.value = year+'-'+month+'-'+day;
327 key : 'master_account',
329 id : 'ue_group_lead',
336 key : 'claims_returned_count',
338 id : 'ue_claims_returned',
346 key : 'alert_message',
348 id : 'ue_alert_message',
354 for( var f in fields )
355 dataFields.push(fields[f]);
357 uEditBuildAddrs(patron);
358 uEditBuildPatronSCM(patron);
361 var uEditOldFirstName;
362 var uEditOldMiddleName; /* future */
363 var uEditOldLastName;
364 function uEditCheckNamesDup(type, field) {
365 var newval = uEditNodeVal(field);
368 var dosearch = false;
371 if( newval != uEditOldFirstName )
373 uEditOldFirstName = newval;
377 if( newval != uEditOldLastName )
379 uEditOldLastName = newval;
382 if( dosearch && uEditOldFirstName && uEditOldLastName ) {
383 var search_hash = {};
384 search_hash['first_given_name'] = { value : uEditOldFirstName, group : 0 };
385 search_hash['family_name'] = { value : uEditOldLastName, group : 0 };
386 uEditRunDupeSearch('names', search_hash);
390 var uEditOldIdentValue;
391 function uEditCheckIdentDup(field) {
392 var newval = uEditNodeVal(field);
393 if( newval && newval != uEditOldIdentValue ) {
394 /* searches all ident_value fields */
395 var search_hash = { ident : { value : newval, group : 2 } };
396 uEditRunDupeSearch('ident', search_hash);
397 uEditOldIdentValue = newval;
402 /* Adds all of the addresses attached to the patron object
403 to the fields array */
404 var uEditAddrTemplate;
405 function uEditBuildAddrs(patron) {
406 var tbody = $('ue_address_tbody');
409 tbody.removeChild($('ue_address_template'));
411 for( var a in patron.addresses() ) {
412 if(!uEditAddrTemplate)
413 uEditAddrTemplate = tbody.removeChild($('ue_address_template'));
414 uEditBuildAddrFields( patron, patron.addresses()[a]);
419 function uEditDeleteAddr( tbody, row, address, detach ) {
420 if(!confirm($('ue_delete_addr_warn').innerHTML)) return;
421 if(address.isnew()) {
423 grep( patron.addresses(),
425 return (i.id() != address.id());
430 if(!detach) address.isdeleted(1);
432 tbody.removeChild(row);
434 var bid = patron.billing_address();
435 bid = (typeof bid == 'object') ? bid.id() : bid;
437 var mid = patron.mailing_address();
438 mid = (typeof mid == 'object') ? mid.id() : mid;
441 /* -----------------------------------------------------------------------
442 if we're deleting a billing or mailing address
443 make sure some other address is automatically
444 assigned as the billing or mailng address
445 ----------------------------------------------------------------------- */
447 if( bid == address.id() ) {
448 for( var a in patron.addresses() ) {
449 var addr = patron.addresses()[a];
450 if(!addr.isdeleted() && addr.id() != address.id()) {
451 var node = uEditFindAddrInput('billing', addr.id());
453 uEditAddrTypeClick(node, 'billing');
459 if( mid == address.id() ) {
460 for( var a in patron.addresses() ) {
461 var addr = patron.addresses()[a];
462 if(!addr.isdeleted() && addr.id() != address.id()) {
463 var node = uEditFindAddrInput('mailing', addr.id());
465 uEditAddrTypeClick(node, 'mailing');
473 function uEditFindAddrInput(type, id) {
474 var tbody = $('ue_address_tbody');
475 var rows = tbody.getElementsByTagName('tr');
476 for( var r in rows ) {
478 if(row.parentNode != tbody) continue;
479 var node = $n(row, 'ue_addr_'+type+'_yes');
480 if( node.getAttribute('address') == id )
486 function uEditAddrTypeClick(input, type) {
487 var tbody = $('ue_address_tbody');
488 var rows = tbody.getElementsByTagName('tr');
489 for( var r in rows ) {
491 if(row.parentNode != tbody) continue;
492 var node = $n(row, 'ue_addr_'+type+'_yes');
493 removeCSSClass(node.parentNode,'addr_info_checked');
496 addCSSClass(input.parentNode,'addr_info_checked');
497 patron[type+'_address'](input.getAttribute('address'));
504 /* Creates the field entries for an address object. */
505 function uEditBuildAddrFields(patron, address) {
507 var tbody = $('ue_address_tbody');
511 var row = tbody.appendChild(
512 uEditAddrTemplate.cloneNode(true));
514 uEditCheckSharedAddr(patron, address, tbody, row);
516 $n(row, 'ue_addr_delete').onclick =
517 function() { uEditDeleteAddr(tbody, row, address); }
519 if( address.id() == patron.billing_address().id() )
520 $n(row, 'ue_addr_billing_yes').checked = true;
522 if( address.id() == patron.mailing_address().id() )
523 $n(row, 'ue_addr_mailing_yes').checked = true;
525 $n(row, 'ue_addr_billing_yes').setAttribute('address', address.id());
526 $n(row, 'ue_addr_mailing_yes').setAttribute('address', address.id());
532 key : 'address_type',
535 name : 'ue_addr_label',
543 errkey : 'ue_bad_addr_street',
546 name : 'ue_addr_street1',
554 errkey : 'ue_bad_addr_street',
557 name : 'ue_addr_street2',
565 errkey : 'ue_bad_addr_city',
568 name : 'ue_addr_city',
578 name : 'ue_addr_county',
586 errkey : 'ue_bad_addr_state',
589 name : 'ue_addr_state',
597 errkey : 'ue_bad_addr_country',
600 name : 'ue_addr_country',
608 errkey : 'ue_bad_addr_zip',
611 name : 'ue_addr_zip',
614 onblur : function(f) {
615 var v = uEditNodeVal(f);
616 var req = new Request(ZIP_SEARCH, v);
619 var info = r.getResultObject();
621 var state = $n(f.widget.base, 'ue_addr_state');
622 var county = $n(f.widget.base, 'ue_addr_county');
623 var city = $n(f.widget.base, 'ue_addr_city');
624 if(!state.value) state.value = info.state;
625 if(!county.value) county.value = info.county;
626 if(!city.value) city.value = info.city;
636 key : 'within_city_limits',
639 name : 'ue_addr_inc_yes',
649 name : 'ue_addr_valid_yes',
655 for( var f in fields ) {
656 dataFields.push(fields[f]);
657 uEditActivateField(fields[f]);
661 function uEditBuildPatronSCM(patron) {
662 /* get the list of pre-defined maps */
663 var fields = uEditFindFieldsByKey('stat_cat_entry');
667 /* for each user stat cat, pop it off the list,
668 updated the existing stat map field to match
669 the popped map and shove the existing stat
670 map field onto the user's list of stat maps */
671 while( (map = patron.stat_cat_entries().pop()) ) {
673 var field = grep(fields,
675 return (item.object.stat_cat() == map.stat_cat());
680 var val = map.stat_cat_entry();
682 $n(field.widget.base, field.widget.name).value = val;
683 setSelector($n(field.widget.base, 'ue_stat_cat_selector'), val );
684 field.object.stat_cat_entry(val);
685 field.object.id(map.id());
686 newmaps.push(field.object);
690 for( var m in newmaps )
691 patron.stat_cat_entries().push(newmaps[m]);
695 function uEditBuildSCMField(statcat, row) {
697 var map = new actscecm();
698 map.stat_cat(statcat.id());
699 map.target_usr(patron.id());
704 key : 'stat_cat_entry',
707 name : 'ue_stat_cat_newval',
710 onpostchange : function( field, newval ) {
712 /* see if the current map already resides in
713 the patron entry list */
714 var exists = grep( patron.stat_cat_entries(),
716 return (item.stat_cat() == statcat.id());
722 setSelector($n(row, 'ue_stat_cat_selector'), newval);
728 /* if the map is new but currently contains no value
729 remove it from the set of new maps */
731 patron.stat_cat_entries(
732 grep( patron.stat_cat_entries(),
734 return (item.stat_cat() != map.stat_cat());
747 /* map does not exist in the map array but now has data */
750 patron.stat_cat_entries().push(map);
757 dataFields.push(field);
762 /** Run this after a new ident type is selected */
763 function _uEditIdentPostchange(type, field, newval) {
767 /* When the ident type is changed, we change the
768 regex on the ident_value to match the selected type */
769 var vfname = 'ident_value';
770 if(type == 'secondary') vfname = 'ident_value2';
771 var vfield = uEditFindFieldByKey(vfname);
772 var name = identTypesCache[uEditNodeVal(field)].name();
774 hideMe($(type+'_ident_ssn_help'));
775 hideMe($(type+'_ident_dl_help'));
777 if(name.match(/ssn/i)) {
778 vfield.widget.regex = ssnRegex;
779 vfield.errkey = 'ue_bad_ident_ssn';
780 unHideMe($(type+'_ident_ssn_help'));
784 if(name.match(/driver/i)) {
785 vfield.widget.regex = dlRegex;
786 vfield.errkey = 'ue_bad_ident_dl';
787 unHideMe($(type+'_ident_dl_help'));
788 if(!uEditNodeVal(vfield))
789 vfield.widget.node.value = defaultState + '-';
792 vfield.widget.regex = null;
793 vfield.errkey = null;
797 /* focus then valdate the value field */
798 vfield.widget.node.onchange();
799 vfield.widget.node.focus();
803 /* checks to see if the given address is shared by others.
804 * if so, the address row is styled and ...
806 function uEditCheckSharedAddr(patron, address, tbody, row) {
807 var req = new Request(FETCH_ADDR_MEMS, SESSION, address.id());
810 var members = r.getResultObject();
811 for( var m in members ) {
814 if( id != patron.id() ) {
816 addCSSClass(row, 'shared_address');
817 unHideMe($n(row, 'shared_row'));
818 $n(row, 'ue_addr_delete').disabled = true;
820 if( address.usr() != patron.id() ) {
821 var button = $n(row, 'ue_addr_detach');
824 function() { uEditDeleteAddr( tbody, row, address, true ); }