Formidable Forms – Form Builder for WordPress - Version 5.5.3

Version Description

  • New: HTML emails using wpautop will now also convert line breaks into
    tags.
  • New: Improved support for importing large XML files. Previously a file over 200MB would trigger a "parser error : internal error: Huge input lookup" error.
  • Fix: When an HTML email includes a body tag, only the content of the body tag will use wpautop.
  • Fix: A duplicated field group would merge into one larger field group instead of creating a second identical field group as expected.
  • Fix: The "Add Fields Here" placeholder wouldn't hide after duplicating a section until after refreshing the page.
  • Fix: The Screen Options tab was not hidden after duplicating an entry, causing it to overlap the update button.
  • Fix: An imported view shortcode was not properly updating to its new ID value if the post containing it did not also include a [formidable] shortcode.
  • Fix: Tooltips that overlap the element that triggered the tooltip would cause the tooltip to flicker on and off.
  • Fix: The ellipses icon that triggers shortcode pop ups was offset incorrectly in of text fields inside of form actions.
  • Fix: The update button was missing on the alternative style editor submenu link available from the WordPress themes menu.
  • Fix: Honeypot fields should no longer gain focus when tabbing through fields in Chrome.
  • Fix: Fields wouldn't follow the cursor as expected after scrolling the page while dragging.
  • Fix: Recent styling updates were applying to radio buttons in the form builder by mistake, causing them to look incorrect.
  • Front end polyfills for IE8 have been removed, reducing the size of the loaded script file.
  • Added additional form builder restrictions so a hidden field and page break don't become part of a field group.
Download this release

Release Info

Developer formidableforms
Plugin Icon 128x128 Formidable Forms – Form Builder for WordPress
Version 5.5.3
Comparing to
See all releases

Code changes from version 5.5.2 to 5.5.3

classes/controllers/FrmAppController.php CHANGED
@@ -178,7 +178,7 @@ class FrmAppController {
178
  'permission' => 'frm_edit_forms',
179
  ),
