1 /* -----------------------------------------------------------------------
2 ----------------------------------------------------------------------- */
3 var SC_FETCH_ALL = 'open-ils.circ:open-ils.circ.stat_cat.actor.retrieve.all';
4 var SC_CREATE_MAP = 'open-ils.circ:open-ils.circ.stat_cat.actor.user_map.create';
5 var SV_FETCH_ALL = 'open-ils.circ:open-ils.circ.survey.retrieve.all';
6 var FETCH_ID_TYPES = 'open-ils.actor:open-ils.actor.user.ident_types.retrieve';
7 var FETCH_GROUPS = 'open-ils.actor:open-ils.actor.groups.tree.retrieve';
8 var UPDATE_PATRON = 'open-ils.actor:open-ils.actor.patron.update';
9 var PATRON_SEARCH = 'open-ils.actor:open-ils.actor.patron.search.advanced';
10 var ZIP_SEARCH = 'open-ils.search:open-ils.search.zip';
11 var defaultState = 'GA';
12 var defaultCountry = 'USA';
13 var CSS_INVALID_DATA = 'invalid_value';
15 /* if they don't have these perms, they shouldn't be here */
16 var myPerms = [ 'CREATE_USER', 'UPDATE_USER', 'CREATE_PATRON_STAT_CAT_ENTRY_MAP' ];
19 var numRegex = /^\d+$/;
20 var wordRegex = /^\w+$/;
21 var ssnRegex = /^\d{3}-\d{2}-\d{4}$/;
22 var dlRegex = /^[a-zA-Z]{2}-\w+/; /* driver's license */
23 var phoneRegex = /\d{3}-\d{3}-\d{4}/;
24 var nonumRegex = /^[a-zA-Z]\D*$/; /* no numbers, no beginning whitespace */
25 var dateRegex = /^\d{4}-\d{2}-\d{2}/;
29 function uEditDefineData(patron) {
34 object : patron.card(),
36 errkey : 'ue_bad_barcode',
47 errkey : 'ue_bad_username',
55 required : (patron.isnew()) ? true : false,
58 errkey : 'ue_bad_password',
62 onpostchange : function(field, newval) {
63 var pw2 = uEditFindFieldByWId('ue_password2');
64 /* tell the second passsword input to re-validate */
65 pw2.widget.node.onchange();
71 required : (patron.isnew()) ? true : false,
74 errkey : 'ue_bad_password',
78 onpostchange : function(field, newval) {
79 var pw1f = uEditFindFieldByWId('ue_password1');
80 var pw1 = uEditNodeVal(pw1f);
82 removeCSSClass(field.widget.node, CSS_INVALID_DATA);
84 addCSSClass(field.widget.node, CSS_INVALID_DATA);
91 key : 'first_given_name',
92 errkey : 'ue_bad_firstname',
97 onblur : function(field) {
98 uEditCheckNamesDup('first', field );
106 key : 'second_given_name',
107 errkey : 'ue_bad_middlename',
109 id : 'ue_middlename',
118 errkey : 'ue_bad_lastname',
123 onblur : function(field) {
124 uEditCheckNamesDup('last', field );
135 onload : function(val) {
136 setSelector($('ue_suffix_selector'), val);
144 errkey : 'ue_bad_dob',
155 errkey : 'ue_no_ident',
157 id : 'ue_primary_ident_type',
160 onpostchange : function(field, newval)
161 { _uEditIdentPostchange('primary', field, newval); }
169 id : 'ue_primary_ident',
171 onblur : function(field) {
172 uEditCheckIdentDup(field);
181 id : 'ue_secondary_ident_type',
184 onpostchange : function(field, newval)
185 { _uEditIdentPostchange('secondary', field, newval); }
191 key : 'ident_value2',
193 id : 'ue_secondary_ident',
195 onblur : function(field) {
196 uEditCheckIdentDup(field);
204 errkey : 'ue_bad_email',
208 regex : /.+\@.+\..+/, /* make me better */
209 onblur : function(field) {
210 var val = uEditNodeVal(field);
211 if( val && val != field.oldemail ) {
212 uEditRunDupeSearch('email',
213 { email : { value : val, group : 0 } });
214 field.oldemail = val;
223 errkey : 'ue_bad_phone',
233 key : 'evening_phone',
234 errkey : 'ue_bad_phone',
236 id : 'ue_night_phone',
245 errkey : 'ue_bad_phone',
247 id : 'ue_other_phone',
257 id : 'ue_org_selector',
266 errkey : 'ue_bad_expire',
295 errkey : 'ue_no_profile',
300 onpostchange : function(field, value) {
301 var type = groupsCache[value];
302 var interval = type.perm_interval();
303 var intsecs = parseInt(util.date.interval_to_seconds(interval));
305 var expdate = new Date();
306 var exptime = expdate.getTime();
307 exptime += intsecs * 1000;
308 expdate.setTime(exptime);
310 var year = expdate.getYear() + 1900;
311 var month = (expdate.getMonth() + 1) + '';
312 var day = (expdate.getDate() + 1) + '';
314 if(!month.match(/\d{2}/)) month = '0' + month;
315 if(!day.match(/\d{2}/)) day = '0' + day;
317 var node = $('ue_expire');
318 node.value = year+'-'+month+'-'+day;
325 key : 'master_account',
327 id : 'ue_group_lead',
334 key : 'claims_returned_count',
336 id : 'ue_claims_returned',
344 key : 'alert_message',
346 id : 'ue_alert_message',
352 for( var f in fields )
353 dataFields.push(fields[f]);
355 uEditBuildAddrs(patron);
356 uEditBuildPatronSCM(patron);
359 var uEditOldFirstName;
360 var uEditOldMiddleName; /* future */
361 var uEditOldLastName;
362 function uEditCheckNamesDup(type, field) {
363 var newval = uEditNodeVal(field);
366 var dosearch = false;
369 if( newval != uEditOldFirstName )
371 uEditOldFirstName = newval;
375 if( newval != uEditOldLastName )
377 uEditOldLastName = newval;
380 if( dosearch && uEditOldFirstName && uEditOldLastName ) {
381 var search_hash = {};
382 search_hash['first_given_name'] = { value : uEditOldFirstName, group : 0 };
383 search_hash['family_name'] = { value : uEditOldLastName, group : 0 };
384 uEditRunDupeSearch('names', search_hash);
388 var uEditOldIdentValue;
389 function uEditCheckIdentDup(field) {
390 var newval = uEditNodeVal(field);
391 if( newval && newval != uEditOldIdentValue ) {
392 /* searches all ident_value fields */
393 var search_hash = { ident : { value : newval, group : 2 } };
394 uEditRunDupeSearch('ident', search_hash);
395 uEditOldIdentValue = newval;
400 /* Adds all of the addresses attached to the patron object
401 to the fields array */
402 var uEditAddrTemplate;
403 function uEditBuildAddrs(patron) {
404 var tbody = $('ue_address_tbody');
406 tbody.removeChild($('ue_address_template'));
407 for( var a in patron.addresses() )
408 uEditBuildAddrFields( patron, patron.addresses()[a]);
412 function uEditDeleteAddr( tbody, row, address ) {
413 if(!confirm($('ue_delete_addr_warn').innerHTML)) return;
414 if(address.isnew()) {
416 grep( patron.addresses(),
418 return (i.id() != address.id());
423 address.isdeleted(1);
425 tbody.removeChild(row);
427 var bid = patron.billing_address();
428 bid = (typeof bid == 'object') ? bid.id() : bid;
430 var mid = patron.mailing_address();
431 mid = (typeof mid == 'object') ? mid.id() : mid;
434 /* -----------------------------------------------------------------------
435 if we're deleting a billing or mailing address
436 make sure some other address is automatically
437 assigned as the billing or mailng address
438 ----------------------------------------------------------------------- */
440 if( bid == address.id() ) {
441 for( var a in patron.addresses() ) {
442 var addr = patron.addresses()[a];
443 if(!addr.isdeleted()) {
444 var node = uEditFindAddrInput('billing', addr.id());
446 uEditAddrTypeClick(node, 'billing');
452 if( mid == address.id() ) {
453 for( var a in patron.addresses() ) {
454 var addr = patron.addresses()[a];
455 if(!addr.isdeleted()) {
456 var node = uEditFindAddrInput('mailing', addr.id());
458 uEditAddrTypeClick(node, 'mailing');
466 function uEditFindAddrInput(type, id) {
467 var tbody = $('ue_address_tbody');
468 var rows = tbody.getElementsByTagName('tr');
469 for( var r in rows ) {
471 if(row.parentNode != tbody) continue;
472 var node = $n(row, 'ue_addr_'+type+'_yes');
473 if( node.getAttribute('address') == id )
479 function uEditAddrTypeClick(input, type) {
480 var tbody = $('ue_address_tbody');
481 var rows = tbody.getElementsByTagName('tr');
482 for( var r in rows ) {
484 if(row.parentNode != tbody) continue;
485 var node = $n(row, 'ue_addr_'+type+'_yes');
486 removeCSSClass(node.parentNode,'addr_info_checked');
489 addCSSClass(input.parentNode,'addr_info_checked');
490 patron[type+'_address'](input.getAttribute('address'));
497 /* Creates the field entries for an address object. */
498 function uEditBuildAddrFields(patron, address) {
500 var tbody = $('ue_address_tbody');
501 var row = tbody.appendChild(
502 uEditAddrTemplate.cloneNode(true));
504 $n(row, 'ue_addr_delete').onclick =
505 function() { uEditDeleteAddr(tbody, row, address); }
507 if( address.id() == patron.billing_address().id() )
508 $n(row, 'ue_addr_billing_yes').checked = true;
511 if( address.id() == patron.mailing_address().id() )
512 $n(row, 'ue_addr_mailing_yes').checked = true;
514 $n(row, 'ue_addr_billing_yes').setAttribute('address', address.id());
515 $n(row, 'ue_addr_mailing_yes').setAttribute('address', address.id());
521 key : 'address_type',
524 name : 'ue_addr_label',
532 errkey : 'ue_bad_addr_street',
535 name : 'ue_addr_street1',
543 errkey : 'ue_bad_addr_street',
546 name : 'ue_addr_street2',
554 errkey : 'ue_bad_addr_city',
557 name : 'ue_addr_city',
567 name : 'ue_addr_county',
575 errkey : 'ue_bad_addr_state',
578 name : 'ue_addr_state',
586 errkey : 'ue_bad_addr_country',
589 name : 'ue_addr_country',
597 errkey : 'ue_bad_addr_zip',
600 name : 'ue_addr_zip',
603 onblur : function(f) {
604 var v = uEditNodeVal(f);
605 var req = new Request(ZIP_SEARCH, v);
608 var info = r.getResultObject();
610 var state = $n(f.widget.base, 'ue_addr_state');
611 var county = $n(f.widget.base, 'ue_addr_county');
612 var city = $n(f.widget.base, 'ue_addr_city');
613 if(!state.value) state.value = info.state;
614 if(!county.value) county.value = info.county;
615 if(!city.value) city.value = info.city;
625 key : 'within_city_limits',
628 name : 'ue_addr_inc_yes',
638 name : 'ue_addr_valid_yes',
644 for( var f in fields ) {
645 dataFields.push(fields[f]);
646 uEditActivateField(fields[f]);
650 function uEditBuildPatronSCM(patron) {
651 /* get the list of pre-defined maps */
652 var fields = uEditFindFieldsByKey('stat_cat_entry');
656 /* for each user stat cat, pop it off the list,
657 updated the existing stat map field to match
658 the popped map and shove the existing stat
659 map field onto the user's list of stat maps */
660 while( (map = patron.stat_cat_entries().pop()) ) {
662 var field = grep(fields,
664 return (item.object.stat_cat() == map.stat_cat());
669 var val = map.stat_cat_entry();
671 $n(field.widget.base, field.widget.name).value = val;
672 setSelector($n(field.widget.base, 'ue_stat_cat_selector'), val );
673 field.object.stat_cat_entry(val);
674 field.object.id(map.id());
675 newmaps.push(field.object);
679 for( var m in newmaps )
680 patron.stat_cat_entries().push(newmaps[m]);
684 function uEditBuildSCMField(statcat, row) {
686 var map = new actscecm();
687 map.stat_cat(statcat.id());
688 map.target_usr(patron.id());
693 key : 'stat_cat_entry',
696 name : 'ue_stat_cat_newval',
699 onpostchange : function( field, newval ) {
701 /* see if the current map already resides in
702 the patron entry list */
703 var exists = grep( patron.stat_cat_entries(),
705 return (item.stat_cat() == statcat.id());
711 setSelector($n(row, 'ue_stat_cat_selector'), newval);
717 /* if the map is new but currently contains no value
718 remove it from the set of new maps */
720 patron.stat_cat_entries(
721 grep( patron.stat_cat_entries(),
723 return (item.stat_cat() != map.stat_cat());
736 /* map does not exist in the map array but now has data */
739 patron.stat_cat_entries().push(map);
746 dataFields.push(field);
751 /** Run this after a new ident type is selected */
752 function _uEditIdentPostchange(type, field, newval) {
756 /* When the ident type is changed, we change the
757 regex on the ident_value to match the selected type */
758 var vfname = 'ident_value';
759 if(type == 'secondary') vfname = 'ident_value2';
760 var vfield = uEditFindFieldByKey(vfname);
761 var name = identTypesCache[uEditNodeVal(field)].name();
763 hideMe($(type+'_ident_ssn_help'));
764 hideMe($(type+'_ident_dl_help'));
766 if(name.match(/ssn/i)) {
767 vfield.widget.regex = ssnRegex;
768 vfield.errkey = 'ue_bad_ident_ssn';
769 unHideMe($(type+'_ident_ssn_help'));
773 if(name.match(/driver/i)) {
774 vfield.widget.regex = dlRegex;
775 vfield.errkey = 'ue_bad_ident_dl';
776 unHideMe($(type+'_ident_dl_help'));
777 if(!uEditNodeVal(vfield))
778 vfield.widget.node.value = defaultState + '-';
781 vfield.widget.regex = null;
782 vfield.errkey = null;
786 /* focus then valdate the value field */
787 vfield.widget.node.onchange();
788 vfield.widget.node.focus();