-
Notifications
You must be signed in to change notification settings - Fork 21
#80(wpum custom fields) adding repeaters as subfields of a repeater should be allowed #410
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -30,14 +30,18 @@ jQuery( function( $ ) { | |||||||||
| init: function() { | ||||||||||
| var self = this; | ||||||||||
|
|
||||||||||
| $( '.add-repeater-row' ).each( function() { | ||||||||||
| var parent = $( this ).parents( 'fieldset' ); | ||||||||||
| var repeater = parent.find( '.fieldset-wpum_field_group' ).not('.fieldset-wpum_field_group-clone' ); | ||||||||||
|
|
||||||||||
| if ( repeater.length ) { | ||||||||||
| var name = parent.get( 0 ).classList[ 0 ]; | ||||||||||
| self.increaseInstance( name ); | ||||||||||
| self.validateMaxRows( name ); | ||||||||||
| // Setup instances to first level repeaters | ||||||||||
| $('form > fieldset > .add-repeater-row').each(function () { | ||||||||||
| var fieldSet = $(this).closest( 'fieldset' ); | ||||||||||
| var fieldGroup = $(fieldSet).find( ' > .fieldset-wpum_field_group' ).not('.fieldset-wpum_field_group-clone' ); | ||||||||||
|
|
||||||||||
| if ( fieldGroup.length ) { | ||||||||||
| self.setupInstances(fieldSet, null); | ||||||||||
|
|
||||||||||
| var repeaterKey = self.getRepeaterKey(fieldSet); | ||||||||||
|
|
||||||||||
| self.increaseInstance( repeaterKey ); | ||||||||||
| self.validateMaxRows( fieldSet ); | ||||||||||
| } | ||||||||||
| } ); | ||||||||||
|
|
||||||||||
|
|
@@ -51,17 +55,21 @@ jQuery( function( $ ) { | |||||||||
| } ); | ||||||||||
|
|
||||||||||
| self.form.on( 'click', '.add-repeater-row', function() { | ||||||||||
| var parent = $( this ).parents( 'fieldset' ); | ||||||||||
| self.addNewInstance( parent.get( 0 ).classList[ 0 ] ); | ||||||||||
| var fieldSet = $(this).parent('fieldset'); | ||||||||||
| // Setup new instance based on the parent fieldset | ||||||||||
| self.addNewInstance( fieldSet ); | ||||||||||
| self.form.wpumConditionalFields({}); | ||||||||||
| } ); | ||||||||||
|
|
||||||||||
| self.form.on( 'click', '.remove-repeater-row', function(e) { | ||||||||||
| e.preventDefault(); | ||||||||||
| var parent = $( this ).parents( 'fieldset' ); | ||||||||||
| var $row = $( this ).parents( '.fieldset-wpum_field_group' ); | ||||||||||
| var fieldSet = $(this).closest('fieldset'); | ||||||||||
| var parentBase = $(fieldSet).attr('data-parent-base'); | ||||||||||
| var $row = $( this ).parent( '.fieldset-wpum_field_group' ); | ||||||||||
| $row.remove(); | ||||||||||
| self.setupInstances( parent.get( 0 ).classList[ 0 ] ); | ||||||||||
|
|
||||||||||
| self.setupInstances( fieldSet, parentBase ); | ||||||||||
| self.validateMaxRows( fieldSet ); | ||||||||||
| } ); | ||||||||||
| }, | ||||||||||
|
|
||||||||||
|
|
@@ -73,23 +81,27 @@ jQuery( function( $ ) { | |||||||||
| this.repeaters[ name ]++; | ||||||||||
| }, | ||||||||||
|
|
||||||||||
| addNewInstance: function( name ) { | ||||||||||
| this.addNewRepeaterRow( name ); | ||||||||||
| this.setupInstances( name ); | ||||||||||
| addNewInstance: function( fieldSet ) { | ||||||||||
| this.addNewRepeaterRow(fieldSet); | ||||||||||
|
|
||||||||||
| var parentBase = $(fieldSet).attr('data-parent-base'); | ||||||||||
| this.setupInstances(fieldSet, parentBase); | ||||||||||
|
|
||||||||||
| initFields(); | ||||||||||
| }, | ||||||||||
|
|
||||||||||
| resetInstance: function( name ) { | ||||||||||
| this.repeaters[ name ] = 0; | ||||||||||
| }, | ||||||||||
|
|
||||||||||
| addNewRepeaterRow: function( name ) { | ||||||||||
| var repeater = $( '.' + name ).find( '.fieldset-wpum_field_group-clone' ).last(); | ||||||||||
| addNewRepeaterRow: function (fieldSet) { | ||||||||||
| // Get repeater from the immediate child | ||||||||||
| var repeater = $(fieldSet).find(' > .fieldset-wpum_field_group-clone').last(); | ||||||||||
| if ( !repeater.length ) { | ||||||||||
| return; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| if ( !this.validateMaxRows( name ) ) { | ||||||||||
| if ( !this.validateMaxRows( fieldSet ) ) { | ||||||||||
| return; | ||||||||||
| } | ||||||||||
|
|
||||||||||
|
|
@@ -99,58 +111,87 @@ jQuery( function( $ ) { | |||||||||
| newRepeater.insertBefore( repeater ); | ||||||||||
| }, | ||||||||||
|
|
||||||||||
| setupInstances: function( name ) { | ||||||||||
| var repeaterRow = $( '.' + name ).find( '.fieldset-wpum_field_group' ).not( '.fieldset-wpum_field_group-clone' ); | ||||||||||
| getRepeaterKey: function(fieldSet) { | ||||||||||
| var parentBase = $(fieldSet).attr('data-parent-base'); | ||||||||||
| var repeaterKey = $(fieldSet).get(0).classList[0]; | ||||||||||
| repeaterKey = repeaterKey.replace('fieldset-', ''); | ||||||||||
|
|
||||||||||
| if (parentBase) { | ||||||||||
| repeaterKey = parentBase + '[' + repeaterKey + ']'; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| return repeaterKey; | ||||||||||
| }, | ||||||||||
|
|
||||||||||
| setupInstances: function (fieldSet, parentBase) { | ||||||||||
| if (typeof parentBase === 'undefined' || parentBase === null) { | ||||||||||
| parentBase = null; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| var repeaterRow = $( fieldSet ).find( ' > .fieldset-wpum_field_group' ).not( '.fieldset-wpum_field_group-clone' ); | ||||||||||
| var self = this; | ||||||||||
|
|
||||||||||
| if ( !repeaterRow.length ) { | ||||||||||
| return; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| self.resetInstance( name ); | ||||||||||
|
|
||||||||||
| repeaterRow.each( function( i ) { | ||||||||||
| $( this ).find('fieldset').attr('data-index', i); | ||||||||||
| $( this ).find( ':input' ).each( function() { | ||||||||||
| var name = ''; | ||||||||||
| if ( $( this ).attr( 'data-name' ) ) { | ||||||||||
| name = $( this ).attr( 'data-name' ); | ||||||||||
| } else { | ||||||||||
| name = $( this ).prop( 'name' ); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| $( this ).attr( | ||||||||||
| 'name', | ||||||||||
| name.replace( | ||||||||||
| new RegExp( /\[(.*?)\]/ ), | ||||||||||
| function() { | ||||||||||
| return '[' + i + ']'; | ||||||||||
| } | ||||||||||
| ) | ||||||||||
| ); | ||||||||||
|
|
||||||||||
| if ( i > 0 ) { | ||||||||||
| var clone_id = ''; | ||||||||||
| if ( $( this ).attr( 'data-clone' ) ) { | ||||||||||
| clone_id = $( this ).attr( 'data-clone' ); | ||||||||||
| } else { | ||||||||||
| clone_id = $(this).prop( 'id' ); | ||||||||||
| // Apply parentBase to the fieldset to make it available later | ||||||||||
| if (parentBase) { | ||||||||||
| $(fieldSet).attr('data-parent-base', parentBase); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| var repeaterKey = self.getRepeaterKey(fieldSet); | ||||||||||
| self.resetInstance(repeaterKey); | ||||||||||
|
|
||||||||||
| repeaterRow.each(function (i) { | ||||||||||
| $(fieldSet).attr('data-index', i); | ||||||||||
| $(this) | ||||||||||
| .find('> fieldset > .field :input') | ||||||||||
| // Exclude sub repeater fields | ||||||||||
| .not($(this).find('> fieldset > .fieldset-wpum_field_group :input')) | ||||||||||
| .each(function() { | ||||||||||
| var fieldName = $(this).attr('data-name') || $(this).prop('name'); | ||||||||||
| fieldName = fieldName.replace(/\[(.*?)\]/, '[' + i + ']'); | ||||||||||
|
|
||||||||||
| // Prepend parentBase if available and does not already have a parentBase | ||||||||||
| if (parentBase && !fieldName.includes(parentBase)) { | ||||||||||
|
Comment on lines
+156
to
+157
|
||||||||||
| // Prepend parentBase if available and does not already have a parentBase | |
| if (parentBase && !fieldName.includes(parentBase)) { | |
| // Prepend parentBase if available and the fieldName is not already prefixed with it | |
| if (parentBase && !fieldName.startsWith(parentBase + '[')) { |
Copilot
AI
Feb 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The recursive call to setupInstances on line 185 doesn't have any depth limit or circular reference check. While unlikely in normal usage, if there's a bug in the field configuration that creates circular parent-child relationships, this could cause infinite recursion and stack overflow. Consider adding a depth parameter or tracking visited fieldsets to prevent potential infinite loops.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The selector
$(this).find('> fieldset > .field :input')excludes inputs from nested repeaters using.not($(this).find('> fieldset > .fieldset-wpum_field_group :input')). However, this creates a new jQuery object inside.not()which could have performance implications if there are many nested repeaters. Consider caching the nested inputs selector or using a more efficient approach like filtering within a single find operation.