180
  array(
181
- 'link' => admin_url( 'admin.php?page=formidable-entries&frm-full=1&frm_action=list&form=' . absint( $id ) ),
182
  'label' => __( 'Entries', 'formidable' ),
183
  'current' => array(),
184
  'page' => 'formidable-entries',
@@ -190,7 +190,7 @@ class FrmAppController {
190
 
191
  if ( ! $views_installed ) {
192
  $nav_items[] = array(
193
- 'link' => admin_url( 'admin.php?page=formidable-views&frm-full=1&form=' . absint( $id ) ),
194
  'label' => __( 'Views', 'formidable' ),
195
  'current' => array(),
196
  'page' => 'formidable-views',
@@ -204,7 +204,7 @@ class FrmAppController {
204
  // Let people know reports and views exist.
205
  if ( ! FrmAppHelper::pro_is_installed() ) {
206
  $nav_items[] = array(
207
- 'link' => admin_url( 'admin.php?page=formidable&frm_action=lite-reports&frm-full=1&form=' . absint( $id ) ),
208
  'label' => __( 'Reports', 'formidable' ),
209
  'current' => array( 'reports' ),
210
  'page' => 'formidable',
@@ -499,7 +499,7 @@ class FrmAppController {
499
  'formidable_embed',
500
  );
501
 
502
- if ( FrmAppHelper::is_admin_page( 'formidable-styles' ) || FrmAppHelper::is_admin_page( 'formidable-styles2' ) ) {
503
  $dependencies[] = 'wp-color-picker';
504
  }
505
 
178
  'permission' => 'frm_edit_forms',
179
  ),
180
  array(
181
+ 'link' => admin_url( 'admin.php?page=formidable-entries&frm_action=list&form=' . absint( $id ) ),
182
  'label' => __( 'Entries', 'formidable' ),
183
  'current' => array(),
184
  'page' => 'formidable-entries',
190
 
191
  if ( ! $views_installed ) {
192
  $nav_items[] = array(
193
+ 'link' => admin_url( 'admin.php?page=formidable-views&form=' . absint( $id ) ),
194
  'label' => __( 'Views', 'formidable' ),
195
  'current' => array(),
196
  'page' => 'formidable-views',
204
  // Let people know reports and views exist.
205
  if ( ! FrmAppHelper::pro_is_installed() ) {
206
  $nav_items[] = array(
207
+ 'link' => admin_url( 'admin.php?page=formidable&frm_action=lite-reports&form=' . absint( $id ) ),
208
  'label' => __( 'Reports', 'formidable' ),
209
  'current' => array( 'reports' ),
210
  'page' => 'formidable',
499
  'formidable_embed',
500
  );
501
 
502
+ if ( FrmAppHelper::is_style_editor_page() ) {
503
  $dependencies[] = 'wp-color-picker';
504
  }
505
 
classes/controllers/FrmApplicationsController.php CHANGED
@@ -14,9 +14,8 @@ class FrmApplicationsController {
14
  * @return void
15
  */
16
  public static function menu() {
17
- $label = __( 'Applications', 'formidable' );
18
- $new_pill = '<span class="frm-new-pill">NEW</span>';
19
- $cap = self::get_required_capability();
20
 
21
  if ( ! current_user_can( $cap ) && is_callable( 'FrmProApplicationsHelper::get_custom_applications_capability' ) ) {
22
  $custom_applications_cap = FrmProApplicationsHelper::get_custom_applications_capability();
@@ -32,7 +31,7 @@ class FrmApplicationsController {
32
  $callback = array( __CLASS__, 'landing_page' );
33
  }
34
 
35
- add_submenu_page( 'formidable', 'Formidable | ' . $label, $label . $new_pill, $cap, $slug, $callback );
36
  }
37
 
38
  /**
14
  * @return void
15
  */
16
  public static function menu() {
17
+ $label = __( 'Applications', 'formidable' );
18
+ $cap = self::get_required_capability();
 
19
 
20
  if ( ! current_user_can( $cap ) && is_callable( 'FrmProApplicationsHelper::get_custom_applications_capability' ) ) {
21
  $custom_applications_cap = FrmProApplicationsHelper::get_custom_applications_capability();
31
  $callback = array( __CLASS__, 'landing_page' );
32
  }
33
 
34
+ add_submenu_page( 'formidable', 'Formidable | ' . $label, $label, $cap, $slug, $callback );
35
  }
36
 
37
  /**
classes/controllers/FrmEntriesController.php CHANGED
@@ -24,7 +24,7 @@ class FrmEntriesController {
24
  * @since 2.05.07
25
  */
26
  private static function load_manage_entries_hooks() {
27
- if ( ! in_array( FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' ), array( 'edit', 'show', 'new' ) ) ) {
28
  $menu_name = FrmAppHelper::get_menu_name();
29
  $base = self::base_column_key( $menu_name );
30
 
24
  * @since 2.05.07
25
  */
26
  private static function load_manage_entries_hooks() {
27
+ if ( ! in_array( FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' ), array( 'edit', 'show', 'new', 'duplicate' ), true ) ) {
28
  $menu_name = FrmAppHelper::get_menu_name();
29
  $base = self::base_column_key( $menu_name );
30
 
classes/controllers/FrmFormActionsController.php CHANGED
@@ -44,31 +44,32 @@ class FrmFormActionsController {
44
  */
45
  public static function register_actions() {
46
  $action_classes = array(
47
- 'email' => 'FrmEmailAction',
48
- 'wppost' => 'FrmDefPostAction',
49
- 'register' => 'FrmDefRegAction',
50
- 'paypal' => 'FrmDefPayPalAction',
51
- 'payment' => 'FrmDefHrsAction',
52
- 'quiz' => 'FrmDefQuizAction',
53
- 'quiz_outcome' => 'FrmDefQuizOutcomeAction',
54
- 'mailchimp' => 'FrmDefMlcmpAction',
55
- 'api' => 'FrmDefApiAction',
56
- 'salesforce' => 'FrmDefSalesforceAction',
57
- 'activecampaign' => 'FrmDefActiveCampaignAction',
58
- 'constantcontact' => 'FrmDefConstContactAction',
59
- 'getresponse' => 'FrmDefGetResponseAction',
60
- 'hubspot' => 'FrmDefHubspotAction',
61
- 'zapier' => 'FrmDefZapierAction',
62
- 'twilio' => 'FrmDefTwilioAction',
63
- 'highrise' => 'FrmDefHighriseAction',
64
- 'mailpoet' => 'FrmDefMailpoetAction',
65
- 'aweber' => 'FrmDefAweberAction',
 
66
  );
67
 
68
  $action_classes = apply_filters( 'frm_registered_form_actions', $action_classes );
69
 
70
- include_once( FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/email_action.php' );
71
- include_once( FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/default_actions.php' );
72
 
73
  foreach ( $action_classes as $action_class ) {
74
  self::$registered_actions->register( $action_class );
@@ -89,7 +90,7 @@ class FrmFormActionsController {
89
 
90
  $allowed = self::active_actions( $action_controls );
91
 
92
- include( FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/settings.php' );
93
  }
94
 
95
  /**
@@ -131,7 +132,7 @@ class FrmFormActionsController {
131
  */
132
  public static function form_action_groups() {
133
  $groups = array(
134
- 'misc' => array(
135
  'name' => '',
136
  'icon' => 'frm_icon_font frm_shuffle_icon',
137
  'actions' => array(
@@ -317,7 +318,7 @@ class FrmFormActionsController {
317
 
318
  $use_logging = self::should_show_log_message( $form_action->post_excerpt );
319
 
320
- include( FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/form_action.php' );
321
  }
322
 
323
  public static function add_form_action() {
@@ -340,7 +341,7 @@ class FrmFormActionsController {
340
  $values = array();
341
  $form = self::fields_to_values( $form_id, $values );
342
 
343
- include( FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/form_action.php' );
344
  wp_die();
345
  }
346
 
@@ -363,7 +364,7 @@ class FrmFormActionsController {
363
 
364
  $use_logging = self::should_show_log_message( $action_type );
365
 
366
- include( FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/_action_inside.php' );
367
  wp_die();
368
  }
369
 
@@ -467,7 +468,7 @@ class FrmFormActionsController {
467
  $action_status = array(
468
  'post_status' => 'publish',
469
  );
470
- $form_actions = FrmFormAction::get_action_for_form( ( is_object( $form ) ? $form->id : $form ), $type, $action_status );
471
 
472
  if ( empty( $form_actions ) ) {
473
  return;
44
  */
45
  public static function register_actions() {
46
  $action_classes = array(
47
+ 'email' => 'FrmEmailAction',
48
+ 'wppost' => 'FrmDefPostAction',
49
+ 'register' => 'FrmDefRegAction',
50
+ 'paypal' => 'FrmDefPayPalAction',
51
+ 'payment' => 'FrmDefHrsAction',
52
+ 'quiz' => 'FrmDefQuizAction',
53
+ 'quiz_outcome' => 'FrmDefQuizOutcomeAction',
54
+ 'mailchimp' => 'FrmDefMlcmpAction',
55
+ 'api' => 'FrmDefApiAction',
56
+ 'salesforce' => 'FrmDefSalesforceAction',
57
+ 'activecampaign' => 'FrmDefActiveCampaignAction',
58
+ 'constantcontact' => 'FrmDefConstContactAction',
59
+ 'getresponse' => 'FrmDefGetResponseAction',
60
+ 'hubspot' => 'FrmDefHubspotAction',
61
+ 'zapier' => 'FrmDefZapierAction',
62
+ 'twilio' => 'FrmDefTwilioAction',
63
+ 'highrise' => 'FrmDefHighriseAction',
64
+ 'mailpoet' => 'FrmDefMailpoetAction',
65
+ 'aweber' => 'FrmDefAweberAction',
66
+ 'googlespreadsheet' => 'FrmDefGoogleSpreadsheetAction',
67
  );
68
 
69
  $action_classes = apply_filters( 'frm_registered_form_actions', $action_classes );
70
 
71
+ include_once FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/email_action.php';
72
+ include_once FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/default_actions.php';
73
 
74
  foreach ( $action_classes as $action_class ) {
75
  self::$registered_actions->register( $action_class );
90
 
91
  $allowed = self::active_actions( $action_controls );
92
 
93
+ include FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/settings.php';
94
  }
95
 
96
  /**
132
  */
133
  public static function form_action_groups() {
134
  $groups = array(
135
+ 'misc' => array(
136
  'name' => '',
137
  'icon' => 'frm_icon_font frm_shuffle_icon',
138
  'actions' => array(
318
 
319
  $use_logging = self::should_show_log_message( $form_action->post_excerpt );
320
 
321
+ include FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/form_action.php';
322
  }
323
 
324
  public static function add_form_action() {
341
  $values = array();
342
  $form = self::fields_to_values( $form_id, $values );
343
 
344
+ include FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/form_action.php';
345
  wp_die();
346
  }
347
 
364
 
365
  $use_logging = self::should_show_log_message( $action_type );
366
 
367
+ include FrmAppHelper::plugin_path() . '/classes/views/frm-form-actions/_action_inside.php';
368
  wp_die();
369
  }
370
 
468
  $action_status = array(
469
  'post_status' => 'publish',
470
  );
471
+ $form_actions = FrmFormAction::get_action_for_form( ( is_object( $form ) ? $form->id : $form ), $type, $action_status );
472
 
473
  if ( empty( $form_actions ) ) {
474
  return;
classes/controllers/FrmStylesController.php CHANGED
@@ -51,8 +51,11 @@ class FrmStylesController {
51
  add_submenu_page( 'themes.php', 'Formidable | ' . __( 'Styles', 'formidable' ), __( 'Forms', 'formidable' ), 'frm_change_settings', 'formidable-styles2', 'FrmStylesController::route' );
52
  }
53
 
 
 
 
54
  public static function admin_init() {
55
- if ( ! FrmAppHelper::is_admin_page( 'formidable-styles' ) && ! FrmAppHelper::is_admin_page( 'formidable-styles2' ) ) {
56
  return;
57
  }
58
 
51
  add_submenu_page( 'themes.php', 'Formidable | ' . __( 'Styles', 'formidable' ), __( 'Forms', 'formidable' ), 'frm_change_settings', 'formidable-styles2', 'FrmStylesController::route' );
52
  }
53
 
54
+ /**
55
+ * @return void
56
+ */
57
  public static function admin_init() {
58
+ if ( ! FrmAppHelper::is_style_editor_page() ) {
59
  return;
60
  }
61
 
classes/helpers/FrmAppHelper.php CHANGED
@@ -1402,7 +1402,6 @@ class FrmAppHelper {
1402
  $post = get_post( $post_id );
1403
  if ( $post ) {
1404
  $post_url = admin_url( 'post.php?post=' . $post_id . '&action=edit' );
1405
- $post_url = self::maybe_full_screen_link( $post_url );
1406
 
1407
  return '<a href="' . esc_url( $post_url ) . '">' . self::truncate( $post->post_title, 50 ) . '</a>';
1408
  }
@@ -1419,20 +1418,38 @@ class FrmAppHelper {
1419
  */
1420
  public static function is_full_screen() {
1421
  return self::is_form_builder_page() ||
1422
- self::is_admin_page( 'formidable-styles' ) ||
1423
- self::is_admin_page( 'formidable-styles2' ) ||
1424
- self::simple_get( 'frm-full', 'absint' ) ||
1425
- self::is_view_builder_page();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1426
  }
1427
 
1428
  /**
1429
  * @since 4.0
 
1430
  */
1431
  public static function maybe_full_screen_link( $link ) {
1432
- $is_full = self::simple_get( 'frm-full', 'absint' );
1433
- if ( $is_full && ! empty( $link ) && $link !== '#' ) {
1434
- $link .= '&frm-full=1';
1435
- }
1436
  return $link;
1437
  }
1438
 
@@ -2856,6 +2873,7 @@ class FrmAppHelper {
2856
  'active' => __( 'Active', 'formidable' ),
2857
  'select_a_field' => __( 'Select a Field', 'formidable' ),
2858
  'no_items_found' => __( 'No items found.', 'formidable' ),
 
2859
  );
2860
  $admin_script_strings = apply_filters( 'frm_admin_script_strings', $admin_script_strings );
2861
 
1402
  $post = get_post( $post_id );
1403
  if ( $post ) {
1404
  $post_url = admin_url( 'post.php?post=' . $post_id . '&action=edit' );
 
1405
 
1406
  return '<a href="' . esc_url( $post_url ) . '">' . self::truncate( $post->post_title, 50 ) . '</a>';
1407
  }
1418
  */
1419
  public static function is_full_screen() {
1420
  return self::is_form_builder_page() ||
1421
+ self::is_style_editor_page() ||
1422
+ self::is_full_screen_view_builder_page();
1423
+ }
1424
+
1425
+ /**
1426
+ * Check if user is on the style editor, or the alternative URL.
1427
+ * The first URL is a submenu "Styles" in the Formidable menu /wp-admin/admin.php?page=formidable-styles.
1428
+ * The alternative URL is linked as a submenu "Forms" item of the Appearance menu /wp-admin/themes.php?page=formidable-styles2.
1429
+ *
1430
+ * @since 5.5.3
1431
+ *
1432
+ * @return bool
1433
+ */
1434
+ public static function is_style_editor_page() {
1435
+ return self::is_admin_page( 'formidable-styles' ) || self::is_admin_page( 'formidable-styles2' );
1436
+ }
1437
+
1438
+ /**
1439
+ * @since 5.5.3
1440
+ *
1441
+ * @return bool
1442
+ */
1443
+ private static function is_full_screen_view_builder_page() {
1444
+ return self::is_admin_page( 'formidable-views-editor' );
1445
  }
1446
 
1447
  /**
1448
  * @since 4.0
1449
+ * @deprecated 5.5.3
1450
  */
1451
  public static function maybe_full_screen_link( $link ) {
1452
+ _deprecated_function( __METHOD__, '5.5.3' );
 
 
 
1453
  return $link;
1454
  }
1455
 
2873
  'active' => __( 'Active', 'formidable' ),
2874
  'select_a_field' => __( 'Select a Field', 'formidable' ),
2875
  'no_items_found' => __( 'No items found.', 'formidable' ),
2876
+ 'field_already_used' => __( 'Oops. You have already used that field.', 'formidable' ),
2877
  );
2878
  $admin_script_strings = apply_filters( 'frm_admin_script_strings', $admin_script_strings );
2879
 
classes/helpers/FrmCSVExportHelper.php CHANGED
@@ -477,7 +477,12 @@ class FrmCSVExportHelper {
477
 
478
  foreach ( self::$fields_by_repeater_id[ $repeater_id ] as $repeater_child ) {
479
  if ( ! isset( $metas[ $repeater_child->id ] ) ) {
480
- $metas[ $repeater_child->id ] = '';
 
 
 
 
 
481
  $entries[ self::$entry->parent_item_id ]->metas[ $repeater_child->id ][] = '';
482
  }
483
  }
@@ -517,8 +522,11 @@ class FrmCSVExportHelper {
517
  $label_key = $col->id . '_label';
518
  if ( self::is_the_child_of_a_repeater( $col ) ) {
519
  $row[ $label_key ] = array();
520
- foreach ( $field_value as $value ) {
521
- $row[ $label_key ][] = self::get_separate_value_label( $value, $col );
 
 
 
522
  }
523
  } else {
524
  $row[ $label_key ] = self::get_separate_value_label( $field_value, $col );
477
 
478
  foreach ( self::$fields_by_repeater_id[ $repeater_id ] as $repeater_child ) {
479
  if ( ! isset( $metas[ $repeater_child->id ] ) ) {
480
+ $metas[ $repeater_child->id ] = '';
481
+
482
+ if ( ! isset( $entries[ self::$entry->parent_item_id ]->metas[ $repeater_child->id ] ) || ! is_array( $entries[ self::$entry->parent_item_id ]->metas[ $repeater_child->id ] ) ) {
483
+ $entries[ self::$entry->parent_item_id ]->metas[ $repeater_child->id ] = array();
484
+ }
485
+
486
  $entries[ self::$entry->parent_item_id ]->metas[ $repeater_child->id ][] = '';
487
  }
488
  }
522
  $label_key = $col->id . '_label';
523
  if ( self::is_the_child_of_a_repeater( $col ) ) {
524
  $row[ $label_key ] = array();
525
+
526
+ if ( is_array( $field_value ) ) {
527
+ foreach ( $field_value as $value ) {
528
+ $row[ $label_key ][] = self::get_separate_value_label( $value, $col );
529
+ }
530
  }
531
  } else {
532
  $row[ $label_key ] = self::get_separate_value_label( $field_value, $col );
classes/helpers/FrmEntriesHelper.php CHANGED
@@ -613,7 +613,7 @@ class FrmEntriesHelper {
613
  foreach ( $links as $link ) {
614
  ?>
615
  <div class="misc-pub-section">
616
- <a href="<?php echo esc_url( FrmAppHelper::maybe_full_screen_link( $link['url'] ) ); ?>"
617
  <?php
618
  if ( isset( $link['data'] ) ) {
619
  foreach ( $link['data'] as $data => $value ) {
613
  foreach ( $links as $link ) {
614
  ?>
615
  <div class="misc-pub-section">
616
+ <a href="<?php echo esc_url( $link['url'] ); ?>"
617
  <?php
618
  if ( isset( $link['data'] ) ) {
619
  foreach ( $link['data'] as $data => $value ) {
classes/helpers/FrmEntriesListHelper.php CHANGED
@@ -224,7 +224,7 @@ class FrmEntriesListHelper extends FrmListHelper {
224
 
225
  $r .= "<td $attributes>";
226
  if ( $column_name == $action_col ) {
227
- $edit_link = FrmAppHelper::maybe_full_screen_link( '?page=formidable-entries&frm_action=edit&id=' . $item->id );
228
  $r .= '<a href="' . esc_url( isset( $actions['edit'] ) ? $edit_link : $view_link ) . '" class="row-title" >' . $val . '</a> ';
229
  $r .= $action_links;
230
  } else {
@@ -310,12 +310,10 @@ class FrmEntriesListHelper extends FrmListHelper {
310
  * @param string $view_link
311
  */
312
  private function get_actions( &$actions, $item, $view_link ) {
313
- $view_link = FrmAppHelper::maybe_full_screen_link( $view_link );
314
  $actions['view'] = '<a href="' . esc_url( $view_link ) . '">' . __( 'View', 'formidable' ) . '</a>';
315
 
316
  if ( current_user_can( 'frm_delete_entries' ) ) {
317
  $delete_link = '?page=formidable-entries&frm_action=destroy&id=' . $item->id . '&form=' . $this->params['form'];
318
- $delete_link = FrmAppHelper::maybe_full_screen_link( $delete_link );
319
  $actions['delete'] = '<a href="' . esc_url( wp_nonce_url( $delete_link ) ) . '" class="submitdelete" data-frmverify="' . esc_attr__( 'Permanently delete this entry?', 'formidable' ) . '">' . __( 'Delete', 'formidable' ) . '</a>';
320
  }
321
 
224
 
225
  $r .= "<td $attributes>";
226
  if ( $column_name == $action_col ) {
227
+ $edit_link = admin_url( 'admin.php?page=formidable-entries&frm_action=edit&id=' . $item->id );
228
  $r .= '<a href="' . esc_url( isset( $actions['edit'] ) ? $edit_link : $view_link ) . '" class="row-title" >' . $val . '</a> ';
229
  $r .= $action_links;
230
  } else {
310
  * @param string $view_link
311
  */
312
  private function get_actions( &$actions, $item, $view_link ) {
 
313
  $actions['view'] = '<a href="' . esc_url( $view_link ) . '">' . __( 'View', 'formidable' ) . '</a>';
314
 
315
  if ( current_user_can( 'frm_delete_entries' ) ) {
316
  $delete_link = '?page=formidable-entries&frm_action=destroy&id=' . $item->id . '&form=' . $this->params['form'];
 
317
  $actions['delete'] = '<a href="' . esc_url( wp_nonce_url( $delete_link ) ) . '" class="submitdelete" data-frmverify="' . esc_attr__( 'Permanently delete this entry?', 'formidable' ) . '">' . __( 'Delete', 'formidable' ) . '</a>';
318
  }
319
 
classes/helpers/FrmXMLHelper.php CHANGED
@@ -36,8 +36,10 @@ class FrmXMLHelper {
36
  return new WP_Error( 'SimpleXML_parse_error', __( 'Your server does not have XML enabled', 'formidable' ), libxml_get_errors() );
37
  }
38
 
39
- $dom = new DOMDocument();
40
- $success = $dom->loadXML( file_get_contents( $file ) );
 
 
41
  if ( ! $success ) {
42
  return new WP_Error( 'SimpleXML_parse_error', __( 'There was an error when reading this XML file', 'formidable' ), libxml_get_errors() );
43
  }
@@ -846,7 +848,7 @@ class FrmXMLHelper {
846
  continue;
847
  }
848
 
849
- if ( false !== strpos( $post['post_content'], '[frm-display-data' ) || false !== strpos( $post['post_content'], '[formidable' ) ) {
850
  $posts_with_shortcodes[ $post_id ] = $post;
851
  }
852
 
36
  return new WP_Error( 'SimpleXML_parse_error', __( 'Your server does not have XML enabled', 'formidable' ), libxml_get_errors() );
37
  }
38
 
39
+ $dom = new DOMDocument();
40
+ // LIBXML_COMPACT activates small nodes allocation optimization.
41
+ // Use LIBXML_PARSEHUGE to avoid "parser error : internal error: Huge input lookup" for large (300MB) files.
42
+ $success = $dom->loadXML( file_get_contents( $file ), LIBXML_COMPACT | LIBXML_PARSEHUGE );
43
  if ( ! $success ) {
44
  return new WP_Error( 'SimpleXML_parse_error', __( 'There was an error when reading this XML file', 'formidable' ), libxml_get_errors() );
45
  }
848
  continue;
849
  }
850
 
851
+ if ( false !== strpos( $post['post_content'], '[display-frm-data' ) || false !== strpos( $post['post_content'], '[formidable' ) ) {
852
  $posts_with_shortcodes[ $post_id ] = $post;
853
  }
854
 
classes/models/FrmEmail.php CHANGED
@@ -397,12 +397,25 @@ class FrmEmail {
397
  if ( $this->is_plain_text ) {
398
  $this->message = wp_specialchars_decode( strip_tags( $this->message ), ENT_QUOTES );
399
  } else {
400
- $this->message = wpautop( $this->message, false ); // HTML emails should use autop.
401
  }
402
 
403
  $this->message = apply_filters( 'frm_email_message', $this->message, $this->package_atts() );
404
  }
405
 
 
 
 
 
 
 
 
 
 
 
 
 
 
406
  private function maybe_add_ip( &$mail_body ) {
407
  if ( ! empty( $this->entry->ip ) ) {
408
  $mail_body .= __( 'IP Address', 'formidable' ) . ': ' . $this->entry->ip . "\r\n";
397
  if ( $this->is_plain_text ) {
398
  $this->message = wp_specialchars_decode( strip_tags( $this->message ), ENT_QUOTES );
399
  } else {
400
+ $this->add_autop();
401
  }
402
 
403
  $this->message = apply_filters( 'frm_email_message', $this->message, $this->package_atts() );
404
  }
405
 
406
+ /**
407
+ * Runs message through autop, extracting the content inside body tag if it has <body>.
408
+ */
409
+ private function add_autop() {
410
+ $message = $this->message;
411
+ $result = preg_match( '/<body[^>]*>([\s\S]*?)<\/body>/', $message, $match );
412
+ if ( ! empty( $match[1] ) ) {
413
+ $this->message = str_replace( $match[1], trim( wpautop( $match[1] ) ), $message );
414
+ } else {
415
+ $this->message = trim( wpautop( $message ) );
416
+ }
417
+ }
418
+
419
  private function maybe_add_ip( &$mail_body ) {
420
  if ( ! empty( $this->entry->ip ) ) {
421
  $mail_body .= __( 'IP Address', 'formidable' ) . ': ' . $this->entry->ip . "\r\n";
classes/models/FrmEntry.php CHANGED
@@ -479,7 +479,7 @@ class FrmEntry {
479
  $entries = wp_cache_get( $cache_key, 'frm_entry' );
480
 
481
  if ( false === $entries ) {
482
- $fields = 'it.id, it.item_key, it.name, it.ip, it.form_id, it.post_id, it.user_id, it.parent_item_id, it.updated_by, it.created_at, it.updated_at, it.is_draft';
483
  $table = $wpdb->prefix . 'frm_items it ';
484
 
485
  if ( $inc_form ) {
479
  $entries = wp_cache_get( $cache_key, 'frm_entry' );
480
 
481
  if ( false === $entries ) {
482
+ $fields = 'it.id, it.item_key, it.name, it.ip, it.form_id, it.post_id, it.user_id, it.parent_item_id, it.updated_by, it.created_at, it.updated_at, it.is_draft, it.description';
483
  $table = $wpdb->prefix . 'frm_items it ';
484
 
485
  if ( $inc_form ) {
classes/views/frm-entries/list.php CHANGED
@@ -26,7 +26,7 @@ if ( ! defined( 'ABSPATH' ) ) {
26
  <?php
27
  FrmAppHelper::add_new_item_link(
28
  array(
29
- 'new_link' => FrmAppHelper::maybe_full_screen_link( admin_url( 'admin.php?page=formidable-entries&frm_action=new&form=' . $form->id ) ),
30
  )
31
  );
32
  ?>
26
  <?php
27
  FrmAppHelper::add_new_item_link(
28
  array(
29
+ 'new_link' => admin_url( 'admin.php?page=formidable-entries&frm_action=new&form=' . $form->id ),
30
  )
31
  );
32
  ?>
classes/views/frm-form-actions/default_actions.php CHANGED
@@ -6,8 +6,8 @@ if ( ! defined( 'ABSPATH' ) ) {
6
  // add post action
7
  class FrmDefPostAction extends FrmFormAction {
8
  public function __construct() {
9
- $action_ops = FrmFormAction::default_action_opts( 'frm_wordpress_icon frm-inverse frm_show_upgrade' );
10
- $action_ops['color'] = 'rgb(0,160,210)';
11
 
12
  parent::__construct( 'wppost', __( 'Create Post', 'formidable' ), $action_ops );
13
  }
@@ -16,9 +16,9 @@ class FrmDefPostAction extends FrmFormAction {
16
  // add register action
17
  class FrmDefRegAction extends FrmFormAction {
18
  public function __construct() {
19
- $action_ops = FrmFormAction::default_action_opts( 'frm_register_icon frm_show_upgrade' );
20
- $action_ops['plugin'] = 'registration';
21
- $action_ops['color'] = 'var(--pink)';
22
  parent::__construct( 'register', __( 'Register User', 'formidable' ), $action_ops );
23
  }
24
  }
@@ -26,7 +26,7 @@ class FrmDefRegAction extends FrmFormAction {
26
  // add paypal action
27
  class FrmDefPayPalAction extends FrmFormAction {
28
  public function __construct() {
29
- $action_ops = FrmFormAction::default_action_opts( 'frm_paypal_icon frm-inverse frm_show_upgrade' );
30
  $action_ops['color'] = 'var(--primary-hover)';
31
 
32
  parent::__construct( 'paypal', 'PayPal', $action_ops );
@@ -54,7 +54,7 @@ class FrmDefQuizOutcomeAction extends FrmFormAction {
54
  // add aweber action
55
  class FrmDefAweberAction extends FrmFormAction {
56
  public function __construct() {
57
- $action_ops = FrmFormAction::default_action_opts( 'frm_aweber_icon frm_show_upgrade' );
58
  $action_ops['color'] = 'var(--green)';
59
  parent::__construct( 'aweber', 'AWeber', $action_ops );
60
  }
@@ -63,8 +63,8 @@ class FrmDefAweberAction extends FrmFormAction {
63
  // add mailchimp action
64
  class FrmDefMlcmpAction extends FrmFormAction {
65
  public function __construct() {
66
- $action_ops = FrmFormAction::default_action_opts( 'frm_mailchimp_icon frm_show_upgrade frm-inverse' );
67
- $action_ops['color'] = 'var(--dark-grey)';
68
 
69
  parent::__construct( 'mailchimp', 'MailChimp', $action_ops );
70
  }
@@ -73,7 +73,7 @@ class FrmDefMlcmpAction extends FrmFormAction {
73
  // add zapier action
74
  class FrmDefZapierAction extends FrmFormAction {
75
  public function __construct() {
76
- $action_ops = FrmFormAction::default_action_opts( 'frm_zapier_icon frm_show_upgrade' );
77
  $action_ops['color'] = 'var(--orange)';
78
  parent::__construct( 'zapier', 'Zapier', $action_ops );
79
  }
@@ -90,8 +90,8 @@ class FrmDefTwilioAction extends FrmFormAction {
90
  // add payment action
91
  class FrmDefHrsAction extends FrmFormAction {
92
  public function __construct() {
93
- $action_ops = FrmFormAction::default_action_opts( 'frm_stripe_icon frm_credit_card_alt_icon frm_show_upgrade' );
94
- $action_ops['color'] = 'var(--green)';
95
  $action_ops['plugin'] = 'stripe';
96
  parent::__construct( 'payment', __( 'eCommerce', 'formidable' ), $action_ops );
97
  }
@@ -99,7 +99,7 @@ class FrmDefHrsAction extends FrmFormAction {
99
 
100
  class FrmDefActiveCampaignAction extends FrmFormAction {
101
  public function __construct() {
102
- $action_ops = FrmFormAction::default_action_opts( 'frm_activecampaign_icon frm_show_upgrade' );
103
  $action_ops['color'] = 'var(--primary-hover)';
104
  parent::__construct( 'activecampaign', 'ActiveCampaign', $action_ops );
105
  }
@@ -107,7 +107,7 @@ class FrmDefActiveCampaignAction extends FrmFormAction {
107
 
108
  class FrmDefSalesforceAction extends FrmFormAction {
109
  public function __construct() {
110
- $action_ops = FrmFormAction::default_action_opts( 'frm_salesforce_icon frm-inverse frm_show_upgrade' );
111
  $action_ops['color'] = 'var(--primary-color)';
112
  parent::__construct( 'salesforce', 'Salesforce', $action_ops );
113
  }
@@ -115,7 +115,7 @@ class FrmDefSalesforceAction extends FrmFormAction {
115
 
116
  class FrmDefConstContactAction extends FrmFormAction {
117
  public function __construct() {
118
- $action_ops = FrmFormAction::default_action_opts( 'frm_constant_contact_icon frm_show_upgrade' );
119
  $action_ops['color'] = 'rgb(0,160,210)';
120
  parent::__construct( 'constantcontact', 'Constant Contact', $action_ops );
121
  }
@@ -123,7 +123,7 @@ class FrmDefConstContactAction extends FrmFormAction {
123
 
124
  class FrmDefGetResponseAction extends FrmFormAction {
125
  public function __construct() {
126
- $action_ops = FrmFormAction::default_action_opts( 'frm_getresponse_icon frm_show_upgrade' );
127
  $action_ops['color'] = '#00baff';
128
  parent::__construct( 'getresponse', 'GetResponse', $action_ops );
129
  }
@@ -131,7 +131,7 @@ class FrmDefGetResponseAction extends FrmFormAction {
131
 
132
  class FrmDefHubspotAction extends FrmFormAction {
133
  public function __construct() {
134
- $action_ops = FrmFormAction::default_action_opts( 'frm_hubspot_icon frm_show_upgrade' );
135
  $action_ops['color'] = 'var(--orange)';
136
 
137
  $action_ops['message'] = '';
@@ -146,7 +146,7 @@ class FrmDefHubspotAction extends FrmFormAction {
146
 
147
  class FrmDefHighriseAction extends FrmFormAction {
148
  public function __construct() {
149
- $action_ops = FrmFormAction::default_action_opts( 'frm_building_icon frm_show_upgrade' );
150
  $action_ops['color'] = 'var(--purple)';
151
  parent::__construct( 'highrise', 'Highrise', $action_ops );
152
  }
@@ -154,7 +154,7 @@ class FrmDefHighriseAction extends FrmFormAction {
154
 
155
  class FrmDefMailpoetAction extends FrmFormAction {
156
  public function __construct() {
157
- $action_ops = FrmFormAction::default_action_opts( 'frm_mailpoet_icon frm_show_upgrade' );
158
  $action_ops['color'] = 'var(--orange)';
159
  parent::__construct( 'mailpoet', 'MailPoet', $action_ops );
160
  }
@@ -162,8 +162,17 @@ class FrmDefMailpoetAction extends FrmFormAction {
162
 
163
  class FrmDefApiAction extends FrmFormAction {
164
  public function __construct() {
165
- $action_ops = FrmFormAction::default_action_opts( 'frm_feed_icon frm_show_upgrade' );
166
  $action_ops['color'] = 'var(--purple)';
167
  parent::__construct( 'api', __( 'Send API data', 'formidable' ), $action_ops );
168
  }
169
  }
 
 
 
 
 
 
 
 
 
6
  // add post action
7
  class FrmDefPostAction extends FrmFormAction {
8
  public function __construct() {
9
+ $action_ops = FrmFormAction::default_action_opts( 'frm_wordpress_icon frm-inverse frm_show_upgrade' );
10
+ $action_ops['color'] = 'rgb(0,160,210)';
11
 
12
  parent::__construct( 'wppost', __( 'Create Post', 'formidable' ), $action_ops );
13
  }
16
  // add register action
17
  class FrmDefRegAction extends FrmFormAction {
18
  public function __construct() {
19
+ $action_ops = FrmFormAction::default_action_opts( 'frm_register_icon frm_show_upgrade' );
20
+ $action_ops['plugin'] = 'registration';
21
+ $action_ops['color'] = 'var(--pink)';
22
  parent::__construct( 'register', __( 'Register User', 'formidable' ), $action_ops );
23
  }
24
  }
26
  // add paypal action
27
  class FrmDefPayPalAction extends FrmFormAction {
28
  public function __construct() {
29
+ $action_ops = FrmFormAction::default_action_opts( 'frm_paypal_icon frm-inverse frm_show_upgrade' );
30
  $action_ops['color'] = 'var(--primary-hover)';
31
 
32
  parent::__construct( 'paypal', 'PayPal', $action_ops );
54
  // add aweber action
55
  class FrmDefAweberAction extends FrmFormAction {
56
  public function __construct() {
57
+ $action_ops = FrmFormAction::default_action_opts( 'frm_aweber_icon frm_show_upgrade' );
58
  $action_ops['color'] = 'var(--green)';
59
  parent::__construct( 'aweber', 'AWeber', $action_ops );
60
  }
63
  // add mailchimp action
64
  class FrmDefMlcmpAction extends FrmFormAction {
65
  public function __construct() {
66
+ $action_ops = FrmFormAction::default_action_opts( 'frm_mailchimp_icon frm_show_upgrade frm-inverse' );
67
+ $action_ops['color'] = 'var(--dark-grey)';
68
 
69
  parent::__construct( 'mailchimp', 'MailChimp', $action_ops );
70
  }
73
  // add zapier action
74
  class FrmDefZapierAction extends FrmFormAction {
75
  public function __construct() {
76
+ $action_ops = FrmFormAction::default_action_opts( 'frm_zapier_icon frm_show_upgrade' );
77
  $action_ops['color'] = 'var(--orange)';
78
  parent::__construct( 'zapier', 'Zapier', $action_ops );
79
  }
90
  // add payment action
91
  class FrmDefHrsAction extends FrmFormAction {
92
  public function __construct() {
93
+ $action_ops = FrmFormAction::default_action_opts( 'frm_stripe_icon frm_credit_card_alt_icon frm_show_upgrade' );
94
+ $action_ops['color'] = 'var(--green)';
95
  $action_ops['plugin'] = 'stripe';
96
  parent::__construct( 'payment', __( 'eCommerce', 'formidable' ), $action_ops );
97
  }
99
 
100
  class FrmDefActiveCampaignAction extends FrmFormAction {
101
  public function __construct() {
102
+ $action_ops = FrmFormAction::default_action_opts( 'frm_activecampaign_icon frm_show_upgrade' );
103
  $action_ops['color'] = 'var(--primary-hover)';
104
  parent::__construct( 'activecampaign', 'ActiveCampaign', $action_ops );
105
  }
107
 
108
  class FrmDefSalesforceAction extends FrmFormAction {
109
  public function __construct() {
110
+ $action_ops = FrmFormAction::default_action_opts( 'frm_salesforce_icon frm-inverse frm_show_upgrade' );
111
  $action_ops['color'] = 'var(--primary-color)';
112
  parent::__construct( 'salesforce', 'Salesforce', $action_ops );
113
  }
115
 
116
  class FrmDefConstContactAction extends FrmFormAction {
117
  public function __construct() {
118
+ $action_ops = FrmFormAction::default_action_opts( 'frm_constant_contact_icon frm_show_upgrade' );
119
  $action_ops['color'] = 'rgb(0,160,210)';
120
  parent::__construct( 'constantcontact', 'Constant Contact', $action_ops );
121
  }
123
 
124
  class FrmDefGetResponseAction extends FrmFormAction {
125
  public function __construct() {
126
+ $action_ops = FrmFormAction::default_action_opts( 'frm_getresponse_icon frm_show_upgrade' );
127
  $action_ops['color'] = '#00baff';
128
  parent::__construct( 'getresponse', 'GetResponse', $action_ops );
129
  }
131
 
132
  class FrmDefHubspotAction extends FrmFormAction {
133
  public function __construct() {
134
+ $action_ops = FrmFormAction::default_action_opts( 'frm_hubspot_icon frm_show_upgrade' );
135
  $action_ops['color'] = 'var(--orange)';
136
 
137
  $action_ops['message'] = '';
146
 
147
  class FrmDefHighriseAction extends FrmFormAction {
148
  public function __construct() {
149
+ $action_ops = FrmFormAction::default_action_opts( 'frm_building_icon frm_show_upgrade' );
150
  $action_ops['color'] = 'var(--purple)';
151
  parent::__construct( 'highrise', 'Highrise', $action_ops );
152
  }
154
 
155
  class FrmDefMailpoetAction extends FrmFormAction {
156
  public function __construct() {
157
+ $action_ops = FrmFormAction::default_action_opts( 'frm_mailpoet_icon frm_show_upgrade' );
158
  $action_ops['color'] = 'var(--orange)';
159
  parent::__construct( 'mailpoet', 'MailPoet', $action_ops );
160
  }
162
 
163
  class FrmDefApiAction extends FrmFormAction {
164
  public function __construct() {
165
+ $action_ops = FrmFormAction::default_action_opts( 'frm_feed_icon frm_show_upgrade' );
166
  $action_ops['color'] = 'var(--purple)';
167
  parent::__construct( 'api', __( 'Send API data', 'formidable' ), $action_ops );
168
  }
169
  }
170
+
171
+ // add google sheets
172
+ class FrmDefGoogleSpreadsheetAction extends FrmFormAction {
173
+ public function __construct() {
174
+ $action_ops = FrmFormAction::default_action_opts( 'frm_googlesheets_icon frm_show_upgrade' );
175
+ $action_ops['color'] = 'var(--green)';
176
+ parent::__construct( 'googlespreadsheet', __( 'Google Sheets', 'formidable' ), $action_ops );
177
+ }
178
+ }
classes/views/frm-forms/landing-page-preview-option.php CHANGED
@@ -12,8 +12,5 @@ $params['class'] = 'frm_show_upgrade frm_noallow';
12
  $params['href'] = '#';
13
  ?>
14
  <a <?php FrmAppHelper::array_to_html_params( $params, true ); ?>>
15
- <?php
16
- esc_html_e( 'Generate Form Page', 'formidable' );
17
- FrmAppHelper::show_pill_text();
18
- ?>
19
  </a>
12
  $params['href'] = '#';
13
  ?>
14
  <a <?php FrmAppHelper::array_to_html_params( $params, true ); ?>>
15
+ <?php esc_html_e( 'Generate Form Page', 'formidable' ); ?>
 
 
 
16
  </a>
classes/views/shared/admin-header.php CHANGED
@@ -5,7 +5,7 @@ if ( ! defined( 'ABSPATH' ) ) {
5
 
6
  FrmAppHelper::print_admin_banner( ! $has_nav && empty( $atts['switcher'] ) );
7
  ?>
8
- <div id="frm_top_bar">
9
  <?php if ( FrmAppHelper::is_full_screen() ) { ?>
10
  <div class="frm-full-close">
11
  <a href="<?php echo esc_attr( $atts['close'] ); ?>" aria-label="<?php esc_attr_e( 'Close', 'formidable' ); ?>">
5
 
6
  FrmAppHelper::print_admin_banner( ! $has_nav && empty( $atts['switcher'] ) );
7
  ?>
8
+ <div id="frm_top_bar" class="<?php echo esc_attr( $has_nav ? 'frm_nav_bar' : 'frm_no_nav_bar' ); ?>">
9
  <?php if ( FrmAppHelper::is_full_screen() ) { ?>
10
  <div class="frm-full-close">
11
  <a href="<?php echo esc_attr( $atts['close'] ); ?>" aria-label="<?php esc_attr_e( 'Close', 'formidable' ); ?>">
css/frm_admin.css CHANGED
@@ -227,8 +227,7 @@ td.column-title .frm_actions_dropdown {
227
  text-align: center;
228
  }
229
 
230
- .post-type-frm_display:not(.edit-php) #frm_top_bar,
231
- .frm-full-screen.post-type-frm_display #frm_top_bar,
232
  .frm_page_container #frm_top_bar {
233
  border-bottom: 1px solid var(--grey-border);
234
  padding: 0 20px;
@@ -286,14 +285,12 @@ a .frmsvg,
286
  max-width: 100%;
287
  }
288
 
289
- .frm-header-logo,
290
- .edit-php.post-type-frm_display .frm-header-logo {
291
  float: left;
292
  margin: 0 15px 0 0;
293
  }
294
 
295
- .frm-full-screen.post-type-frm_display .frm-header-logo,
296
- .post-type-frm_display .frm-header-logo,
297
  .frm_page_container .frm-header-logo {
298
  margin: 13px 0 0;
299
  }
@@ -400,7 +397,7 @@ ul.frm_form_nav > li:last-of-type {
400
  color: var(--grey);
401
  }
402
 
403
- .edit-php.post-type-frm_display #frm_top_bar h1,
404
  .frm_wrap #frm_top_bar h1 {
405
  font-size: 22px;
406
  font-weight: 400;
@@ -411,8 +408,7 @@ ul.frm_form_nav > li:last-of-type {
411
  line-height: 1.4;
412
  }
413
 
414
- .frm-full-screen.post-type-frm_display #frm_top_bar h1,
415
- .post-type-frm_display #frm_top_bar h1,
416
  .frm_page_container #frm_top_bar h1 {
417
  margin: 0 15px;
418
  padding: 20px 0 0;
@@ -421,8 +417,7 @@ ul.frm_form_nav > li:last-of-type {
421
  line-height: 1.16;
422
  }
423
 
424
- .frm-full-screen.post-type-frm_display #frm_top_bar h1 span,
425
- .post-type-frm_display #frm_top_bar h1 span,
426
  .frm_page_container #frm_top_bar h1 span {
427
  font-size: 19px;
428
  max-width: 175px;
@@ -3350,13 +3345,13 @@ input[type="checkbox"] {
3350
  margin-right: 5px;
3351
  }
3352
 
3353
- .with_frm_style .frm_radio input[type=radio] {
3354
  margin: 5px 0;
3355
  width: 18px;
3356
  position: relative; /* override Bootstrap */
3357
  }
3358
 
3359
- .with_frm_style .frm_radio input[type=radio]:before {
3360
  position: relative !important;
3361
  left: calc(50% - 6px);
3362
  top: calc(50% - 6px);
@@ -3390,10 +3385,6 @@ li.ui-state-default.selected > .frm_inner_field_container > label {
3390
  max-width: calc(100% - 100px);
3391
  }
3392
 
3393
- .frm-dragging * {
3394
- cursor: grabbing !important;
3395
- }
3396
-
3397
  .frm-drag-fade {
3398
  background-color: var(--lightest-grey) !important;
3399
  border-radius: 4px;
@@ -7432,6 +7423,7 @@ iframe#dyncontent_ifr {
7432
 
7433
  /* Custom rules */
7434
  z-index: 9999999;
 
7435
  }
7436
 
7437
  .tooltip.show {
@@ -8101,7 +8093,7 @@ Responsive Design
8101
  margin: 5px 0;
8102
  }
8103
 
8104
- .post-type-frm_display #frm_top_bar h1,
8105
  .frm_page_container #frm_top_bar h1 {
8106
  width: auto;
8107
  max-width: 200px;
@@ -8245,13 +8237,16 @@ Responsive Design
8245
  width: 100%;
8246
  }
8247
 
8248
- .with_frm_style .frm_radio input[type=radio] {
8249
- width: 18px !important;
8250
- }
8251
  .with_frm_style .frm_checkbox input[type=checkbox] {
8252
  width: 25px !important;
8253
  }
8254
 
 
 
 
 
 
8255
  .wp-list-table.toplevel_page_formidable .column-entries,
8256
  .wp-list-table.toplevel_page_formidable .column-form_key,
8257
  .wp-list-table.toplevel_page_formidable .column-shortcode,
@@ -8521,7 +8516,8 @@ Responsive Design
8521
  }
8522
  }
8523
 
8524
- .frm-admin-page-styles #frm-publishing #save_menu_header {
 
8525
  display: inline-block;
8526
  }
8527
 
227
  text-align: center;
228
  }
229
 
230
+ .post-type-frm_display #frm_top_bar.frm_nav_bar,
 
231
  .frm_page_container #frm_top_bar {
232
  border-bottom: 1px solid var(--grey-border);
233
  padding: 0 20px;
285
  max-width: 100%;
286
  }
287
 
288
+ .frm-header-logo {
 
289
  float: left;
290
  margin: 0 15px 0 0;
291
  }
292
 
293
+ .post-type-frm_display .frm_nav_bar .frm-header-logo,
 
294
  .frm_page_container .frm-header-logo {
295
  margin: 13px 0 0;
296
  }
397
  color: var(--grey);
398
  }
399
 
400
+ .post-type-frm_display #frm_top_bar h1,
401
  .frm_wrap #frm_top_bar h1 {
402
  font-size: 22px;
403
  font-weight: 400;
408
  line-height: 1.4;
409
  }
410
 
411
+ .post-type-frm_display #frm_top_bar.frm_nav_bar h1,
 
412
  .frm_page_container #frm_top_bar h1 {
413
  margin: 0 15px;
414
  padding: 20px 0 0;
417
  line-height: 1.16;
418
  }
419
 
420
+ .post-type-frm_display #frm_top_bar.frm_nav_bar h1 span,
 
421
  .frm_page_container #frm_top_bar h1 span {
422
  font-size: 19px;
423
  max-width: 175px;
3345
  margin-right: 5px;
3346
  }
3347
 
3348
+ .frm_single_entry_page .with_frm_style .frm_radio input[type=radio] {
3349
  margin: 5px 0;
3350
  width: 18px;
3351
  position: relative; /* override Bootstrap */
3352
  }
3353
 
3354
+ .frm_single_entry_page .with_frm_style .frm_radio input[type=radio]:before {
3355
  position: relative !important;
3356
  left: calc(50% - 6px);
3357
  top: calc(50% - 6px);
3385
  max-width: calc(100% - 100px);
3386
  }
3387
 
 
 
 
 
3388
  .frm-drag-fade {
3389
  background-color: var(--lightest-grey) !important;
3390
  border-radius: 4px;
7423
 
7424
  /* Custom rules */
7425
  z-index: 9999999;
7426
+ pointer-events: none;
7427
  }
7428
 
7429
  .tooltip.show {
8093
  margin: 5px 0;
8094
  }
8095
 
8096
+ .post-type-frm_display #frm_top_bar.frm-nav-bar h1,
8097
  .frm_page_container #frm_top_bar h1 {
8098
  width: auto;
8099
  max-width: 200px;
8237
  width: 100%;
8238
  }
8239
 
8240
+ .with_frm_style .frm_radio input[type=radio],
 
 
8241
  .with_frm_style .frm_checkbox input[type=checkbox] {
8242
  width: 25px !important;
8243
  }
8244
 
8245
+ .frm_single_entry_page .with_frm_style .frm_radio input[type=radio],
8246
+ .frm_single_entry_page .with_frm_style .frm_checkbox input[type=checkbox] {
8247
+ width: 18px !important;
8248
+ }
8249
+
8250
  .wp-list-table.toplevel_page_formidable .column-entries,
8251
  .wp-list-table.toplevel_page_formidable .column-form_key,
8252
  .wp-list-table.toplevel_page_formidable .column-shortcode,
8516
  }
8517
  }
8518
 
8519
+ .frm-admin-page-styles #frm-publishing #save_menu_header,
8520
+ .frm-admin-page-styles2 #frm-publishing #save_menu_header {
8521
  display: inline-block;
8522
  }
8523
 
js/formidable.js CHANGED
@@ -48,6 +48,32 @@ function frmFrontFormJS() {
48
  }
49
  }
50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  /* Get the ID of the field that changed*/
52
  function getFieldId( field, fullID ) {
53
  var nameParts, fieldId,
@@ -136,7 +162,7 @@ function frmFrontFormJS() {
136
  * @since 2.03.02
137
  *
138
  * @param {object} $form
139
- */
140
  function disableSubmitButton( $form ) {
141
  $form.find( 'input[type="submit"], input[type="button"], button[type="submit"]' ).attr( 'disabled', 'disabled' );
142
  }
@@ -147,7 +173,7 @@ function frmFrontFormJS() {
147
  * @since 2.03.02
148
  *
149
  * @param {object} $form
150
- */
151
  function enableSubmitButton( $form ) {
152
  $form.find( 'input[type="submit"], input[type="button"], button[type="submit"]' ).prop( 'disabled', false );
153
  }
@@ -196,21 +222,8 @@ function frmFrontFormJS() {
196
  if ( fields.length ) {
197
  for ( n = 0, nl = fields.length; n < nl; n++ ) {
198
  field = fields[n];
199
- value = field.value;
200
- if ( value !== '' ) {
201
- if ( field.type === 'hidden' ) {
202
- // don't validate
203
- } else if ( field.type === 'number' ) {
204
- errors = checkNumberField( field, errors );
205
- } else if ( field.type === 'email' ) {
206
- errors = checkEmailField( field, errors );
207
- } else if ( field.type === 'password' ) {
208
- errors = checkPasswordField( field, errors );
209
- } else if ( field.type === 'url' ) {
210
- errors = checkUrlField( field, errors );
211
- } else if ( field.pattern !== null ) {
212
- errors = checkPatternField( field, errors );
213
- }
214
  }
215
  }
216
  }
@@ -259,17 +272,7 @@ function frmFrontFormJS() {
259
  }
260
 
261
  if ( errors.length < 1 ) {
262
- if ( field.type === 'email' ) {
263
- errors = checkEmailField( field, errors );
264
- } else if ( field.type === 'password' ) {
265
- errors = checkPasswordField( field, errors );
266
- } else if ( field.type === 'number' ) {
267
- errors = checkNumberField( field, errors );
268
- } else if ( field.type === 'url' ) {
269
- errors = checkUrlField( field, errors );
270
- } else if ( field.pattern !== null ) {
271
- errors = checkPatternField( field, errors );
272
- }
273
  }
274
 
275
  removeFieldError( $fieldCont );
@@ -280,6 +283,27 @@ function frmFrontFormJS() {
280
  }
281
  }
282
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
283
  function checkRequiredField( field, errors ) {
284
  var checkGroup, tempVal, i, placeholder,
285
  val = '',
@@ -397,7 +421,6 @@ function frmFrontFormJS() {
397
  errors[ fieldID ] = getFieldValidationMessage( field, 'data-invmsg' );
398
  }
399
  }
400
- return errors;
401
  }
402
 
403
  function checkEmailField( field, errors ) {
@@ -410,12 +433,10 @@ function frmFrontFormJS() {
410
  }
411
 
412
  confirmField( field, errors );
413
- return errors;
414
  }
415
 
416
  function checkPasswordField( field, errors ) {
417
  confirmField( field, errors );
418
- return errors;
419
  }
420
 
421
  function confirmField( field, errors ) {
@@ -451,7 +472,6 @@ function frmFrontFormJS() {
451
  errors[ fieldID ] = getFieldValidationMessage( field, 'data-invmsg' );
452
  }
453
  }
454
- return errors;
455
  }
456
 
457
  function checkPatternField( field, errors ) {
@@ -468,7 +488,6 @@ function frmFrontFormJS() {
468
  }
469
  }
470
  }
471
- return errors;
472
  }
473
 
474
  function hasInvisibleRecaptcha( object ) {
@@ -557,7 +576,7 @@ function frmFrontFormJS() {
557
  }
558
 
559
  function getFormErrors( object, action ) {
560
- var fieldset, data, success, error;
561
 
562
  if ( typeof action === 'undefined' ) {
563
  jQuery( object ).find( 'input[name="frm_action"]' ).val();
@@ -566,12 +585,19 @@ function frmFrontFormJS() {
566
  fieldset = jQuery( object ).find( '.frm_form_field' );
567
  fieldset.addClass( 'frm_doing_ajax' );
568
 
569
- data = jQuery( object ).serialize() + '&action=frm_entries_' + action + '&nonce=' + frm_js.nonce;
 
570
 
571
  success = function( response ) {
572
- var formID, replaceContent, pageOrder, formReturned, contSubmit, delay,
573
- $fieldCont, key, inCollapsedSection, frmTrigger,
574
- defaultResponse = { 'content': '', 'errors': {}, 'pass': false };
 
 
 
 
 
 
575
  if ( response === null ) {
576
  response = defaultResponse;
577
  }
@@ -584,15 +610,26 @@ function frmFrontFormJS() {
584
  }
585
 
586
  if ( typeof response.redirect !== 'undefined' ) {
 
 
 
 
 
587
  jQuery( document ).trigger( 'frmBeforeFormRedirect', [ object, response ]);
588
  window.location = response.redirect;
589
  } else if ( response.content !== '' ) {
590
  // the form or success message was returned
591
 
 
 
 
 
 
592
  removeSubmitLoading( jQuery( object ) );
593
  if ( frm_js.offset != -1 ) {
594
  frmFrontForm.scrollMsg( jQuery( object ), false );
595
  }
 
596
  formID = jQuery( object ).find( 'input[name="form_id"]' ).val();
597
  response.content = response.content.replace( / frm_pro_form /g, ' frm_pro_form frm_no_hide ' );
598
  replaceContent = jQuery( object ).closest( '.frm_forms' );
@@ -1003,30 +1040,7 @@ function frmFrontFormJS() {
1003
  * Fallback functions
1004
  *********************************************/
1005
 
1006
- function addIndexOfFallbackForIE8() {
1007
- var len, from;
1008
-
1009
- if ( ! Array.prototype.indexOf ) {
1010
- Array.prototype.indexOf = function( elt /*, from*/ ) {
1011
- len = this.length >>> 0;
1012
-
1013
- from = Number( arguments[1]) || 0;
1014
- from = ( from < 0 ) ? Math.ceil( from ) : Math.floor( from );
1015
- if ( from < 0 ) {
1016
- from += len;
1017
- }
1018
-
1019
- for ( ; from < len; from++ ) {
1020
- if ( from in this && this[from] === elt ) {
1021
- return from;
1022
- }
1023
- }
1024
- return -1;
1025
- };
1026
- }
1027
- }
1028
-
1029
- function addTrimFallbackForIE8() {
1030
  if ( typeof String.prototype.trim !== 'function' ) {
1031
  String.prototype.trim = function() {
1032
  return this.replace( /^\s+|\s+$/g, '' );
@@ -1034,7 +1048,7 @@ function frmFrontFormJS() {
1034
  }
1035
  }
1036
 
1037
- function addFilterFallbackForIE8() {
1038
  var t, len, res, thisp, i, val;
1039
 
1040
  if ( ! Array.prototype.filter ) {
@@ -1067,24 +1081,6 @@ function frmFrontFormJS() {
1067
  }
1068
  }
1069
 
1070
- function addKeysFallbackForIE8() {
1071
- var keys, i;
1072
-
1073
- if ( ! Object.keys ) {
1074
- Object.keys = function( obj ) {
1075
- keys = [];
1076
-
1077
- for ( i in obj ) {
1078
- if ( obj.hasOwnProperty( i ) ) {
1079
- keys.push( i );
1080
- }
1081
- }
1082
-
1083
- return keys;
1084
- };
1085
- }
1086
- }
1087
-
1088
  /**
1089
  * Check for -webkit-box-shadow css value for input:-webkit-autofill selector.
1090
  * If this is a match, the User is autofilling the input on a Webkit browser.
@@ -1097,6 +1093,36 @@ function frmFrontFormJS() {
1097
  }
1098
  }
1099
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1100
  /**
1101
  * Focus on the first sub field when clicking to the primary label of combo field.
1102
  *
@@ -1341,6 +1367,7 @@ function frmFrontFormJS() {
1341
  jQuery( document ).on( 'change', '.frm-show-form input[name^="item_meta"], .frm-show-form select[name^="item_meta"], .frm-show-form textarea[name^="item_meta"]', frmFrontForm.fieldValueChanged );
1342
 
1343
  jQuery( document ).on( 'change', '[id^=frm_email_]', onHoneypotFieldChange );
 
1344
 
1345
  jQuery( document ).on( 'click', 'a[data-frmconfirm]', confirmClick );
1346
  jQuery( 'a[data-frmtoggle]' ).on( 'click', toggleDiv );
@@ -1350,11 +1377,9 @@ function frmFrontFormJS() {
1350
  // Focus on the first sub field when clicking to the primary label of combo field.
1351
  changeFocusWhenClickComboFieldLabel();
1352
 
1353
- // Add fallbacks for the beloved IE8
1354
- addIndexOfFallbackForIE8();
1355
- addTrimFallbackForIE8();
1356
- addFilterFallbackForIE8();
1357
- addKeysFallbackForIE8();
1358
 
1359
  initFloatingLabels();
1360
  },
@@ -1541,10 +1566,10 @@ function frmFrontFormJS() {
1541
  removeSubmitLoading( $object, enable, processesRunning );
1542
  },
1543
 
1544
- scrollToID: function( id ) {
1545
- var object = jQuery( document.getElementById( id ) );
1546
- frmFrontForm.scrollMsg( object, false );
1547
- },
1548
 
1549
  scrollMsg: function( id, object, animate ) {
1550
  var newPos, m, b, screenTop, screenBottom,
48
  }
49
  }
50
 
51
+ /**
52
+ * Triggers custom JS event.
53
+ *
54
+ * @since 5.x
55
+ *
56
+ * @param {HTMLElement} el The HTML element.
57
+ * @param {String} eventName Event name.
58
+ * @param {mixed} data The passed data.
59
+ */
60
+ function triggerCustomEvent( el, eventName, data ) {
61
+ var event;
62
+
63
+ if ( typeof window.CustomEvent === 'function' ) {
64
+ event = new CustomEvent( eventName );
65
+ } else if ( document.createEvent ) {
66
+ event = document.createEvent( 'HTMLEvents' );
67
+ event.initEvent( eventName, false, true );
68
+ } else {
69
+ return;
70
+ }
71
+
72
+ event.frmData = data;
73
+
74
+ el.dispatchEvent( event );
75
+ }
76
+
77
  /* Get the ID of the field that changed*/
78
  function getFieldId( field, fullID ) {
79
  var nameParts, fieldId,
162
  * @since 2.03.02
163
  *
164
  * @param {object} $form
165
+ */
166
  function disableSubmitButton( $form ) {
167
  $form.find( 'input[type="submit"], input[type="button"], button[type="submit"]' ).attr( 'disabled', 'disabled' );
168
  }
173
  * @since 2.03.02
174
  *
175
  * @param {object} $form
176
+ */
177
  function enableSubmitButton( $form ) {
178
  $form.find( 'input[type="submit"], input[type="button"], button[type="submit"]' ).prop( 'disabled', false );
179
  }
222
  if ( fields.length ) {
223
  for ( n = 0, nl = fields.length; n < nl; n++ ) {
224
  field = fields[n];
225
+ if ( '' !== field.value ) {
226
+ validateFieldValue( field, errors );
 
 
 
 
 
 
 
 
 
 
 
 
 
227
  }
228
  }
229
  }
272
  }
273
 
274
  if ( errors.length < 1 ) {
275
+ validateFieldValue( field, errors );
 
 
 
 
 
 
 
 
 
 
276
  }
277
 
278
  removeFieldError( $fieldCont );
283
  }
284
  }
285
 
286
+ function validateFieldValue( field, errors ) {
287
+ if ( field.type === 'hidden' ) {
288
+ // don't validate
289
+ } else if ( field.type === 'number' ) {
290
+ checkNumberField( field, errors );
291
+ } else if ( field.type === 'email' ) {
292
+ checkEmailField( field, errors );
293
+ } else if ( field.type === 'password' ) {
294
+ checkPasswordField( field, errors );
295
+ } else if ( field.type === 'url' ) {
296
+ checkUrlField( field, errors );
297
+ } else if ( field.pattern !== null ) {
298
+ checkPatternField( field, errors );
299
+ }
300
+
301
+ triggerCustomEvent( document, 'frm_validate_field_value', {
302
+ field: field,
303
+ errors: errors
304
+ });
305
+ }
306
+
307
  function checkRequiredField( field, errors ) {
308
  var checkGroup, tempVal, i, placeholder,
309
  val = '',
421
  errors[ fieldID ] = getFieldValidationMessage( field, 'data-invmsg' );
422
  }
423
  }
 
424
  }
425
 
426
  function checkEmailField( field, errors ) {
433
  }
434
 
435
  confirmField( field, errors );
 
436
  }
437
 
438
  function checkPasswordField( field, errors ) {
439
  confirmField( field, errors );
 
440
  }
441
 
442
  function confirmField( field, errors ) {
472
  errors[ fieldID ] = getFieldValidationMessage( field, 'data-invmsg' );
473
  }
474
  }
 
475
  }
476
 
477
  function checkPatternField( field, errors ) {
488
  }
489
  }
490
  }
 
491
  }
492
 
493
  function hasInvisibleRecaptcha( object ) {
576
  }
577
 
578
  function getFormErrors( object, action ) {
579
+ var fieldset, data, success, error, shouldTriggerEvent;
580
 
581
  if ( typeof action === 'undefined' ) {
582
  jQuery( object ).find( 'input[name="frm_action"]' ).val();
585
  fieldset = jQuery( object ).find( '.frm_form_field' );
586
  fieldset.addClass( 'frm_doing_ajax' );
587
 
588
+ data = jQuery( object ).serialize() + '&action=frm_entries_' + action + '&nonce=' + frm_js.nonce;
589
+ shouldTriggerEvent = object.classList.contains( 'frm_trigger_event_on_submit' );
590
 
591
  success = function( response ) {
592
+ var defaultResponse, formID, replaceContent, pageOrder, formReturned, contSubmit, delay,
593
+ $fieldCont, key, inCollapsedSection, frmTrigger;
594
+
595
+ defaultResponse = {
596
+ content: '',
597
+ errors: {},
598
+ pass: false
599
+ };
600
+
601
  if ( response === null ) {
602
  response = defaultResponse;
603
  }
610
  }
611
 
612
  if ( typeof response.redirect !== 'undefined' ) {
613
+ if ( shouldTriggerEvent ) {
614
+ triggerCustomEvent( object, 'frmSubmitEvent' );
615
+ return;
616
+ }
617
+
618
  jQuery( document ).trigger( 'frmBeforeFormRedirect', [ object, response ]);
619
  window.location = response.redirect;
620
  } else if ( response.content !== '' ) {
621
  // the form or success message was returned
622
 
623
+ if ( shouldTriggerEvent ) {
624
+ triggerCustomEvent( object, 'frmSubmitEvent' );
625
+ return;
626
+ }
627
+
628
  removeSubmitLoading( jQuery( object ) );
629
  if ( frm_js.offset != -1 ) {
630
  frmFrontForm.scrollMsg( jQuery( object ), false );
631
  }
632
+
633
  formID = jQuery( object ).find( 'input[name="form_id"]' ).val();
634
  response.content = response.content.replace( / frm_pro_form /g, ' frm_pro_form frm_no_hide ' );
635
  replaceContent = jQuery( object ).closest( '.frm_forms' );
1040
  * Fallback functions
1041
  *********************************************/
1042
 
1043
+ function addTrimFallbackForIE() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1044
  if ( typeof String.prototype.trim !== 'function' ) {
1045
  String.prototype.trim = function() {
1046
  return this.replace( /^\s+|\s+$/g, '' );
1048
  }
1049
  }
1050
 
1051
+ function addFilterFallbackForIE() {
1052
  var t, len, res, thisp, i, val;
1053
 
1054
  if ( ! Array.prototype.filter ) {
1081
  }
1082
  }
1083
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1084
  /**
1085
  * Check for -webkit-box-shadow css value for input:-webkit-autofill selector.
1086
  * If this is a match, the User is autofilling the input on a Webkit browser.
1093
  }
1094
  }
1095
 
1096
+ function maybeMakeHoneypotFieldsUntabbable() {
1097
+ document.addEventListener( 'keydown', handleKeyUp );
1098
+
1099
+ function handleKeyUp( event ) {
1100
+ var code;
1101
+
1102
+ if ( 'undefined' !== typeof event.key ) {
1103
+ code = event.key;
1104
+ } else if ( 'undefined' !== typeof event.keyCode && 9 === event.keyCode ) {
1105
+ code = 'Tab';
1106
+ }
1107
+
1108
+ if ( 'Tab' === code ) {
1109
+ makeHoneypotFieldsUntabbable();
1110
+ document.removeEventListener( 'keydown', handleKeyUp );
1111
+ }
1112
+ }
1113
+
1114
+ function makeHoneypotFieldsUntabbable() {
1115
+ document.querySelectorAll( '.frm_verify' ).forEach(
1116
+ function( wrapper ) {
1117
+ var input = wrapper.querySelector( 'input[id^=frm_email]' );
1118
+ if ( input ) {
1119
+ input.setAttribute( 'tabindex', -1 );
1120
+ }
1121
+ }
1122
+ );
1123
+ }
1124
+ }
1125
+
1126
  /**
1127
  * Focus on the first sub field when clicking to the primary label of combo field.
1128
  *
1367
  jQuery( document ).on( 'change', '.frm-show-form input[name^="item_meta"], .frm-show-form select[name^="item_meta"], .frm-show-form textarea[name^="item_meta"]', frmFrontForm.fieldValueChanged );
1368
 
1369
  jQuery( document ).on( 'change', '[id^=frm_email_]', onHoneypotFieldChange );
1370
+ maybeMakeHoneypotFieldsUntabbable();
1371
 
1372
  jQuery( document ).on( 'click', 'a[data-frmconfirm]', confirmClick );
1373
  jQuery( 'a[data-frmtoggle]' ).on( 'click', toggleDiv );
1377
  // Focus on the first sub field when clicking to the primary label of combo field.
1378
  changeFocusWhenClickComboFieldLabel();
1379
 
1380
+ // Add fallbacks for IE.
1381
+ addTrimFallbackForIE(); // Trim only works in IE10+.
1382
+ addFilterFallbackForIE(); // Filter is not supported in any version of IE.
 
 
1383
 
1384
  initFloatingLabels();
1385
  },
1566
  removeSubmitLoading( $object, enable, processesRunning );
1567
  },
1568
 
1569
+ scrollToID: function( id ) {
1570
+ var object = jQuery( document.getElementById( id ) );
1571
+ frmFrontForm.scrollMsg( object, false );
1572
+ },
1573
 
1574
  scrollMsg: function( id, object, animate ) {
1575
  var newPos, m, b, screenTop, screenBottom,
js/formidable_admin.js CHANGED
@@ -335,7 +335,7 @@ function frmAdminBuildJS() {
335
  lastNewActionIdReturned = 0;
336
 
337
  const { __ } = wp.i18n;
338
- let debouncedSyncAfterDragAndDrop;
339
 
340
  if ( thisForm !== null ) {
341
  thisFormId = thisForm.value;
@@ -882,6 +882,7 @@ function frmAdminBuildJS() {
882
  start: handleDragStart,
883
  stop: handleDragStop,
884
  drag: handleDrag,
 
885
  cursorAt: {
886
  top: 0,
887
  left: 90 // The width of draggable button is 180. 90 should center the draggable on the cursor.
@@ -931,11 +932,12 @@ function frmAdminBuildJS() {
931
  }
932
 
933
  function handleDragStart( event, ui ) {
934
- const container = document.getElementById( 'post-body-content' );
935
  container.classList.add( 'frm-dragging-field' );
936
 
937
  document.body.classList.add( 'frm-dragging' );
938
  ui.helper.addClass( 'frm-sortable-helper' );
 
939
 
940
  event.target.classList.add( 'frm-drag-fade' );
941
 
@@ -947,7 +949,7 @@ function frmAdminBuildJS() {
947
  }
948
 
949
  function handleDragStop() {
950
- const container = document.getElementById( 'post-body-content' );
951
  container.classList.remove( 'frm-dragging-field' );
952
  document.body.classList.remove( 'frm-dragging' );
953
 
@@ -957,7 +959,7 @@ function frmAdminBuildJS() {
957
  }
958
  }
959
 
960
- function handleDrag( event ) {
961
  const draggable = event.target;
962
  const droppable = getDroppableTarget();
963
 
@@ -977,6 +979,9 @@ function frmAdminBuildJS() {
977
  });
978
  }
979
 
 
 
 
980
  if ( 'frm-show-fields' === droppable.id || droppable.classList.contains( 'start_divider' ) ) {
981
  placeholder.style.left = 0;
982
  handleDragOverYAxis({ droppable, y: event.clientY, placeholder });
@@ -987,6 +992,10 @@ function frmAdminBuildJS() {
987
  handleDragOverFieldGroup({ droppable, x: event.clientX, placeholder });
988
  }
989
 
 
 
 
 
990
  function getDroppableTarget() {
991
  let droppable = document.getElementById( 'frm-show-fields' );
992
  while ( droppable.querySelector( '.frm-over-droppable' ) ) {
@@ -1717,6 +1726,7 @@ function frmAdminBuildJS() {
1717
  }
1718
 
1719
  // Don't allow a new page break or hidden field in a field group.
 
1720
  // Don't allow a new section inside of a section.
1721
  // Don't allow an embedded form in a section.
1722
  function allowNewFieldDrop( draggable, droppable ) {
@@ -1726,6 +1736,16 @@ function frmAdminBuildJS() {
1726
  const newSectionField = classes.contains( 'frm_tdivider' );
1727
  const newEmbedField = classes.contains( 'frm_tform' );
1728
 
 
 
 
 
 
 
 
 
 
 
1729
  const fieldTypeIsAlwaysAllowed = ! newPageBreakField && ! newHiddenField && ! newSectionField && ! newEmbedField;
1730
  if ( fieldTypeIsAlwaysAllowed ) {
1731
  return true;
@@ -1737,11 +1757,6 @@ function frmAdminBuildJS() {
1737
  return ! newEmbedField && ! newSectionField;
1738
  }
1739
 
1740
- const newFieldWillBeAddedToAGroup = ! ( 'frm-show-fields' === droppable.id || droppable.classList.contains( 'start_divider' ) );
1741
- if ( newFieldWillBeAddedToAGroup ) {
1742
- return ! newHiddenField && ! newPageBreakField;
1743
- }
1744
-
1745
  return true;
1746
  }
1747
 
@@ -1760,6 +1775,12 @@ function frmAdminBuildJS() {
1760
  return allowMoveFieldToSection( draggable );
1761
  }
1762
 
 
 
 
 
 
 
1763
  return allowMoveFieldToGroup( draggable, droppable );
1764
  }
1765
 
@@ -1792,8 +1813,7 @@ function frmAdminBuildJS() {
1792
  }
1793
 
1794
  function allowMoveFieldToGroup( draggable, group ) {
1795
- const groupIncludesBreakOrHidden = null !== group.querySelector( '.edit_field_type_break, .edit_field_type_hidden' );
1796
- if ( groupIncludesBreakOrHidden ) {
1797
  // Never allow any field beside a page break or a hidden field.
1798
  return false;
1799
  }
@@ -1815,6 +1835,10 @@ function frmAdminBuildJS() {
1815
  return true;
1816
  }
1817
 
 
 
 
 
1818
  function groupCanFitAnotherField( fieldsInRow, $field ) {
1819
  var fieldId;
1820
  if ( fieldsInRow.length < 6 ) {
@@ -2029,6 +2053,7 @@ function frmAdminBuildJS() {
2029
  updateFieldOrder();
2030
  afterAddField( msg, false );
2031
  maybeDuplicateUnsavedSettings( fieldId, msg );
 
2032
  }
2033
  });
2034
  return false;
@@ -2143,7 +2168,7 @@ function frmAdminBuildJS() {
2143
  function checkForActiveHoverTarget( event ) {
2144
  var container, elementFromPoint, list, previousHoverTarget;
2145
 
2146
- container = document.getElementById( 'post-body-content' );
2147
  if ( container.classList.contains( 'frm-dragging-field' ) ) {
2148
  return;
2149
  }
@@ -3469,41 +3494,43 @@ function frmAdminBuildJS() {
3469
  }
3470
 
3471
  function duplicateFieldGroup() {
3472
- var hoverTarget, newRowId, $newRow, $fields, syncDetails, expectedLength, duplicatedCount, originalFieldIdByDuplicatedFieldId, injectedCloneOptions;
3473
-
3474
- hoverTarget = document.querySelector( '.frm-field-group-hover-target' );
3475
-
3476
  if ( null === hoverTarget ) {
3477
  return;
3478
  }
3479
 
3480
- newRowId = 'frm_field_group_' + getAutoId();
3481
- $newRow = wrapFieldLi( '' );
3482
- $newRowUl = $newRow.find( 'ul' );
3483
- $newRowUl.attr( 'id', newRowId );
3484
- $newRow.addClass( 'frm_hidden' );
3485
- jQuery( hoverTarget ).closest( 'li.frm_field_box' ).after( $newRow );
3486
 
3487
- $fields = getFieldsInRow( jQuery( hoverTarget ) );
3488
- syncDetails = [];
3489
- injectedCloneOptions = [];
3490
 
3491
- expectedLength = $fields.length;
3492
- duplicatedCount = 0;
3493
- originalFieldIdByDuplicatedFieldId = {};
3494
 
3495
- $newRow.on(
3496
- 'frm_added_duplicated_field_to_row',
3497
- function( event, args ) {
3498
- var $duplicatedFields, index;
 
 
 
 
 
 
3499
 
 
 
 
3500
  originalFieldIdByDuplicatedFieldId[ jQuery( args.duplicatedFieldHtml ).attr( 'data-fid' ) ] = args.originalFieldId;
3501
 
3502
  if ( expectedLength > ++duplicatedCount ) {
3503
  return;
3504
  }
3505
 
3506
- $duplicatedFields = getFieldsInRow( $newRowUl );
 
3507
 
3508
  injectedCloneOptions.forEach(
3509
  function( cloneOption ) {
@@ -3511,12 +3538,12 @@ function frmAdminBuildJS() {
3511
  }
3512
  );
3513
 
3514
- for ( index = 0; index < expectedLength; ++index ) {
3515
  $newRowUl.append( $newRowUl.children( 'li.form-field[frm-field-order="' + index + '"]' ) );
3516
  }
3517
 
3518
  syncLayoutClasses( $duplicatedFields.first(), syncDetails );
3519
- $newRow.removeClass( 'frm_hidden' );
3520
  updateFieldOrder();
3521
 
3522
  getFieldsInRow( $newRowUl ).each(
@@ -6748,7 +6775,7 @@ function frmAdminBuildJS() {
6748
  if ( jQuery( this ).val() === v && this.name !== $t.name ) {
6749
  this.style.borderColor = 'red';
6750
  jQuery( $t ).val( '' );
6751
- infoModal( 'Oops. You have already used that field.' );
6752
  return false;
6753
  }
6754
  });
@@ -7773,6 +7800,13 @@ function frmAdminBuildJS() {
7773
  }
7774
 
7775
  function onActionLoaded( event ) {
 
 
 
 
 
 
 
7776
  const settings = event.target.closest( '.frm_form_action_settings' );
7777
  if ( settings && settings.classList.contains( 'frm_single_email_settings' ) ) {
7778
  onEmailActionLoaded( settings );
@@ -9634,6 +9668,7 @@ function frmAdminBuildJS() {
9634
  let loadFieldId, $builderForm, builderArea;
9635
 
9636
  debouncedSyncAfterDragAndDrop = debounce( syncAfterDragAndDrop, 10 );
 
9637
 
9638
  if ( jQuery( '.frm_field_loading' ).length ) {
9639
  loadFieldId = jQuery( '.frm_field_loading' ).first().attr( 'id' );
335
  lastNewActionIdReturned = 0;
336
 
337
  const { __ } = wp.i18n;
338
+ let debouncedSyncAfterDragAndDrop, postBodyContent;
339
 
340
  if ( thisForm !== null ) {
341
  thisFormId = thisForm.value;
882
  start: handleDragStart,
883
  stop: handleDragStop,
884
  drag: handleDrag,
885
+ cursor: 'grabbing',
886
  cursorAt: {
887
  top: 0,
888
  left: 90 // The width of draggable button is 180. 90 should center the draggable on the cursor.
932
  }
933
 
934
  function handleDragStart( event, ui ) {
935
+ const container = postBodyContent;
936
  container.classList.add( 'frm-dragging-field' );
937
 
938
  document.body.classList.add( 'frm-dragging' );
939
  ui.helper.addClass( 'frm-sortable-helper' );
940
+ ui.helper.initialOffset = container.scrollTop;
941
 
942
  event.target.classList.add( 'frm-drag-fade' );
943
 
949
  }
950
 
951
  function handleDragStop() {
952
+ const container = postBodyContent;
953
  container.classList.remove( 'frm-dragging-field' );
954
  document.body.classList.remove( 'frm-dragging' );
955
 
959
  }
960
  }
961
 
962
+ function handleDrag( event, ui ) {
963
  const draggable = event.target;
964
  const droppable = getDroppableTarget();
965
 
979
  });
980
  }
981
 
982
+ // Sync the y position of the draggable so it still follows the cursor after scrolling up and down the field list.
983
+ ui.helper.get( 0 ).style.transform = 'translateY(' + getDragOffset( ui.helper ) + 'px)';
984
+
985
  if ( 'frm-show-fields' === droppable.id || droppable.classList.contains( 'start_divider' ) ) {
986
  placeholder.style.left = 0;
987
  handleDragOverYAxis({ droppable, y: event.clientY, placeholder });
992
  handleDragOverFieldGroup({ droppable, x: event.clientX, placeholder });
993
  }
994
 
995
+ function getDragOffset( $helper ) {
996
+ return postBodyContent.scrollTop - $helper.initialOffset;
997
+ }
998
+
999
  function getDroppableTarget() {
1000
  let droppable = document.getElementById( 'frm-show-fields' );
1001
  while ( droppable.querySelector( '.frm-over-droppable' ) ) {
1726
  }
1727
 
1728
  // Don't allow a new page break or hidden field in a field group.
1729
+ // Don't allow a new field into a field group that includes a page break or hidden field.
1730
  // Don't allow a new section inside of a section.
1731
  // Don't allow an embedded form in a section.
1732
  function allowNewFieldDrop( draggable, droppable ) {
1736
  const newSectionField = classes.contains( 'frm_tdivider' );
1737
  const newEmbedField = classes.contains( 'frm_tform' );
1738
 
1739
+ const newFieldWillBeAddedToAGroup = ! ( 'frm-show-fields' === droppable.id || droppable.classList.contains( 'start_divider' ) );
1740
+ if ( newFieldWillBeAddedToAGroup ) {
1741
+ if ( groupIncludesBreakOrHidden( droppable ) ) {
1742
+ // Never allow any field beside a page break or a hidden field.
1743
+ return false;
1744
+ }
1745
+
1746
+ return ! newHiddenField && ! newPageBreakField;
1747
+ }
1748
+
1749
  const fieldTypeIsAlwaysAllowed = ! newPageBreakField && ! newHiddenField && ! newSectionField && ! newEmbedField;
1750
  if ( fieldTypeIsAlwaysAllowed ) {
1751
  return true;
1757
  return ! newEmbedField && ! newSectionField;
1758
  }
1759
 
 
 
 
 
 
1760
  return true;
1761
  }
1762
 
1775
  return allowMoveFieldToSection( draggable );
1776
  }
1777
 
1778
+ const isHiddenField = draggable.classList.contains( 'edit_field_type_hidden' );
1779
+ if ( isHiddenField ) {
1780
+ // Hidden fields should not be added to field groups since they're not shown and don't make sense with the grid distribution.
1781
+ return false;
1782
+ }
1783
+
1784
  return allowMoveFieldToGroup( draggable, droppable );
1785
  }
1786
 
1813
  }
1814
 
1815
  function allowMoveFieldToGroup( draggable, group ) {
1816
+ if ( groupIncludesBreakOrHidden( group ) ) {
 
1817
  // Never allow any field beside a page break or a hidden field.
1818
  return false;
1819
  }
1835
  return true;
1836
  }
1837
 
1838
+ function groupIncludesBreakOrHidden( group ) {
1839
+ return null !== group.querySelector( '.edit_field_type_break, .edit_field_type_hidden' );
1840
+ }
1841
+
1842
  function groupCanFitAnotherField( fieldsInRow, $field ) {
1843
  var fieldId;
1844
  if ( fieldsInRow.length < 6 ) {
2053
  updateFieldOrder();
2054
  afterAddField( msg, false );
2055
  maybeDuplicateUnsavedSettings( fieldId, msg );
2056
+ toggleOneSectionHolder( replaceWith.find( '.start_divider' ) );
2057
  }
2058
  });
2059
  return false;
2168
  function checkForActiveHoverTarget( event ) {
2169
  var container, elementFromPoint, list, previousHoverTarget;
2170
 
2171
+ container = postBodyContent;
2172
  if ( container.classList.contains( 'frm-dragging-field' ) ) {
2173
  return;
2174
  }
3494
  }
3495
 
3496
  function duplicateFieldGroup() {
3497
+ const hoverTarget = document.querySelector( '.frm-field-group-hover-target' );
 
 
 
3498
  if ( null === hoverTarget ) {
3499
  return;
3500
  }
3501
 
3502
+ const newRowId = 'frm_field_group_' + getAutoId();
3503
+ const placeholderUlChild = document.createTextNode( '' );
3504
+ wrapFieldLiInPlace( placeholderUlChild );
 
 
 
3505
 
3506
+ const newRow = jQuery( placeholderUlChild ).closest( 'li' ).get( 0 );
3507
+ newRow.classList.add( 'frm_hidden' );
 
3508
 
3509
+ const newRowUl = newRow.querySelector( 'ul' );
3510
+ newRowUl.id = newRowId;
 
3511
 
3512
+ jQuery( hoverTarget.closest( 'li.frm_field_box' ) ).after( newRow );
3513
+
3514
+ const $fields = getFieldsInRow( jQuery( hoverTarget ) );
3515
+ const syncDetails = [];
3516
+ const injectedCloneOptions = [];
3517
+
3518
+ const expectedLength = $fields.length;
3519
+ const originalFieldIdByDuplicatedFieldId = {};
3520
+
3521
+ let duplicatedCount = 0;
3522
 
3523
+ jQuery( newRow ).on(
3524
+ 'frm_added_duplicated_field_to_row',
3525
+ function( _, args ) {
3526
  originalFieldIdByDuplicatedFieldId[ jQuery( args.duplicatedFieldHtml ).attr( 'data-fid' ) ] = args.originalFieldId;
3527
 
3528
  if ( expectedLength > ++duplicatedCount ) {
3529
  return;
3530
  }
3531
 
3532
+ const $newRowUl = jQuery( newRowUl );
3533
+ const $duplicatedFields = getFieldsInRow( $newRowUl );
3534
 
3535
  injectedCloneOptions.forEach(
3536
  function( cloneOption ) {
3538
  }
3539
  );
3540
 
3541
+ for ( let index = 0; index < expectedLength; ++index ) {
3542
  $newRowUl.append( $newRowUl.children( 'li.form-field[frm-field-order="' + index + '"]' ) );
3543
  }
3544
 
3545
  syncLayoutClasses( $duplicatedFields.first(), syncDetails );
3546
+ newRow.classList.remove( 'frm_hidden' );
3547
  updateFieldOrder();
3548
 
3549
  getFieldsInRow( $newRowUl ).each(
6775
  if ( jQuery( this ).val() === v && this.name !== $t.name ) {
6776
  this.style.borderColor = 'red';
6777
  jQuery( $t ).val( '' );
6778
+ infoModal( frm_admin_js.field_already_used );
6779
  return false;
6780
  }
6781
  });
7800
  }
7801
 
7802
  function onActionLoaded( event ) {
7803
+ event.target.closest( '.frm_form_action_settings' ).querySelectorAll( '.frmsvg.frm-show-box' ).forEach( ( svg ) => {
7804
+ if ( svg.nextElementSibling.type === 'text' ) {
7805
+ svg.style.bottom = '-3px';
7806
+ svg.style.marginRight = '0';
7807
+ }
7808
+ });
7809
+
7810
  const settings = event.target.closest( '.frm_form_action_settings' );
7811
  if ( settings && settings.classList.contains( 'frm_single_email_settings' ) ) {
7812
  onEmailActionLoaded( settings );
9668
  let loadFieldId, $builderForm, builderArea;
9669
 
9670
  debouncedSyncAfterDragAndDrop = debounce( syncAfterDragAndDrop, 10 );
9671
+ postBodyContent = document.getElementById( 'post-body-content' );
9672
 
9673
  if ( jQuery( '.frm_field_loading' ).length ) {
9674
  loadFieldId = jQuery( '.frm_field_loading' ).first().attr( 'id' );
readme.txt CHANGED
@@ -3,9 +3,9 @@ Plugin Name: Formidable Forms - Contact Form, Survey & Quiz Form Builder for Wor
3
  Contributors: formidableforms, sswells, srwells
4
  Tags: forms, form builder, survey, free, custom form, contact form, form maker, form creator, paypal form, paypal, stripe, stripe form, aweber, aweber form, getresponse, calculator, quote form, contact button, form manager, Akismet, payment form, survey form, donation form, email subscription, user registration form, wordpress registration, wordpress login form, constant contact, mailpoet, active campaign, salesforce, hubspot, campaign monitor, quiz builder, quiz, feedback form, drag and drop, mailchimp form
5
  Requires at least: 5.2
6
- Tested up to: 6.0.2
7
  Requires PHP: 5.6
8
- Stable tag: 5.5.2
9
 
10
  The most advanced WordPress forms plugin. Go beyond contact forms with our drag and drop form builder for surveys, quizzes, and more.
11
 
@@ -440,6 +440,23 @@ Using our Zapier integration, you can easily connect your website with over 1000
440
  See all <a href="https://zapier.com/apps/formidable/integrations">Formidable Zapier Integrations</a>.
441
 
442
  == Changelog ==
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
443
  = 5.5.2 =
444
  * New: When dragging a field or field group, a smaller drag helper will be used that is more consistent with the field type options in the sidebar, and the field that is being dragged will gray out.
445
  * New: Improved error handling when installing templates from XML. A message will be shown when the simple XML extension is not installed, and errors will now be shown in a pop up when a template falls to install.
@@ -461,10 +478,10 @@ See all <a href="https://zapier.com/apps/formidable/integrations">Formidable Zap
461
  * New: Email actions now use a rich text editor.
462
  * New: Added new frm_before_title, frm_before_submit_btn, and frm_after_submit_btn actions.
463
  * New: Image URLs used in options for radio and checkbox fields will now be included in XML exports, and used on import when the option to import files is on.
464
- * Fix: Prevent a bug that would sometimes cause a form to repeat when previewing in-theme.
465
  * Fix: Shortcode popup will now appear below textareas to avoid visibility issues with overlapping over content.
466
- * Fix: Prevent a fatal error in PHP8 where a field's options data is in an unsupported format.
467
- * Fix: An entry with a name longer than 255 characters long would throw an error and never submit. It will now be truncated to a maximum of 255 characters.
468
  * Removed icon fonts from front end CSS when only Lite is loaded to significantly reduce CSS size where it is not required.
469
  * Updated styles for back end modals.
470
 
@@ -773,4 +790,29 @@ See all <a href="https://zapier.com/apps/formidable/integrations">Formidable Zap
773
  * Tweak: Improve the admin listing pages when nothing has been created.
774
  * Fix: Update the recaptcha for better reliability to catch more spam.
775
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
776
  <a href="https://raw.githubusercontent.com/Strategy11/formidable-forms/master/changelog.txt">See changelog for all versions</a>
3
  Contributors: formidableforms, sswells, srwells
4
  Tags: forms, form builder, survey, free, custom form, contact form, form maker, form creator, paypal form, paypal, stripe, stripe form, aweber, aweber form, getresponse, calculator, quote form, contact button, form manager, Akismet, payment form, survey form, donation form, email subscription, user registration form, wordpress registration, wordpress login form, constant contact, mailpoet, active campaign, salesforce, hubspot, campaign monitor, quiz builder, quiz, feedback form, drag and drop, mailchimp form
5
  Requires at least: 5.2
6
+ Tested up to: 6.1
7
  Requires PHP: 5.6
8
+ Stable tag: 5.5.3
9
 
10
  The most advanced WordPress forms plugin. Go beyond contact forms with our drag and drop form builder for surveys, quizzes, and more.
11
 
440
  See all <a href="https://zapier.com/apps/formidable/integrations">Formidable Zapier Integrations</a>.
441
 
442
  == Changelog ==
443
+ = 5.5.3 =
444
+ * New: HTML emails using wpautop will now also convert line breaks into <br /> tags.
445
+ * New: Improved support for importing large XML files. Previously a file over 200MB would trigger a "parser error : internal error: Huge input lookup" error.
446
+ * Fix: When an HTML email includes a body tag, only the content of the body tag will use wpautop.
447
+ * Fix: A duplicated field group would merge into one larger field group instead of creating a second identical field group as expected.
448
+ * Fix: The "Add Fields Here" placeholder wouldn't hide after duplicating a section until after refreshing the page.
449
+ * Fix: The Screen Options tab was not hidden after duplicating an entry, causing it to overlap the update button.
450
+ * Fix: An imported view shortcode was not properly updating to its new ID value if the post containing it did not also include a [formidable] shortcode.
451
+ * Fix: Tooltips that overlap the element that triggered the tooltip would cause the tooltip to flicker on and off.
452
+ * Fix: The ellipses icon that triggers shortcode pop ups was offset incorrectly in of text fields inside of form actions.
453
+ * Fix: The update button was missing on the alternative style editor submenu link available from the WordPress themes menu.
454
+ * Fix: Honeypot fields should no longer gain focus when tabbing through fields in Chrome.
455
+ * Fix: Fields wouldn't follow the cursor as expected after scrolling the page while dragging.
456
+ * Fix: Recent styling updates were applying to radio buttons in the form builder by mistake, causing them to look incorrect.
457
+ * Front end polyfills for IE8 have been removed, reducing the size of the loaded script file.
458
+ * Added additional form builder restrictions so a hidden field and page break don't become part of a field group.
459
+
460
  = 5.5.2 =
461
  * New: When dragging a field or field group, a smaller drag helper will be used that is more consistent with the field type options in the sidebar, and the field that is being dragged will gray out.
462
  * New: Improved error handling when installing templates from XML. A message will be shown when the simple XML extension is not installed, and errors will now be shown in a pop up when a template falls to install.
478
  * New: Email actions now use a rich text editor.
479
  * New: Added new frm_before_title, frm_before_submit_btn, and frm_after_submit_btn actions.
480
  * New: Image URLs used in options for radio and checkbox fields will now be included in XML exports, and used on import when the option to import files is on.
481
+ * Fix: Prevent a bug that would sometimes cause a form to repeat 10 times when previewing in-theme.
482
  * Fix: Shortcode popup will now appear below textareas to avoid visibility issues with overlapping over content.
483
+ * Fix: Prevent a fatal error in PHP8 where a field's field options data is in an unsupported format.
484
+ * Fix: An entry with a name longer than 255 characters long would throw an error and never submit. It will now be truncated to a maximum of 255 characters instead.
485
  * Removed icon fonts from front end CSS when only Lite is loaded to significantly reduce CSS size where it is not required.
486
  * Updated styles for back end modals.
487
 
790
  * Tweak: Improve the admin listing pages when nothing has been created.
791
  * Fix: Update the recaptcha for better reliability to catch more spam.
792
 
793
+ = 4.06.03 =
794
+ * More consistent dropdown styling with multiselect dropdowns.
795
+ * Prepare the code for handling permissions options as an array of roles.
796
+ * Fix: WP 5.5 - Email subject lines were coming through encoded.
797
+ * Fix: WP 5.5 - When WP Mail SMTP was installed, the Formidable SMTP page has an error.
798
+
799
+ = 4.05.02 =
800
+ * New: Added frm_message_placement hook to show the message below the form
801
+ * New: New classes that can be used in the class setting: frm_plain_success (Removes styling from the success message) and frm_below_success (Moves the success message below).
802
+ * Add Formidable back to the admin bar. This is now a setting if the default WordPress v5.2+ behavior is desired.
803
+ * Fix: Review requests were added to the inbox too frequently for sites with multiple admins.
804
+ * Fix: Elementor conflict by using the glost $post in the admin area.
805
+ * Fix: The color picker position in the styling settings was off for some options.
806
+
807
+ = 4.05.01 =
808
+ * Fix: The entry list wasn't always showing the entries.
809
+ * Better sync between review requests in inbox and message.
810
+
811
+ = 4.05 =
812
+ * Updates to the default styling.
813
+ * New: Added an inbox as a centralized place for notices and communication.
814
+ * New: Added frm_color_block and frm_total_big classes for more beautiful forms.
815
+ * Help prevent common email issues by showing a warning in the email settings when the from and to email addresses are the same.
816
+ * Fix: Forms edited after export and reimported were losing the required indicator in some cases.
817
+
818
  <a href="https://raw.githubusercontent.com/Strategy11/formidable-forms/master/changelog.txt">See changelog for all versions</a>