@@ -438,44 +438,177 @@ var wfCivi = (function ($, D) {
438438 */
439439 D . behaviors . membershipTypeFeesUpdate = {
440440 attach : function ( context , settings ) {
441- const membershipSelector = 'select[id*="membership-membership-type-id"]' ;
442- // Should apply for multiple membership type.
441+ const membershipSelector = '[id*="membership-membership-type-id"]' ;
442+
443+ // Function to get membership value from Drupal settings.
444+ function getMembershipValue ( fieldsetName ) {
445+ // Solution 1: Check Drupal settings.
446+ if ( typeof Drupal . settings . webform !== 'undefined' &&
447+ typeof Drupal . settings . webform . membershipValues !== 'undefined' ) {
448+ return Drupal . settings . webform . membershipValues [ fieldsetName ] || '' ;
449+ }
450+ return '' ;
451+ }
452+
453+ // Function to update fee field with AJAX call.
454+ function updateFeeField ( membershipId , feeFieldInput ) {
455+ if ( ! membershipId || feeFieldInput . length === 0 ) {
456+ return ;
457+ }
458+
459+ $ . ajax ( {
460+ url : '/webform-civicrm/js/getMembershipFees/' + membershipId ,
461+ dataType : 'json' ,
462+ success : function ( response ) {
463+ if ( response . fees !== undefined ) {
464+ $ ( feeFieldInput ) . val ( response . fees ) ;
465+ }
466+ } ,
467+ error : function ( ) {
468+ console . log ( 'Failed to fetch fee.' ) ;
469+ }
470+ } ) ;
471+ }
472+
473+ // Function to extract core membership pattern from field name.
474+ function extractMembershipPattern ( elementName ) {
475+ // Extract civicrm_X_membership_Y_membership from both structures:
476+ // 1. submitted[civicrm_1_membership_1_membership_membership_type_id]
477+ // 2. submitted[...][civicrm_1_membership_1_membership_membership_type_id]
478+ const match = elementName . match ( / ( c i v i c r m _ \d + _ m e m b e r s h i p _ \d + _ m e m b e r s h i p ) _ m e m b e r s h i p _ t y p e _ i d / ) ;
479+ return match ? match [ 1 ] : null ;
480+ }
481+
482+ // Function to find corresponding fee field.
483+ function findCorrespondingFeeField ( membershipPattern , context ) {
484+ // Look for fee field with the same pattern.
485+ const feeFields = $ ( 'input[id*="membership-fee-amount-from-membership"]' , context ) ;
486+ return feeFields . filter ( function ( ) {
487+ const feeFieldName = $ ( this ) . attr ( 'name' ) ;
488+ if ( ! feeFieldName ) {
489+ return false ;
490+ }
491+
492+ // Check if this fee field contains the same membership pattern.
493+ const feePattern = membershipPattern + '_fee_amount_from_membership' ;
494+ return feeFieldName . includes ( feePattern ) ;
495+ } ) ;
496+ }
497+
498+ // Function to get current membership type value from the form.
499+ function getCurrentMembershipValue ( membershipPattern , context ) {
500+ const membershipFields = $ ( membershipSelector , context ) . filter ( function ( ) {
501+ const fieldName = $ ( this ) . attr ( 'name' ) ;
502+ if ( ! fieldName ) {
503+ return false ;
504+ }
505+
506+ const fieldPattern = extractMembershipPattern ( fieldName ) ;
507+ return fieldPattern === membershipPattern ;
508+ } ) ;
509+
510+ if ( membershipFields . length === 0 ) {
511+ return '' ;
512+ }
513+
514+ const field = membershipFields . first ( ) ;
515+ if ( field . is ( 'input[type="radio"]' ) ) {
516+ const radioName = field . attr ( 'name' ) ;
517+ const checkedRadio = $ ( 'input[type="radio"][name="' + radioName + '"]:checked' , context ) ;
518+ return checkedRadio . length > 0 ? checkedRadio . val ( ) : '' ;
519+ } else {
520+ return field . val ( ) || '' ;
521+ }
522+ }
523+
524+ // Handle each membership field individually.
443525 $ ( membershipSelector , context ) . each ( function ( ) {
444- // On change membership type field.
445- $ ( membershipSelector , context ) . once ( 'feeAjax' ) . change ( function ( ) {
446- const membershipSelect = $ ( this ) ;
447- // Get name attribute of membership type.
448- var membershipSelectname = membershipSelect . attr ( 'name' ) ;
449- // Pregmatch to fetch fieldset name.
450- // Capture fieldset name inside the first pair of square brackets.
451- var membershipSelectMatch = membershipSelectname . match ( / \[ ( [ ^ \[ \] ] + ) \] / ) ;
452- // This is fieldset for each contact.
453- var civiContactFieldset = membershipSelectMatch [ 1 ] ;
454-
455- const feeField = 'input[id*="membership-fee-amount-from-membership"]' ;
456- // Filter the fees input which has same fieldset as name.
457- const feeFieldInput = $ ( feeField ) . filter ( function ( ) {
458- // Safely checks if the name exists and includes the target.
459- return $ ( this ) . attr ( 'name' ) ?. includes ( civiContactFieldset ) ;
460- } ) ;
526+ const $element = $ ( this ) ;
527+ const isRadio = $element . is ( 'input[type="radio"]' ) ;
528+ const isSelect = $element . is ( 'select' ) ;
461529
462- // Make ajax request when fees field present.
463- if ( feeFieldInput ) {
464- const membershipId = membershipSelect . val ( ) ;
465- $ . ajax ( {
466- url : '/webform-civicrm/js/getMembershipFees/' + membershipId ,
467- dataType : 'json' ,
468- success : function ( response ) {
469- if ( response . fees !== undefined ) {
470- $ ( feeFieldInput ) . val ( response . fees ) ;
471- }
472- } ,
473- error : function ( ) {
474- console . log ( 'Failed to fetch fee.' ) ;
475- }
476- } ) ;
530+ if ( ! isRadio && ! isSelect ) {
531+ return ;
532+ }
533+
534+ const elementName = $element . attr ( 'name' ) ;
535+ const membershipPattern = extractMembershipPattern ( elementName ) ;
536+
537+ if ( ! membershipPattern ) {
538+ return ;
539+ }
540+
541+ // Set up change handler for this specific membership instance.
542+ $element . once ( 'feeAjax-' + membershipPattern ) . on ( 'change' , function ( ) {
543+ let selectedValue ;
544+
545+ // Get selected value based on element type.
546+ if ( isRadio ) {
547+ const radioName = $ ( this ) . attr ( 'name' ) ;
548+ const checkedRadio = $ ( 'input[type="radio"][name="' + radioName + '"]:checked' , context ) ;
549+ if ( checkedRadio . length === 0 ) {
550+ return ;
551+ }
552+ selectedValue = checkedRadio . val ( ) ;
553+ } else {
554+ selectedValue = $ ( this ) . val ( ) ;
555+ }
556+
557+ // Find the corresponding fee field.
558+ const feeFieldInput = findCorrespondingFeeField ( membershipPattern , context ) ;
559+ // Update fee field.
560+ updateFeeField ( selectedValue , feeFieldInput ) ;
561+ } ) ;
562+
563+ // Check for stored values on page load for this membership instance.
564+ const storedValue = getMembershipValue ( membershipPattern ) ;
565+ if ( storedValue ) {
566+ // Find the corresponding fee field.
567+ const feeFieldInput = findCorrespondingFeeField ( membershipPattern , context ) ;
568+ // If fee field exists and is empty, update it.
569+ if ( feeFieldInput . length > 0 ) {
570+ updateFeeField ( storedValue , feeFieldInput ) ;
477571 }
572+ }
573+ } ) ;
574+
575+ // Also check for fee fields that might exist without corresponding membership fields on current step.
576+ const feeFields = $ ( 'input[id*="membership-fee-amount-from-membership"]' , context ) ;
577+ feeFields . each ( function ( ) {
578+ const feeInput = $ ( this ) ;
579+ const feeInputName = feeInput . attr ( 'name' ) ;
580+
581+ if ( ! feeInputName ) {
582+ return ;
583+ }
584+
585+ // Extract membership pattern from fee field name.
586+ const match = feeInputName . match ( / ( c i v i c r m _ \d + _ m e m b e r s h i p _ \d + _ m e m b e r s h i p ) _ f e e _ a m o u n t _ f r o m _ m e m b e r s h i p / ) ;
587+ const membershipPattern = match ? match [ 1 ] : null ;
588+
589+ if ( ! membershipPattern ) {
590+ return ;
591+ }
592+
593+ // Check if corresponding membership field exists on current step.
594+ const correspondingMembershipField = $ ( membershipSelector ) . filter ( function ( ) {
595+ const membershipFieldName = $ ( this ) . attr ( 'name' ) ;
596+ if ( ! membershipFieldName ) {
597+ return false ;
598+ }
599+ const fieldPattern = extractMembershipPattern ( membershipFieldName ) ;
600+ return fieldPattern === membershipPattern ;
478601 } ) ;
602+
603+ // Only process if no corresponding membership field exists on current step.
604+ if ( correspondingMembershipField . length === 0 ) {
605+ // Check stored value from Drupal settings.
606+ const membershipValue = getMembershipValue ( membershipPattern ) ;
607+ // If we have a stored value and fee field is empty, update it.
608+ if ( membershipValue ) {
609+ updateFeeField ( membershipValue , feeInput ) ;
610+ }
611+ }
479612 } ) ;
480613 }
481614 } ;
0 commit comments