Skip to content
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

enhance: repeat field enhancement #1389

Open
wants to merge 22 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ Vue.component('field-options', {
return self.$store.state.form_fields[i];
}

// check if the editing field belong to column field
if (self.$store.state.form_fields[i].template === 'column_field') {
// check if the editing field belong to column field or repeat field
if (self.$store.state.form_fields[i].template.match(/^(column|repeat)_field$/)) {
var innerColumnFields = self.$store.state.form_fields[i].inner_fields;

for (const columnFields in innerColumnFields) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ Vue.component('form-column_field', {
return ( field.recaptcha_type && 'invisible_recaptcha' === field.recaptcha_type ) ? true : false;
},

isAllowedInClolumnField: function(field_template) {

isAllowedInColumnField: function(field_template) {
var restrictedFields = ['column_field', 'custom_hidden_field', 'step_start'];

if ( $.inArray(field_template, restrictedFields) >= 0 ) {
Expand All @@ -180,7 +181,7 @@ Vue.component('form-column_field', {
toWhichColumn: data.to_column
};

if (this.isAllowedInClolumnField(data.field_template)) {
if (this.isAllowedInColumnField(data.field_template)) {
Swal.fire({
title: "Oops...",
text: "You cannot add this field as inner column field"
Expand Down
10 changes: 8 additions & 2 deletions admin/form-builder/assets/js/form-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,21 @@

}

// check if the editing field belong to a column field
if (state.form_fields[i].template === 'column_field') {
// check if the editing field belong to a column field or repeat field
if (state.form_fields[i].template.match(/^(column|repeat)_field$/)) {
var innerColumnFields = state.form_fields[i].inner_fields;

for (const columnFields in innerColumnFields) {
if (innerColumnFields.hasOwnProperty(columnFields)) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use Object.hasOwn() instead of hasOwnProperty.

It's recommended to use Object.hasOwn() for better reliability. See MDN web docs for more details.

Apply this diff to replace hasOwnProperty with Object.hasOwn():

- if (innerColumnFields.hasOwnProperty(columnFields)) {
+ if (Object.hasOwn(innerColumnFields, columnFields)) {
- if (payload.field_name === 'name'  && ! innerColumnFields[columnFields][columnFieldIndex].hasOwnProperty('is_new') ) {
+ if (payload.field_name === 'name'  && ! Object.hasOwn(innerColumnFields[columnFields][columnFieldIndex], 'is_new') ) {

Also applies to: 142-142

Tools
Biome

[error] 137-137: Do not access Object.prototype method 'hasOwnProperty' from target object.

It's recommended using Object.hasOwn() instead of using Object.hasOwnProperty().
See MDN web docs for more details.

(lint/suspicious/noPrototypeBuiltins)

var columnFieldIndex = 0;

while (columnFieldIndex < innerColumnFields[columnFields].length) {
// don't modify existing meta key
if (payload.field_name === 'name' && ! innerColumnFields[columnFields][columnFieldIndex].hasOwnProperty('is_new') ) {
columnFieldIndex++;
continue;
}

if (innerColumnFields[columnFields][columnFieldIndex].id === parseInt(payload.editing_field_id)) {
innerColumnFields[columnFields][columnFieldIndex][payload.field_name] = payload.value;
}
Expand Down
4 changes: 2 additions & 2 deletions admin/form-builder/assets/js/mixins/global.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ Vue.mixin({
return true;
}

// check if the single instance field exist in column fields
if (self.$store.state.form_fields[i].template === 'column_field') {
// check if the single instance field exist in column fields or repeat field
if (self.$store.state.form_fields[i].template.match(/^(column|repeat)_field$/)) {
var innerColumnFields = self.$store.state.form_fields[i].inner_fields;

for (const columnFields in innerColumnFields) {
Expand Down
3 changes: 2 additions & 1 deletion assets/css/admin.css
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,8 @@ ul.wpuf-form .wpuf-field-columns .wpuf-column-field-inner-columns .wpuf-column .
margin: 0;
padding: 15px 0;
}
#form-preview-stage .field-items .wpuf-field-columns + div.control-buttons {
#form-preview-stage .field-items .wpuf-field-columns + div.control-buttons,
#form-preview-stage .field-items .wpuf-repeat-field + div.control-buttons {
top: 10px;
z-index: 10;
height: auto;
Expand Down
20 changes: 12 additions & 8 deletions assets/css/frontend-forms.css
Original file line number Diff line number Diff line change
Expand Up @@ -504,24 +504,29 @@ body ul.wpuf-form li .wpuf-fields .wpuf-fields-list.wpuf-list-inline li {
padding-left: 5px;
padding-right: 5px;
}
body ul.wpuf-form li .wpuf-fields table.wpuf-repeatable-field {
body ul.wpuf-form li .wpuf-fields .wpuf-repeatable-field {
border-collapse: collapse;
}
body ul.wpuf-form li .wpuf-fields table.wpuf-repeatable-field * {
box-sizing: border-box;
body ul.wpuf-form li .wpuf-fields .wpuf-repeatable-field.wpuf-field-columns {
display: flex;
justify-content: space-between;
align-items: center;
}
body ul.wpuf-form li .wpuf-fields table.wpuf-repeatable-field input {
body ul.wpuf-form li .wpuf-fields .wpuf-repeatable-field .wpuf-column-field-inner-columns {
width: 100%;
}
body ul.wpuf-form li .wpuf-fields table.wpuf-repeatable-field .wpuf-repeater-buttons {
body ul.wpuf-form li .wpuf-fields .wpuf-repeatable-field * {
box-sizing: border-box;
}
body ul.wpuf-form li .wpuf-fields .wpuf-repeatable-field .wpuf-repeater-buttons {
width: 75px;
padding-left: 12px;
}
body ul.wpuf-form li .wpuf-fields table.wpuf-repeatable-field .wpuf-repeater-buttons img {
body ul.wpuf-form li .wpuf-fields .wpuf-repeatable-field .wpuf-repeater-buttons img {
width: 100%;
height: auto;
}
body ul.wpuf-form li .wpuf-fields table.wpuf-repeatable-field .wpuf-repeater-buttons i {
body ul.wpuf-form li .wpuf-fields .wpuf-repeatable-field .wpuf-repeater-buttons i {
display: inline-block;
width: 15px;
height: 15px;
Expand Down Expand Up @@ -1755,7 +1760,6 @@ body ul.wpuf-form .wpuf-field-columns .wpuf-column-field-inner-columns .wpuf-col
border: 0;
float: none;
width: 100%;
overflow: hidden;
}
body ul.wpuf-form .wpuf-field-columns .wpuf-column-field-inner-columns .wpuf-column .wpuf-column-inner-fields {
padding: 0 5px 0 0;
Expand Down
78 changes: 73 additions & 5 deletions assets/js/frontend-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@
//enable multistep
this.enableMultistep(this);

var form = $('.wpuf-form');
// clone and remove repeated field
$('.wpuf-form').on('click', 'img.wpuf-clone-field', this.cloneField);
$('.wpuf-form').on('click', 'img.wpuf-remove-field', this.removeField);
$('.wpuf-form').on('click', 'a.wpuf-delete-avatar', this.deleteAvatar);
$('.wpuf-form').on('click', 'a#wpuf-post-draft', this.draftPost);
$('.wpuf-form').on('click', 'button#wpuf-account-update-profile', this.account_update_profile);
form.on('click', 'img.wpuf-clone-field', this.cloneField);
form.on('click', 'img.wpuf-clone-repeat-field', this.cloneRepeatField);
form.on('click', 'img.wpuf-remove-field', this.removeField);
form.on('click', 'img.wpuf-remove-repeat-field', this.removeRepeatField);
form.on('click', 'a.wpuf-delete-avatar', this.deleteAvatar);
form.on('click', 'a#wpuf-post-draft', this.draftPost);
form.on('click', 'button#wpuf-account-update-profile', this.account_update_profile);

$('.wpuf-form-add').on('submit', this.formSubmit);
$('form#post').on('submit', this.adminPostSubmit);
Expand Down Expand Up @@ -342,6 +345,71 @@
}
},

cloneRepeatField: function( e ) {
e.preventDefault();

var div = $( this ).closest( '.wpuf-column-field-inner-columns.column-repeat' );
var clone = div.clone();

// clear the inputs
clone.find( 'input:not(:checkbox):not(:radio)' ).val( '' );
clone.find( 'textarea' ).val( '' );
clone.find( ':checked' ).prop( 'checked', false );
div.after( clone );

WP_User_Frontend.calculateFieldsName( $( this ).parents( '.wpuf-field-columns' ) );
WP_User_Frontend.setRowNumber( $( this ).closest( '.wpuf-field-columns' ) );
},

removeRepeatField: function () {
//check if it's the only item
var parent = $( this ).closest( '.wpuf-column-field-inner-columns.column-repeat' );
var allItems = parent.siblings().addBack();
var itemsLength = allItems.length;

var fieldIndex = $( allItems ).index( $( this ).closest( '.wpuf-column-field-inner-columns.column-repeat' ) );

if ( itemsLength > 1 ) {
WP_User_Frontend.setRowNumber( $( parent ).closest( '.wpuf-field-columns' ), itemsLength - 1 );
parent.remove();
}

// calculate only if the removed item is not the last item
if ( fieldIndex + 1 !== itemsLength ) {
WP_User_Frontend.calculateFieldsName( parent );
}
},

setRowNumber: function ( parent, length ) {
if ( ! length ) {
length = $( parent ).children().length;
}

$( parent ).parent( '.wpuf-fields' ).find( 'input.repeat_row_numbers' ).val( length );
},

calculateFieldsName: function( parentItem ) {
var field_rows = parentItem.children();
var field_names = [];
var field_ids = [];
var field_classes = [];
var fields_selector = '.wpuf-column input, .wpuf-column textarea, .wpuf-column select, .wpuf-column .wpuf-rich-validation';

$( field_rows[0] ).find( fields_selector ).each( function ( i, item ) {
field_names.push( $( item ).attr( 'name' ).split( '_0_' ) );
field_ids.push( $( item ).attr( 'id' ).split( '_0_' ) );
field_classes.push( $( item ).attr( 'class' ).split( '_0_' ) );
});

field_rows.each( function( i, row ) {
$( row ).find( fields_selector ).each( function( y, field ) {
$( field ).attr( 'name', field_names[y][0] + '_' + i + '_' + field_names[y][1] );
$( field ).attr( 'id', field_ids[y][0] + '_' + i + '_' + field_ids[y][1] );
$( field ).attr( 'class', field_classes[y][0] + '_' + i + '_' + field_classes[y][1] );
});
});
},

adminPostSubmit: function(e) {
e.preventDefault();

Expand Down
9 changes: 5 additions & 4 deletions assets/js/wpuf-form-builder-components.js
Original file line number Diff line number Diff line change
Expand Up @@ -451,8 +451,8 @@ Vue.component('field-options', {
return self.$store.state.form_fields[i];
}

// check if the editing field belong to column field
if (self.$store.state.form_fields[i].template === 'column_field') {
// check if the editing field belong to column field or repeat field
if (self.$store.state.form_fields[i].template.match(/^(column|repeat)_field$/)) {
var innerColumnFields = self.$store.state.form_fields[i].inner_fields;

for (const columnFields in innerColumnFields) {
Expand Down Expand Up @@ -929,7 +929,8 @@ Vue.component('form-column_field', {
return ( field.recaptcha_type && 'invisible_recaptcha' === field.recaptcha_type ) ? true : false;
},

isAllowedInClolumnField: function(field_template) {

isAllowedInColumnField: function(field_template) {
var restrictedFields = ['column_field', 'custom_hidden_field', 'step_start'];

if ( $.inArray(field_template, restrictedFields) >= 0 ) {
Expand All @@ -947,7 +948,7 @@ Vue.component('form-column_field', {
toWhichColumn: data.to_column
};

if (this.isAllowedInClolumnField(data.field_template)) {
if (this.isAllowedInColumnField(data.field_template)) {
Swal.fire({
title: "Oops...",
text: "You cannot add this field as inner column field"
Expand Down
4 changes: 2 additions & 2 deletions assets/js/wpuf-form-builder-mixins.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ Vue.mixin({
return true;
}

// check if the single instance field exist in column fields
if (self.$store.state.form_fields[i].template === 'column_field') {
// check if the single instance field exist in column fields or repeat field
if (self.$store.state.form_fields[i].template.match(/^(column|repeat)_field$/)) {
var innerColumnFields = self.$store.state.form_fields[i].inner_fields;

for (const columnFields in innerColumnFields) {
Expand Down
2 changes: 1 addition & 1 deletion assets/js/wpuf-form-builder-wpuf-forms.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
}

// check in column field
if (form_field.template === 'column_field' ) {
if (form_field.template.match(/^(column|repeat)_field$/)) {
var innerColumnFields = form_field.inner_fields;

for (const columnFields in innerColumnFields) {
Expand Down
10 changes: 8 additions & 2 deletions assets/js/wpuf-form-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,21 @@

}

// check if the editing field belong to a column field
if (state.form_fields[i].template === 'column_field') {
// check if the editing field belong to a column field or repeat field
if (state.form_fields[i].template.match(/^(column|repeat)_field$/)) {
var innerColumnFields = state.form_fields[i].inner_fields;

for (const columnFields in innerColumnFields) {
if (innerColumnFields.hasOwnProperty(columnFields)) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use Object.hasOwn() instead of hasOwnProperty.

It's recommended to use Object.hasOwn() for better reliability. See MDN web docs for more details.

Apply this diff to replace hasOwnProperty with Object.hasOwn():

- if (innerColumnFields.hasOwnProperty(columnFields)) {
+ if (Object.hasOwn(innerColumnFields, columnFields)) {
- if (payload.field_name === 'name'  && ! innerColumnFields[columnFields][columnFieldIndex].hasOwnProperty('is_new') ) {
+ if (payload.field_name === 'name'  && ! Object.hasOwn(innerColumnFields[columnFields][columnFieldIndex], 'is_new') ) {

Also applies to: 142-142

Tools
Biome

[error] 137-137: Do not access Object.prototype method 'hasOwnProperty' from target object.

It's recommended using Object.hasOwn() instead of using Object.hasOwnProperty().
See MDN web docs for more details.

(lint/suspicious/noPrototypeBuiltins)

var columnFieldIndex = 0;

while (columnFieldIndex < innerColumnFields[columnFields].length) {
// don't modify existing meta key
if (payload.field_name === 'name' && ! innerColumnFields[columnFields][columnFieldIndex].hasOwnProperty('is_new') ) {
columnFieldIndex++;
continue;
}

if (innerColumnFields[columnFields][columnFieldIndex].id === parseInt(payload.editing_field_id)) {
innerColumnFields[columnFields][columnFieldIndex][payload.field_name] = payload.value;
}
Expand Down
3 changes: 2 additions & 1 deletion assets/less/admin.less
Original file line number Diff line number Diff line change
Expand Up @@ -839,7 +839,8 @@ ul.wpuf-form{
}
}

#form-preview-stage .field-items .wpuf-field-columns + div.control-buttons{
#form-preview-stage .field-items .wpuf-field-columns + div.control-buttons,
#form-preview-stage .field-items .wpuf-repeat-field + div.control-buttons{
top: 10px;
z-index: 10;
height: auto;
Expand Down
15 changes: 10 additions & 5 deletions assets/less/frontend-forms.less
Original file line number Diff line number Diff line change
Expand Up @@ -562,17 +562,23 @@ ul.wpuf-form {
}
}

table.wpuf-repeatable-field {
.wpuf-repeatable-field {
border-collapse: collapse;

& * {
box-sizing: border-box;
&.wpuf-field-columns {
display: flex;
justify-content: space-between;
align-items: center;
}

input {
.wpuf-column-field-inner-columns {
width: 100%;
}

& * {
box-sizing: border-box;
}

.wpuf-repeater-buttons {
width: 75px;
padding-left: 12px;
Expand Down Expand Up @@ -2033,7 +2039,6 @@ ul.wpuf-form{
border: 0;
float: none;
width: 100%;
overflow: hidden;

.wpuf-column-inner-fields{
padding: 0 5px 0 0;
Expand Down
1 change: 0 additions & 1 deletion includes/Ajax/Admin_Form_Builder_Ajax.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@
* @return void
*/
public function save_form() {
$post_data = wp_unslash($_POST);

Check failure on line 19 in includes/Ajax/Admin_Form_Builder_Ajax.php

View workflow job for this annotation

GitHub Actions / Run PHPCS inspection

Expected 1 space after "="; 2 found

Check failure on line 19 in includes/Ajax/Admin_Form_Builder_Ajax.php

View workflow job for this annotation

GitHub Actions / Run PHPCS inspection

Expected 1 spaces after opening parenthesis; 0 found

Check failure on line 19 in includes/Ajax/Admin_Form_Builder_Ajax.php

View workflow job for this annotation

GitHub Actions / Run PHPCS inspection

Expected 1 spaces before closing parenthesis; 0 found
if ( isset( $post_data['form_data'] ) ) {
parse_str( $post_data['form_data'], $form_data );

Check failure on line 21 in includes/Ajax/Admin_Form_Builder_Ajax.php

View workflow job for this annotation

GitHub Actions / Run PHPCS inspection

Expected 1 space after comma in argument list; 2 found
} else {
wp_send_json_error( __( 'form data is missing', 'wp-user-frontend'));

Check failure on line 23 in includes/Ajax/Admin_Form_Builder_Ajax.php

View workflow job for this annotation

GitHub Actions / Run PHPCS inspection

Expected 1 spaces before closing parenthesis; 0 found

Check failure on line 23 in includes/Ajax/Admin_Form_Builder_Ajax.php

View workflow job for this annotation

GitHub Actions / Run PHPCS inspection

Expected 1 spaces before closing parenthesis; 0 found
}

if ( !wp_verify_nonce( $form_data['wpuf_form_builder_nonce'], 'wpuf_form_builder_save_form' ) ) {

Check failure on line 26 in includes/Ajax/Admin_Form_Builder_Ajax.php

View workflow job for this annotation

GitHub Actions / Run PHPCS inspection

Expected 1 space after "!"; 0 found
wp_send_json_error( __( 'Unauthorized operation', 'wp-user-frontend' ) );
}

Expand All @@ -50,7 +50,6 @@
$integrations = (array) json_decode( $post_data['integrations'] );
}


$form_fields = json_decode( $form_fields, true );
$notifications = json_decode( $notifications, true );

Expand All @@ -66,11 +65,11 @@

$form_fields = Admin_Form_Builder::save_form( $data );

wp_send_json_success( [ 'form_fields' => $form_fields, 'form_settings' => $settings ] );

Check warning on line 68 in includes/Ajax/Admin_Form_Builder_Ajax.php

View workflow job for this annotation

GitHub Actions / Run PHPCS inspection

When a multi-item array uses associative keys, each value should start on a new line.
}

public function wpuf_get_post_taxonomies() {
$post_data = wp_unslash($_POST);

Check failure on line 72 in includes/Ajax/Admin_Form_Builder_Ajax.php

View workflow job for this annotation

GitHub Actions / Run PHPCS inspection

Expected 1 space after "="; 2 found

Check failure on line 72 in includes/Ajax/Admin_Form_Builder_Ajax.php

View workflow job for this annotation

GitHub Actions / Run PHPCS inspection

Expected 1 spaces after opening parenthesis; 0 found

Check failure on line 72 in includes/Ajax/Admin_Form_Builder_Ajax.php

View workflow job for this annotation

GitHub Actions / Run PHPCS inspection

Expected 1 spaces before closing parenthesis; 0 found
$post_type = $post_data['post_type'];
$nonce = $post_data['wpuf_form_builder_setting_nonce'];

Expand Down Expand Up @@ -108,6 +107,6 @@
}
}

wp_send_json_success( [ 'success' => 'true' , 'data' => $cat ] );

Check warning on line 110 in includes/Ajax/Admin_Form_Builder_Ajax.php

View workflow job for this annotation

GitHub Actions / Run PHPCS inspection

When a multi-item array uses associative keys, each value should start on a new line.
}
}
Loading
Loading