Form builder to get in touch with visitors, grow your email list and collect payments — Happyforms - Version 1.5.6

Version Description

  • New feature: Forms can now show an additional Review step before final submission.
  • Improvement: Previous / Next buttons in form builder got more descriptive labels.
  • Bug fix: Number part didn't allow zero value even when 0 was set as a minimum required value.
  • Bug fix: Email part didn't allow an empty value submitted even when field was not required.
  • Bug fix: Fixes for multiple style issues across all parts in CSS.
  • Bug fix: Welcome screen appearance on RTL layouts.
  • Bug fix: Forms and Responses were appearing in public searches and queries.
Download this release

Release Info

Developer thethemefoundry
Plugin Icon 128x128 Form builder to get in touch with visitors, grow your email list and collect payments — Happyforms
Version 1.5.6
Comparing to
See all releases

Code changes from version 1.5.5 to 1.5.6

Files changed (57) hide show
  1. assets/css/admin.css +13 -6
  2. assets/css/customize.css +5 -6
  3. assets/css/frontend.css +205 -11
  4. assets/js/customize.js +24 -2
  5. assets/js/frontend.js +35 -14
  6. assets/js/lib/happyforms-select.js +173 -169
  7. assets/js/parts/part-address.js +2 -2
  8. assets/js/parts/part-checkbox.js +1 -1
  9. assets/js/parts/part-date.js +7 -5
  10. assets/js/parts/part-email.js +1 -1
  11. assets/js/parts/part-number.js +2 -2
  12. assets/js/parts/part-phone.js +9 -5
  13. assets/js/parts/part-radio.js +1 -1
  14. assets/js/parts/part-scale.js +3 -1
  15. assets/js/parts/part-select.js +8 -3
  16. assets/js/parts/part-table.js +3 -3
  17. happyforms.php +2 -2
  18. inc/classes/class-form-controller.php +89 -9
  19. inc/classes/class-message-controller.php +206 -80
  20. inc/classes/class-session.php +27 -0
  21. inc/classes/parts/class-part-address.php +16 -0
  22. inc/classes/parts/class-part-date.php +16 -0
  23. inc/classes/parts/class-part-email.php +1 -1
  24. inc/classes/parts/class-part-legal.php +12 -0
  25. inc/classes/parts/class-part-number.php +6 -2
  26. inc/helpers/helper-form-templates.php +147 -10
  27. inc/templates/customize-form-setup.php +17 -2
  28. inc/templates/customize-form-steps.php +22 -1
  29. inc/templates/partials/form-confirm-preview.php +4 -0
  30. inc/templates/partials/form-submit-preview.php +3 -0
  31. inc/templates/partials/form-submit.php +3 -0
  32. inc/templates/parts/customize-address.php +2 -2
  33. inc/templates/parts/customize-number.php +2 -2
  34. inc/templates/parts/customize-phone.php +1 -1
  35. inc/templates/parts/customize-scale.php +2 -2
  36. inc/templates/parts/frontend-address.php +11 -5
  37. inc/templates/parts/frontend-checkbox.php +7 -1
  38. inc/templates/parts/frontend-date-day.php +4 -4
  39. inc/templates/parts/frontend-date-month.php +5 -5
  40. inc/templates/parts/frontend-date.php +15 -9
  41. inc/templates/parts/frontend-email.php +8 -2
  42. inc/templates/parts/frontend-legal.php +13 -11
  43. inc/templates/parts/frontend-multi-line-text.php +7 -1
  44. inc/templates/parts/frontend-number.php +10 -4
  45. inc/templates/parts/frontend-phone.php +9 -3
  46. inc/templates/parts/frontend-placeholder.php +5 -0
  47. inc/templates/parts/frontend-radio.php +6 -1
  48. inc/templates/parts/frontend-rating.php +8 -2
  49. inc/templates/parts/frontend-scale.php +9 -5
  50. inc/templates/parts/frontend-select.php +11 -5
  51. inc/templates/parts/frontend-single-line-text.php +7 -1
  52. inc/templates/parts/frontend-table.php +12 -6
  53. inc/templates/parts/frontend-title.php +10 -4
  54. inc/templates/parts/frontend-website-url.php +7 -1
  55. inc/templates/single-form.php +2 -0
  56. languages/happyforms.pot +118 -102
  57. readme.txt +13 -1
assets/css/admin.css CHANGED
@@ -161,13 +161,14 @@ p.happyforms-message-nav span.divider:last-child {
161
  *
162
  */
163
  .happyforms-welcome-panel {
 
164
  max-width: 760px;
165
  box-sizing: border-box;
166
  position: relative;
167
  }
168
 
169
  .happyforms-welcome-panel .welcome-panel-content {
170
- width: 460px;
171
  margin-right: 33px;
172
  padding-bottom: 25px;
173
  }
@@ -183,17 +184,23 @@ p.happyforms-message-nav span.divider:last-child {
183
  }
184
 
185
  .happyforms-welcome-panel .welcome-panel-theme {
186
- position: absolute;
187
- top: 20px;
188
- right: 20px;
189
- bottom: 20px;
190
- width: 250px;
191
  background-image: url(../svg/welcome.svg);
192
  background-position: center center;
193
  background-repeat: no-repeat;
194
  background-size: contain;
195
  }
196
 
 
 
 
 
 
 
 
 
 
197
  p.welcome-panel-footer {
198
  max-width: 760px;
199
  text-align: right;
161
  *
162
  */
163
  .happyforms-welcome-panel {
164
+ display: flex;
165
  max-width: 760px;
166
  box-sizing: border-box;
167
  position: relative;
168
  }
169
 
170
  .happyforms-welcome-panel .welcome-panel-content {
171
+ max-width: 460px;
172
  margin-right: 33px;
173
  padding-bottom: 25px;
174
  }
184
  }
185
 
186
  .happyforms-welcome-panel .welcome-panel-theme {
187
+ min-width: 250px;
188
+ margin-bottom: 20px;
 
 
 
189
  background-image: url(../svg/welcome.svg);
190
  background-position: center center;
191
  background-repeat: no-repeat;
192
  background-size: contain;
193
  }
194
 
195
+ @media screen and (max-width: 960px) {
196
+ .happyforms-welcome-panel {
197
+ flex-direction: column;
198
+ }
199
+ .happyforms-welcome-panel .welcome-panel-theme {
200
+ height: 223px;
201
+ }
202
+ }
203
+
204
  p.welcome-panel-footer {
205
  max-width: 760px;
206
  text-align: right;
assets/css/customize.css CHANGED
@@ -166,12 +166,13 @@ p.description a {
166
  }
167
 
168
  .happyforms-action-buttons {
 
169
  margin-bottom: 15px;
170
  }
171
 
172
  .happyforms-action-buttons button.button-primary.button-hero,
173
  .happyforms-action-buttons button.button-secondary.button-hero {
174
- width: 48%;
175
  margin: 0 1%;
176
  padding: 0;
177
  text-align: center;
@@ -296,12 +297,10 @@ a.happyforms-form-part-remove:hover {
296
  * Form edit
297
  *
298
  */
299
- #happyforms-captcha-settings {
300
- display: none;
301
- }
302
-
303
  #happyforms-alert-email-settings,
304
- #happyforms-confirmation-email-settings {
 
305
  display: none;
306
  }
307
 
166
  }
167
 
168
  .happyforms-action-buttons {
169
+ display: flex;
170
  margin-bottom: 15px;
171
  }
172
 
173
  .happyforms-action-buttons button.button-primary.button-hero,
174
  .happyforms-action-buttons button.button-secondary.button-hero {
175
+ flex: 1;
176
  margin: 0 1%;
177
  padding: 0;
178
  text-align: center;
297
  * Form edit
298
  *
299
  */
300
+ #happyforms-captcha-settings,
 
 
 
301
  #happyforms-alert-email-settings,
302
+ #happyforms-confirmation-email-settings,
303
+ #happyforms-review-button-label-settings {
304
  display: none;
305
  }
306
 
assets/css/frontend.css CHANGED
@@ -55,6 +55,12 @@
55
  font-weight: normal;
56
  font-weight: var(--happyforms-form-font-weight);
57
  background-color: transparent;
 
 
 
 
 
 
58
  }
59
 
60
  .happyforms-form--direction-rtl {
@@ -104,7 +110,7 @@ h3.happyforms-form__title {
104
  }
105
 
106
  .happyforms-part--width-half, .happyforms-part--width-third {
107
- align-self: flex-end;
108
  }
109
 
110
  .happyforms-part__label {
@@ -394,9 +400,10 @@ h3.happyforms-form__title {
394
  /* parts - option labels */
395
 
396
  .happyforms-part .option-label {
 
 
397
  position: relative;
398
  cursor: pointer;
399
- display: inline-block;
400
  margin-bottom: 10px;
401
  padding: 0 5px 5px 0;
402
  font-size: 16px;
@@ -706,7 +713,9 @@ h3.happyforms-form__title {
706
  position: relative;
707
  top: 0;
708
  z-index: 5;
709
- display: inline-block;
 
 
710
  width: 20px;
711
  height: 20px;
712
  border-radius: 50%;
@@ -721,9 +730,6 @@ h3.happyforms-form__title {
721
 
722
  .happyforms-part .checkmark svg {
723
  display: none;
724
- position: absolute;
725
- top: 3px;
726
- left: 3px;
727
  }
728
 
729
  .happyforms-part--checkbox .checkmark,
@@ -863,6 +869,8 @@ h3.happyforms-form__title {
863
  display: block;
864
  position: relative;
865
  width: 100%;
 
 
866
  }
867
 
868
  .happyforms-part--scale output span {
@@ -969,7 +977,7 @@ h3.happyforms-form__title {
969
  /* parts - placeholder */
970
 
971
  .happyforms-part--placeholder .happyforms-part__el {
972
- padding: 10px;
973
  }
974
 
975
  .happyforms-part--placeholder p {
@@ -1652,6 +1660,7 @@ form > .happyforms-message-notices .error {
1652
  position: absolute;
1653
  top: 8px;
1654
  left: 11px;
 
1655
  }
1656
 
1657
  .happyforms-part--label-inside.happyforms-part--phone.happyforms-is-masked label {
@@ -1714,9 +1723,10 @@ form > .happyforms-message-notices .error {
1714
  .happyforms-form--part-borders-bottom-only .happyforms-part input[type=email],
1715
  .happyforms-form--part-borders-bottom-only .happyforms-part input[type=number],
1716
  .happyforms-form--part-borders-bottom-only .happyforms-part textarea {
1717
- border-top-color: transparent;
1718
- border-left-color: transparent;
1719
- border-right-color: transparent;
 
1720
  }
1721
 
1722
  /* part border transitions */
@@ -2095,6 +2105,9 @@ form > .happyforms-message-notices .error {
2095
  }
2096
 
2097
  .happyforms-table__cell {
 
 
 
2098
  box-sizing: border-box;
2099
  flex-grow: 1;
2100
  padding: 15px 10px;
@@ -2116,12 +2129,15 @@ form > .happyforms-message-notices .error {
2116
  color: var(--happyforms-color-part-title);
2117
  }
2118
  .happyforms-table__cell .option-label {
 
2119
  width: 100%;
2120
  margin-bottom: 0;
2121
  padding-bottom: 0;
2122
  text-align: center;
2123
  }
2124
  .happyforms-table__cell--row-title {
 
 
2125
  font-size: 16px;
2126
  font-size: var(--happyforms-part-title-font-size);
2127
  color: #000;
@@ -2289,7 +2305,7 @@ form > .happyforms-message-notices .error {
2289
  padding-left: 75px;
2290
  }
2291
 
2292
- /* new dropdowns */
2293
  .happyforms-part select {
2294
  display: none;
2295
  }
@@ -2341,4 +2357,182 @@ form > .happyforms-message-notices .error {
2341
  .happyforms-custom-select-dropdown .happyforms-custom-select-dropdown-item__label--country-code {
2342
  font-size: 14px;
2343
  color: #888888;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2344
  }
55
  font-weight: normal;
56
  font-weight: var(--happyforms-form-font-weight);
57
  background-color: transparent;
58
+ transition: opacity 0.25s ease-in-out;
59
+ transition: opacity var(--happyforms-transition-duration) ease-in-out;
60
+ }
61
+
62
+ .happyforms-form form.happyforms-form--submitting {
63
+ opacity: 0.5;
64
  }
65
 
66
  .happyforms-form--direction-rtl {
110
  }
111
 
112
  .happyforms-part--width-half, .happyforms-part--width-third {
113
+ align-self: flex-start;
114
  }
115
 
116
  .happyforms-part__label {
400
  /* parts - option labels */
401
 
402
  .happyforms-part .option-label {
403
+ display: flex;
404
+ align-items: center;
405
  position: relative;
406
  cursor: pointer;
 
407
  margin-bottom: 10px;
408
  padding: 0 5px 5px 0;
409
  font-size: 16px;
713
  position: relative;
714
  top: 0;
715
  z-index: 5;
716
+ display: flex;
717
+ align-items: center;
718
+ justify-content: center;
719
  width: 20px;
720
  height: 20px;
721
  border-radius: 50%;
730
 
731
  .happyforms-part .checkmark svg {
732
  display: none;
 
 
 
733
  }
734
 
735
  .happyforms-part--checkbox .checkmark,
869
  display: block;
870
  position: relative;
871
  width: 100%;
872
+ font-size: 16px;
873
+ font-size: var(--happyforms-part-value-font-size);
874
  }
875
 
876
  .happyforms-part--scale output span {
977
  /* parts - placeholder */
978
 
979
  .happyforms-part--placeholder .happyforms-part__el {
980
+ padding: 10px 0;
981
  }
982
 
983
  .happyforms-part--placeholder p {
1660
  position: absolute;
1661
  top: 8px;
1662
  left: 11px;
1663
+ z-index: 2;
1664
  }
1665
 
1666
  .happyforms-part--label-inside.happyforms-part--phone.happyforms-is-masked label {
1723
  .happyforms-form--part-borders-bottom-only .happyforms-part input[type=email],
1724
  .happyforms-form--part-borders-bottom-only .happyforms-part input[type=number],
1725
  .happyforms-form--part-borders-bottom-only .happyforms-part textarea {
1726
+ border-top-color: transparent !important;
1727
+ border-left-color: transparent !important;
1728
+ border-right-color: transparent !important;
1729
+ box-shadow: none !important;
1730
  }
1731
 
1732
  /* part border transitions */
2105
  }
2106
 
2107
  .happyforms-table__cell {
2108
+ display: flex;
2109
+ align-items: center;
2110
+ justify-content: center;
2111
  box-sizing: border-box;
2112
  flex-grow: 1;
2113
  padding: 15px 10px;
2129
  color: var(--happyforms-color-part-title);
2130
  }
2131
  .happyforms-table__cell .option-label {
2132
+ justify-content: center;
2133
  width: 100%;
2134
  margin-bottom: 0;
2135
  padding-bottom: 0;
2136
  text-align: center;
2137
  }
2138
  .happyforms-table__cell--row-title {
2139
+ align-items: flex-start;
2140
+ justify-content: flex-start;
2141
  font-size: 16px;
2142
  font-size: var(--happyforms-part-title-font-size);
2143
  color: #000;
2305
  padding-left: 75px;
2306
  }
2307
 
2308
+ /* new dropdowns */
2309
  .happyforms-part select {
2310
  display: none;
2311
  }
2357
  .happyforms-custom-select-dropdown .happyforms-custom-select-dropdown-item__label--country-code {
2358
  font-size: 14px;
2359
  color: #888888;
2360
+ }
2361
+
2362
+ .happyforms-form-preview .happyforms-part input[type=text],
2363
+ .happyforms-form-preview .happyforms-part input[type=text]:focus,
2364
+ .happyforms-form-preview .happyforms-part input[type=email],
2365
+ .happyforms-form-preview .happyforms-part input[type=email]:focus,
2366
+ .happyforms-form-preview .happyforms-part input[type=number],
2367
+ .happyforms-form-preview .happyforms-part input[type=number]:focus,
2368
+ .happyforms-form-preview .happyforms-part textarea,
2369
+ .happyforms-form-preview .happyforms-part textarea:focus {
2370
+ cursor: default;
2371
+ -webkit-appearance: none;
2372
+ -moz-appearance: none;
2373
+ appearance: none;
2374
+ padding-left: 0;
2375
+ padding-right: 0;
2376
+ border: 0 !important;
2377
+ border-color: transparent !important;
2378
+ box-shadow: none !important;
2379
+ }
2380
+
2381
+ .happyforms-form-preview .happyforms-part label {
2382
+ cursor: default;
2383
+ }
2384
+
2385
+ .happyforms-form-preview .happyforms-custom-select .happyforms-part__select-wrap:after {
2386
+ display: none;
2387
+ }
2388
+
2389
+ .happyforms-form-preview .happyforms-custom-select-dropdown {
2390
+ display: none !important;
2391
+ }
2392
+
2393
+ .happyforms-form-preview .happyforms-part--scale {
2394
+ margin-bottom: 45px;
2395
+ }
2396
+
2397
+ .happyforms-form-preview .happyforms-part--scale input {
2398
+ display: none;
2399
+ }
2400
+
2401
+ .happyforms-form-preview .happyforms-part--scale output span {
2402
+ top: -15px;
2403
+ left: 0 !important;
2404
+ }
2405
+
2406
+ .happyforms-form-preview .happyforms-part--rating label {
2407
+ display: none;
2408
+ }
2409
+
2410
+ .happyforms-form-preview input[type='checkbox'],
2411
+ .happyforms-form-preview input[type='radio'],
2412
+ .happyforms-form-preview .option-label {
2413
+ cursor: default;
2414
+ }
2415
+
2416
+ .happyforms-form-preview input[type='checkbox'],
2417
+ .happyforms-form-preview .option-label .label,
2418
+ .happyforms-form-preview .option-label .checkmark,
2419
+ .happyforms-form-preview .option-label .border {
2420
+ display: none;
2421
+ }
2422
+
2423
+ .happyforms-form-preview .option-label {
2424
+ padding-left: 0;
2425
+ padding-right: 0;
2426
+ }
2427
+
2428
+ .happyforms-form-preview .option-label .label {
2429
+ padding-left: 0;
2430
+ padding-right: 0;
2431
+ }
2432
+
2433
+ .happyforms-form-preview input[checked='checked'] ~ .label {
2434
+ display: block;
2435
+ }
2436
+
2437
+ .happyforms-form-preview .happyforms-country-select {
2438
+ display: none !important;
2439
+ }
2440
+
2441
+ .happyforms-form-preview .happyforms-part--phone.happyforms-is-masked .happyforms-part__el>input[type=text] {
2442
+ padding-left: 0 !important;
2443
+ }
2444
+
2445
+ .happyforms-form-preview .happyforms-part-date__time-input .happyforms-spinner-arrow {
2446
+ display: none;
2447
+ }
2448
+
2449
+ .happyforms-form-preview .happyforms-part--date .happyforms-part__el {
2450
+ display: block;
2451
+ }
2452
+
2453
+ .happyforms-form-preview .happyforms-part--date .happyforms-part__el div {
2454
+ display: inline;
2455
+ }
2456
+
2457
+ .happyforms-form-preview .happyforms-part--date .happyforms-part__el input {
2458
+ display: inline;
2459
+ width: auto;
2460
+ }
2461
+
2462
+ .happyforms-form-preview .happyforms-table__row--body .happyforms-table__cell {
2463
+ display: flex;
2464
+ align-items: center;
2465
+ }
2466
+
2467
+ .happyforms-form-preview .happyforms-table__row--body .happyforms-table__cell input[checked="checked"]~ .checkmark {
2468
+ display: flex;
2469
+ margin: 0 auto;
2470
+ }
2471
+
2472
+ .happyforms-form-preview a.address-geolocate {
2473
+ display: none;
2474
+ }
2475
+
2476
+ .happyforms-form-preview .happyforms-part--date .happyforms-part__el > div {
2477
+ display: none;
2478
+ }
2479
+
2480
+ .happyforms-form-preview .happyforms-part-wrap--confirmation {
2481
+ display: none;
2482
+ }
2483
+
2484
+ .happyforms-form-preview .happyforms-part__preview-value {
2485
+ font-size: 16px;
2486
+ font-size: var(--happyforms-part-value-font-size);
2487
+ }
2488
+
2489
+ .happyforms-form-preview .happyforms-part--date .happyforms-part__el > div.happyforms-part__preview-value {
2490
+ display: block;
2491
+ }
2492
+
2493
+ .happyforms-form-preview .happyforms-part--address .happyforms-part__el {
2494
+ display: none;
2495
+ }
2496
+
2497
+ .happyforms-form-preview .happyforms-part--submit {
2498
+ display: flex;
2499
+ flex-flow: row wrap;
2500
+ align-items: center;
2501
+ }
2502
+
2503
+ .happyforms-form-preview .happyforms-part--submit * {
2504
+ margin-right: 20px;
2505
+ margin-bottom: 20px;
2506
+ }
2507
+
2508
+ .happyforms-form-preview .happyforms-part--submit input {
2509
+ order: 2;
2510
+ }
2511
+
2512
+ .happyforms-form--submit-button-align-center.happyforms-form-preview .happyforms-part--submit,
2513
+ .happyforms-form--submit-button-fullwidth.happyforms-form-preview .happyforms-part--submit {
2514
+ flex-flow: column wrap;
2515
+ align-items: center;
2516
+ }
2517
+
2518
+ .happyforms-form--submit-button-align-center.happyforms-form-preview .happyforms-part--submit a,
2519
+ .happyforms-form--submit-button-fullwidth.happyforms-form-preview .happyforms-part--submit a {
2520
+ order: 2;
2521
+ }
2522
+
2523
+ .happyforms-form--submit-button-align-right.happyforms-form-preview .happyforms-part--submit {
2524
+ justify-content: flex-end;
2525
+ }
2526
+
2527
+ .happyforms-form--submit-button-align-right.happyforms-form-preview .happyforms-part--submit input {
2528
+ margin-right: 0;
2529
+ }
2530
+
2531
+ @media screen and (max-width: 800px) {
2532
+ .happyforms-form-preview .happyforms-part--submit {
2533
+ flex-flow: column wrap;
2534
+ }
2535
+ .happyforms-form-preview .happyforms-part--submit input {
2536
+ margin-right: 0;
2537
+ }
2538
  }
assets/js/customize.js CHANGED
@@ -160,6 +160,17 @@
160
  }
161
  },
162
 
 
 
 
 
 
 
 
 
 
 
 
163
  onRoute: function( segment ) {
164
  this.sidebar.steps.disable();
165
 
@@ -236,7 +247,7 @@
236
  // Capture and mute link clicks to avoid
237
  // hijacking Backbone router and breaking
238
  // Customizer navigation.
239
- this.delegate( 'click', '.happyforms-stack-view a', this.muteLink );
240
  },
241
 
242
  ready: function() {
@@ -1080,7 +1091,7 @@
1080
  html: response,
1081
  };
1082
 
1083
- api.previewer.send( 'happyforms-form-part-refresh', data );
1084
  } );
1085
  } else {
1086
  model.set('label_placement', model.previous('label_placement'), { silent: true });
@@ -1167,6 +1178,7 @@
1167
  this.listenTo( this.model, 'change:captcha_site_key', this.onChangeCaptchaKey );
1168
  this.listenTo( this.model, 'change:captcha_secret_key', this.onChangeCaptchaKey );
1169
  this.listenTo( this.model, 'change:submit_button_label', this.onSubmitButtonLabelChange );
 
1170
  },
1171
 
1172
  render: function() {
@@ -1316,6 +1328,16 @@
1316
  api.previewer.send( 'happyforms-submit-button-text-update', value );
1317
  },
1318
 
 
 
 
 
 
 
 
 
 
 
1319
  remove: function() {
1320
  _.each( this.editorIds, function( editorId ) {
1321
  wp.editor.remove( editorId );
160
  }
161
  },
162
 
163
+ previewSendBuffered: function( event, data ) {
164
+ if ( happyForms.previewer.ready ) {
165
+ api.previewer.send( event, data );
166
+ } else {
167
+ happyForms.buffer.push( {
168
+ event: event,
169
+ data: data
170
+ } );
171
+ }
172
+ },
173
+
174
  onRoute: function( segment ) {
175
  this.sidebar.steps.disable();
176
 
247
  // Capture and mute link clicks to avoid
248
  // hijacking Backbone router and breaking
249
  // Customizer navigation.
250
+ this.delegate( 'click', '.happyforms-stack-view a:not(.external)', this.muteLink );
251
  },
252
 
253
  ready: function() {
1091
  html: response,
1092
  };
1093
 
1094
+ happyForms.previewSendBuffered( 'happyforms-form-part-refresh', data );
1095
  } );
1096
  } else {
1097
  model.set('label_placement', model.previous('label_placement'), { silent: true });
1178
  this.listenTo( this.model, 'change:captcha_site_key', this.onChangeCaptchaKey );
1179
  this.listenTo( this.model, 'change:captcha_secret_key', this.onChangeCaptchaKey );
1180
  this.listenTo( this.model, 'change:submit_button_label', this.onSubmitButtonLabelChange );
1181
+ this.listenTo( this.model, 'change:preview_before_submit', this.onPreviewBeforeSubmitChange );
1182
  },
1183
 
1184
  render: function() {
1328
  api.previewer.send( 'happyforms-submit-button-text-update', value );
1329
  },
1330
 
1331
+ onPreviewBeforeSubmitChange: function() {
1332
+ var $reviewButtonLabelSettings = $( '#happyforms-review-button-label-settings', this.$el );
1333
+
1334
+ if ( this.model.get( 'preview_before_submit' ) ) {
1335
+ $reviewButtonLabelSettings.show();
1336
+ } else {
1337
+ $reviewButtonLabelSettings.hide();
1338
+ }
1339
+ },
1340
+
1341
  remove: function() {
1342
  _.each( this.editorIds, function( editorId ) {
1343
  wp.editor.remove( editorId );
assets/js/frontend.js CHANGED
@@ -96,10 +96,6 @@
96
  return valid;
97
  }
98
 
99
- if ( this.$input.attr( 'readonly' ) ) {
100
- valid = valid && ! this.isFilled();
101
- }
102
-
103
  if ( this.isRequired() ) {
104
  valid = valid && this.isFilled();
105
  }
@@ -127,6 +123,10 @@
127
  $part.happyFormPart( partMethods, {
128
  form: $form,
129
  } );
 
 
 
 
130
  }
131
 
132
  HappyForms.Form = function( el ) {
@@ -134,7 +134,10 @@
134
  this.$el = $( this.el );
135
  this.$form = $( 'form', this.$el );
136
  this.$parts = $( '[data-happyforms-type]', this.$form );
 
137
  this.$submit = $( '[type="submit"]', this.$form );
 
 
138
 
139
  this.init();
140
  }
@@ -149,15 +152,13 @@
149
  var type = $part.data( 'happyforms-type' );
150
 
151
  HappyForms.wrapPart( $part, $form );
152
-
153
- if ($part.find('.happyforms-custom-select').length) {
154
- $('.happyforms-custom-select', $part).happyformsSelect();
155
- }
156
  } );
157
 
158
  this.$el.on( 'happyforms-change', this.validate.bind( this ) );
159
  this.$el.trigger( 'happyforms-change' );
160
  this.$form.submit( this.submit.bind( this ) );
 
 
161
  },
162
 
163
  validate: function( e, data ) {
@@ -179,17 +180,19 @@
179
  } );
180
  }
181
 
182
- this.$submit.attr( 'disabled', ! isValid );
183
  },
184
 
185
- serialize: function() {
186
  var action = $( '[name=action]', this.$form ).val();
187
  var form_id = $( '[name=happyforms_form_id]', this.$form ).val();
188
  var nonce = $( '[name=happyforms_message_nonce]', this.$form ).val();
 
189
 
190
  var formData = [
191
  { name: 'action', value: action },
192
  { name: 'happyforms_form_id', value: form_id },
 
193
  { name: 'happyforms_message_nonce', value: nonce },
194
  ];
195
 
@@ -209,14 +212,32 @@
209
  return querystring;
210
  },
211
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  submit: function( e ) {
213
  e.preventDefault();
214
 
215
- this.$submit.attr('disabled', 'disabled');
 
216
 
217
  $.ajax( {
218
  type: 'post',
219
- data: this.serialize(),
220
  } ).done( this.onSubmitComplete.bind( this ) );
221
  },
222
 
@@ -228,8 +249,8 @@
228
  if ( response.data.html ) {
229
  var $el = $( response.data.html );
230
 
231
- if ( ! $el.find('.happyforms-message-notice.error').length && response.data.redirect ) {
232
- window.location.replace(response.data.redirect);
233
 
234
  return false;
235
  }
96
  return valid;
97
  }
98
 
 
 
 
 
99
  if ( this.isRequired() ) {
100
  valid = valid && this.isFilled();
101
  }
123
  $part.happyFormPart( partMethods, {
124
  form: $form,
125
  } );
126
+
127
+ if ( $part.find( '.happyforms-custom-select' ).length ) {
128
+ $( '.happyforms-custom-select', $part ).happyformsSelect();
129
+ }
130
  }
131
 
132
  HappyForms.Form = function( el ) {
134
  this.$el = $( this.el );
135
  this.$form = $( 'form', this.$el );
136
  this.$parts = $( '[data-happyforms-type]', this.$form );
137
+ this.$submits = $( '[type="submit"], a.submit', this.$form );
138
  this.$submit = $( '[type="submit"]', this.$form );
139
+ this.$submitLinks = $( 'a.submit', this.$form );
140
+ this.$step = $( '[name="happyforms_step"]', this.$form );
141
 
142
  this.init();
143
  }
152
  var type = $part.data( 'happyforms-type' );
153
 
154
  HappyForms.wrapPart( $part, $form );
 
 
 
 
155
  } );
156
 
157
  this.$el.on( 'happyforms-change', this.validate.bind( this ) );
158
  this.$el.trigger( 'happyforms-change' );
159
  this.$form.submit( this.submit.bind( this ) );
160
+ this.$submit.click( this.buttonSubmit.bind( this ) );
161
+ this.$submitLinks.click( this.linkSubmit.bind( this ) );
162
  },
163
 
164
  validate: function( e, data ) {
180
  } );
181
  }
182
 
183
+ this.$submits.attr( 'disabled', ! isValid );
184
  },
185
 
186
+ serialize: function( submitEl ) {
187
  var action = $( '[name=action]', this.$form ).val();
188
  var form_id = $( '[name=happyforms_form_id]', this.$form ).val();
189
  var nonce = $( '[name=happyforms_message_nonce]', this.$form ).val();
190
+ var step = this.$step.val();
191
 
192
  var formData = [
193
  { name: 'action', value: action },
194
  { name: 'happyforms_form_id', value: form_id },
195
+ { name: 'happyforms_step', value: step },
196
  { name: 'happyforms_message_nonce', value: nonce },
197
  ];
198
 
212
  return querystring;
213
  },
214
 
215
+ buttonSubmit: function( e ) {
216
+ if ( e.target.hasAttribute( 'data-step' ) ) {
217
+ this.$step.val( e.target.getAttribute( 'data-step' ) );
218
+ }
219
+ },
220
+
221
+ linkSubmit: function( e ) {
222
+ e.preventDefault();
223
+ e.stopImmediatePropagation();
224
+
225
+ if ( e.target.hasAttribute( 'data-step' ) ) {
226
+ this.$step.val( e.target.getAttribute( 'data-step' ) );
227
+ }
228
+
229
+ this.$form.submit();
230
+ },
231
+
232
  submit: function( e ) {
233
  e.preventDefault();
234
 
235
+ this.$form.addClass( 'happyforms-form--submitting' );
236
+ this.$submits.attr( 'disabled', 'disabled' );
237
 
238
  $.ajax( {
239
  type: 'post',
240
+ data: this.serialize( e.target ),
241
  } ).done( this.onSubmitComplete.bind( this ) );
242
  },
243
 
249
  if ( response.data.html ) {
250
  var $el = $( response.data.html );
251
 
252
+ if ( ! $el.find('.happyforms-message-notice.error' ).length && response.data.redirect ) {
253
+ window.location.replace( response.data.redirect );
254
 
255
  return false;
256
  }
assets/js/lib/happyforms-select.js CHANGED
@@ -1,173 +1,177 @@
1
  (function ($) {
2
- 'use strict';
3
 
4
- function HappyFormsSelect( el, options ) {
5
- this.el = el;
6
- this.$el = $(this.el);
7
- this.options = options;
8
 
9
- this.$el.addClass('happyforms-select-active');
10
-
11
- this.$inputWrapper = $('.happyforms-part__select-wrap', this.$el);
12
- this.$input = $('input', this.$el);
13
- this.$select = $('select', this.$el);
14
- this.$dropdown = $('.happyforms-custom-select-dropdown', this.$el);
15
-
16
- this.defaultValue = '';
17
- }
18
-
19
- var happyformsSelectMethods = {
20
- init: function() {
21
- this.cleanUp();
22
-
23
- if ( this.el.hasAttribute('data-searchable') ) {
24
- this.options.searchable = this.$el.data('searchable');
25
- }
26
-
27
- if ( ! this.options.searchable ) {
28
- this.$input.attr( 'readonly', 'readonly' );
29
- } else {
30
- this.$input.removeAttr( 'readonly' );
31
- }
32
-
33
- if ( $('li.default', this.$dropdown).length ) {
34
- var $defaultItem = $('li.default', this.$dropdown);
35
-
36
- this.defaultValue = ( $defaultItem.data('label') ) ? $defaultItem.data('label') : $defaultItem.data('value');
37
- }
38
-
39
- this.bindEvents();
40
- },
41
-
42
- bindEvents: function() {
43
- if ( this.options.searchable ) {
44
- this.$input.on( 'keyup.happyformsSelect', this.searchOptions.bind(this) );
45
- }
46
-
47
- this.$inputWrapper.on('click', this.onWrapperClick.bind( this ) );
48
- this.$input.on( 'focus.happyformsSelect click.happyformsSelect', this.showDropdown.bind( this ) );
49
- $( 'li', this.$dropdown ).on( 'click.happyformsSelect keyup.happyformsSelect', this.onItemSelect.bind( this ) );
50
- $( window ).on( 'click.happyformsSelect', this.onOutsideClick.bind( this ) );
51
- },
52
-
53
- showDropdown: function( e ) {
54
- $( '.happyforms-part-select__dropdown' ).hide();
55
-
56
- this.$dropdown.show();
57
-
58
- e.stopPropagation();
59
- },
60
-
61
- hideDropdown: function () {
62
- this.verifyValue();
63
- this.$dropdown.hide();
64
-
65
- $( 'li', this.$dropdown ).show();
66
- },
67
-
68
- onWrapperClick: function ( e ) {
69
- this.$input.focus();
70
- this.showDropdown( e );
71
- },
72
-
73
- onOutsideClick: function( e ) {
74
- if ( ! this.el.contains(e.target).length && this.$dropdown.is(':visible') ) {
75
- this.hideDropdown();
76
- }
77
- },
78
-
79
- onItemSelect: function( e ) {
80
- if ( 'keyup' === e.type && 'Enter' !== e.key || 'Tab' === e.key ) {
81
- return false;
82
- }
83
-
84
- e.stopPropagation();
85
-
86
- var $li = $(e.target);
87
- this.$input.val($li.data('value'));
88
-
89
- this.hideDropdown();
90
- },
91
-
92
- searchOptions: function( e ) {
93
- if ( e.key && 'Tab' === e.key ) {
94
- return false;
95
- }
96
-
97
- var value = this.$input.val();
98
- var $allItems = $( 'li', this.$dropdown );
99
-
100
- if ( value ) {
101
- $allItems.hide();
102
-
103
- $allItems.map(function( i, li ) {
104
- var $li = $(li);
105
- var liValue = $li.data('value');
106
- var liLabel = ( $li.data('label') && $li.data('label').length ) ? $li.data('label').toLowerCase() : '';
107
-
108
- if ( liValue ) {
109
- liValue = liValue.toString().toLowerCase();
110
- value = value.toString().toLowerCase();
111
- }
112
-
113
- if ( liValue && -1 !== liValue.indexOf(value) ) {
114
- $li.show();
115
- }
116
-
117
- if ( liLabel && -1 !== liLabel.indexOf(value) ) {
118
- $li.show();
119
- }
120
- });
121
- } else {
122
- $allItems.show();
123
- }
124
- },
125
-
126
- verifyValue: function( e ) {
127
- var value = this.$input.val();
128
- var self = this;
129
-
130
- if ( value ) {
131
- $( 'li', this.$dropdown ).each(function( i, li ) {
132
- var $li = $(li);
133
- var liValue = $li.data('value');
134
- var liLabel = ( $li.data('label') && $li.data('label').length ) ? $li.data('label') : '';
135
-
136
- if ( liValue && liValue.toString() === value || liLabel.toString() === value ) {
137
- self.$select.val(liValue);
138
-
139
- if ( liLabel ) {
140
- self.$input.val(liLabel);
141
- } else {
142
- self.$input.val(liValue);
143
- }
144
-
145
- return false;
146
- } else {
147
- self.$input.val(self.defaultValue);
148
- }
149
- });
150
- } else {
151
- self.$input.val(this.defaultValue);
152
- self.$select.val(this.defaultValue);
153
- }
154
- },
155
-
156
- cleanUp: function() {
157
- $( 'input', this.$el ).off( 'change.happyformsSelect keyup.happyformsSelect focus.happyformsSelect click.happyformsSelect' );
158
- $( '.happyforms-part-select__dropdown li', this.$el ).off( 'click.happyformsSelect keyup.happyformsSelect' );
159
- },
160
- }
161
-
162
- $.fn.happyformsSelect = function( options ) {
163
- options = $.extend({
164
- searchable: false
165
- }, $.fn.happyformsSelect.config, options);
166
-
167
- return this.each(function () {
168
- var instance = new HappyFormsSelect( this, options );
169
- $.extend( instance, happyformsSelectMethods );
170
- instance.init();
171
- });
172
- };
 
 
 
 
173
  } )( jQuery );
1
  (function ($) {
2
+ 'use strict';
3
 
4
+ function HappyFormsSelect( el, options ) {
5
+ this.el = el;
6
+ this.$el = $(this.el);
7
+ this.options = options;
8
 
9
+ this.$el.addClass('happyforms-select-active');
10
+
11
+ this.$inputWrapper = $('.happyforms-part__select-wrap', this.$el);
12
+ this.$input = $('input', this.$el);
13
+ this.$select = $('select', this.$el);
14
+ this.$dropdown = $('.happyforms-custom-select-dropdown', this.$el);
15
+
16
+ this.defaultValue = '';
17
+ }
18
+
19
+ var happyformsSelectMethods = {
20
+ init: function() {
21
+ this.cleanUp();
22
+
23
+ if ( this.el.hasAttribute('data-searchable') ) {
24
+ this.options.searchable = this.$el.data('searchable');
25
+ }
26
+
27
+ if ( ! this.options.searchable ) {
28
+ this.$input.attr( 'readonly', 'readonly' );
29
+ } else {
30
+ this.$input.removeAttr( 'readonly' );
31
+ }
32
+
33
+ if ( $('li.default', this.$dropdown).length ) {
34
+ var $defaultItem = $('li.default', this.$dropdown);
35
+
36
+ this.defaultValue = ( $defaultItem.data('label') ) ? $defaultItem.data('label') : $defaultItem.data('value');
37
+ }
38
+
39
+ this.bindEvents();
40
+
41
+ if (this.$input.val()) {
42
+ this.verifyValue();
43
+ }
44
+ },
45
+
46
+ bindEvents: function() {
47
+ if ( this.options.searchable ) {
48
+ this.$input.on( 'keyup.happyformsSelect', this.searchOptions.bind(this) );
49
+ }
50
+
51
+ this.$inputWrapper.on('click', this.onWrapperClick.bind( this ) );
52
+ this.$input.on( 'focus.happyformsSelect click.happyformsSelect', this.showDropdown.bind( this ) );
53
+ $( 'li', this.$dropdown ).on( 'click.happyformsSelect keyup.happyformsSelect', this.onItemSelect.bind( this ) );
54
+ $( window ).on( 'click.happyformsSelect', this.onOutsideClick.bind( this ) );
55
+ },
56
+
57
+ showDropdown: function( e ) {
58
+ $( '.happyforms-part-select__dropdown' ).hide();
59
+
60
+ this.$dropdown.show();
61
+
62
+ e.stopPropagation();
63
+ },
64
+
65
+ hideDropdown: function () {
66
+ this.verifyValue();
67
+ this.$dropdown.hide();
68
+
69
+ $( 'li', this.$dropdown ).show();
70
+ },
71
+
72
+ onWrapperClick: function ( e ) {
73
+ this.$input.focus();
74
+ this.showDropdown( e );
75
+ },
76
+
77
+ onOutsideClick: function( e ) {
78
+ if ( ! this.el.contains(e.target).length && this.$dropdown.is(':visible') ) {
79
+ this.hideDropdown();
80
+ }
81
+ },
82
+
83
+ onItemSelect: function( e ) {
84
+ if ( 'keyup' === e.type && 'Enter' !== e.key || 'Tab' === e.key ) {
85
+ return false;
86
+ }
87
+
88
+ e.stopPropagation();
89
+
90
+ var $li = $(e.target);
91
+ this.$input.val($li.data('value'));
92
+
93
+ this.hideDropdown();
94
+ },
95
+
96
+ searchOptions: function( e ) {
97
+ if ( e.key && 'Tab' === e.key ) {
98
+ return false;
99
+ }
100
+
101
+ var value = this.$input.val();
102
+ var $allItems = $( 'li', this.$dropdown );
103
+
104
+ if ( value ) {
105
+ $allItems.hide();
106
+
107
+ $allItems.map(function( i, li ) {
108
+ var $li = $(li);
109
+ var liValue = $li.data('value');
110
+ var liLabel = ( $li.data('label') && $li.data('label').length ) ? $li.data('label').toLowerCase() : '';
111
+
112
+ if ( liValue ) {
113
+ liValue = liValue.toString().toLowerCase();
114
+ value = value.toString().toLowerCase();
115
+ }
116
+
117
+ if ( liValue && -1 !== liValue.indexOf(value) ) {
118
+ $li.show();
119
+ }
120
+
121
+ if ( liLabel && -1 !== liLabel.indexOf(value) ) {
122
+ $li.show();
123
+ }
124
+ });
125
+ } else {
126
+ $allItems.show();
127
+ }
128
+ },
129
+
130
+ verifyValue: function( e ) {
131
+ var value = this.$input.val();
132
+ var self = this;
133
+
134
+ if ( value ) {
135
+ $( 'li', this.$dropdown ).each(function( i, li ) {
136
+ var $li = $(li);
137
+ var liValue = $li.data('value');
138
+ var liLabel = ( $li.data('label') && $li.data('label').length ) ? $li.data('label') : '';
139
+
140
+ if ( liValue && liValue.toString() === value || liLabel.toString() === value ) {
141
+ self.$select.val(liValue);
142
+
143
+ if ( liLabel ) {
144
+ self.$input.val(liLabel);
145
+ } else {
146
+ self.$input.val(liValue);
147
+ }
148
+
149
+ return false;
150
+ } else {
151
+ self.$input.val(self.defaultValue);
152
+ }
153
+ });
154
+ } else {
155
+ self.$input.val(this.defaultValue);
156
+ self.$select.val(this.defaultValue);
157
+ }
158
+ },
159
+
160
+ cleanUp: function() {
161
+ $( 'input', this.$el ).off( 'change.happyformsSelect keyup.happyformsSelect focus.happyformsSelect click.happyformsSelect' );
162
+ $( '.happyforms-part-select__dropdown li', this.$el ).off( 'click.happyformsSelect keyup.happyformsSelect' );
163
+ },
164
+ }
165
+
166
+ $.fn.happyformsSelect = function( options ) {
167
+ options = $.extend({
168
+ searchable: false
169
+ }, $.fn.happyformsSelect.config, options);
170
+
171
+ return this.each(function () {
172
+ var instance = new HappyFormsSelect( this, options );
173
+ $.extend( instance, happyformsSelectMethods );
174
+ instance.init();
175
+ });
176
+ };
177
  } )( jQuery );
assets/js/parts/part-address.js CHANGED
@@ -61,7 +61,7 @@
61
  html: response,
62
  };
63
 
64
- api.previewer.send( 'happyforms-form-part-refresh', data );
65
  } );
66
  },
67
 
@@ -77,7 +77,7 @@
77
  html: response,
78
  };
79
 
80
- api.previewer.send( 'happyforms-form-part-refresh', data );
81
  } );
82
  }
83
  } );
61
  html: response,
62
  };
63
 
64
+ happyForms.previewSendBuffered( 'happyforms-form-part-refresh', data );
65
  } );
66
  },
67
 
77
  html: response,
78
  };
79
 
80
+ happyForms.previewSendBuffered( 'happyforms-form-part-refresh', data );
81
  } );
82
  }
83
  } );
assets/js/parts/part-checkbox.js CHANGED
@@ -87,7 +87,7 @@
87
  html: response,
88
  };
89
 
90
- api.previewer.send( 'happyforms-form-part-refresh', data );
91
  } );
92
  },
93
 
87
  html: response,
88
  };
89
 
90
+ happyForms.previewSendBuffered( 'happyforms-form-part-refresh', data );
91
  } );
92
  },
93
 
assets/js/parts/part-date.js CHANGED
@@ -90,7 +90,9 @@
90
  html: response
91
  };
92
 
93
- api.previewer.send('happyforms-form-part-refresh', data);
 
 
94
  });
95
  },
96
 
@@ -102,11 +104,11 @@
102
  if ( 'all' === value ) {
103
  $minYearInput.val(currentYear - 100);
104
  $maxYearInput.val(currentYear + 20);
105
- model.set('min_year', currentYear - 100, {
106
- silent: true
107
  });
108
- model.set('max_year', currentYear + 20, {
109
- silent: true
110
  });
111
  }
112
 
90
  html: response
91
  };
92
 
93
+ happyForms.previewSendBuffered( 'happyforms-form-part-refresh', data );
94
+
95
+ // api.previewer.send('happyforms-form-part-refresh', data);
96
  });
97
  },
98
 
104
  if ( 'all' === value ) {
105
  $minYearInput.val(currentYear - 100);
106
  $maxYearInput.val(currentYear + 20);
107
+ model.set('min_year', currentYear - 100, {
108
+ silent: true
109
  });
110
+ model.set('max_year', currentYear + 20, {
111
+ silent: true
112
  });
113
  }
114
 
assets/js/parts/part-email.js CHANGED
@@ -47,7 +47,7 @@
47
  html: response,
48
  };
49
 
50
- api.previewer.send( 'happyforms-form-part-refresh', data );
51
  } );
52
  },
53
 
47
  html: response,
48
  };
49
 
50
+ happyForms.previewSendBuffered( 'happyforms-form-part-refresh', data );
51
  } );
52
  },
53
 
assets/js/parts/part-number.js CHANGED
@@ -44,7 +44,7 @@
44
  html: response,
45
  };
46
 
47
- api.previewer.send( 'happyforms-form-part-refresh', data );
48
  } );
49
  },
50
 
@@ -88,7 +88,7 @@
88
  html: response,
89
  };
90
 
91
- api.previewer.send( 'happyforms-form-part-refresh', data );
92
  } );
93
  },
94
 
44
  html: response,
45
  };
46
 
47
+ happyForms.previewSendBuffered( 'happyforms-form-part-refresh', data );
48
  } );
49
  },
50
 
88
  html: response,
89
  };
90
 
91
+ happyForms.previewSendBuffered( 'happyforms-form-part-refresh', data );
92
  } );
93
  },
94
 
assets/js/parts/part-phone.js CHANGED
@@ -11,8 +11,8 @@
11
  } );
12
 
13
  var PhoneView = happyForms.classes.views.Part.extend( {
14
- template: '#happyforms-customize-phone-template',
15
-
16
  events: _.extend({}, happyForms.classes.views.Part.prototype.events, {
17
  'change [name=masked]': 'onMaskedChange',
18
  }),
@@ -56,7 +56,9 @@
56
  html: response,
57
  };
58
 
59
- api.previewer.send('happyforms-form-part-refresh', data);
 
 
60
  });
61
  },
62
 
@@ -77,7 +79,7 @@
77
  html: response,
78
  };
79
 
80
- api.previewer.send( 'happyforms-form-part-refresh', data );
81
  } );
82
  },
83
 
@@ -104,7 +106,9 @@
104
  html: response
105
  };
106
 
107
- api.previewer.send('happyforms-form-part-refresh', data);
 
 
108
  });
109
  }
110
  } );
11
  } );
12
 
13
  var PhoneView = happyForms.classes.views.Part.extend( {
14
+ template: '#happyforms-customize-phone-template',
15
+
16
  events: _.extend({}, happyForms.classes.views.Part.prototype.events, {
17
  'change [name=masked]': 'onMaskedChange',
18
  }),
56
  html: response,
57
  };
58
 
59
+ happyForms.previewSendBuffered( 'happyforms-form-part-refresh', data );
60
+
61
+ // api.previewer.send('happyforms-form-part-refresh', data);
62
  });
63
  },
64
 
79
  html: response,
80
  };
81
 
82
+ happyForms.previewSendBuffered( 'happyforms-form-part-refresh', data );
83
  } );
84
  },
85
 
106
  html: response
107
  };
108
 
109
+ happyForms.previewSendBuffered( 'happyforms-form-part-refresh', data );
110
+
111
+ // api.previewer.send('happyforms-form-part-refresh', data);
112
  });
113
  }
114
  } );
assets/js/parts/part-radio.js CHANGED
@@ -89,7 +89,7 @@
89
  html: response,
90
  };
91
 
92
- api.previewer.send( 'happyforms-form-part-refresh', data );
93
  } );
94
  },
95
 
89
  html: response,
90
  };
91
 
92
+ happyForms.previewSendBuffered( 'happyforms-form-part-refresh', data );
93
  } );
94
  },
95
 
assets/js/parts/part-scale.js CHANGED
@@ -141,7 +141,9 @@
141
  html: response
142
  };
143
 
144
- api.previewer.send('happyforms-form-part-refresh', data);
 
 
145
  });
146
  }
147
  } );
141
  html: response
142
  };
143
 
144
+ happyForms.previewSendBuffered( 'happyforms-form-part-refresh', data );
145
+
146
+ // api.previewer.send('happyforms-form-part-refresh', data);
147
  });
148
  }
149
  } );
assets/js/parts/part-select.js CHANGED
@@ -103,7 +103,7 @@
103
  html: response,
104
  };
105
 
106
- api.previewer.send( 'happyforms-form-part-refresh', data );
107
  } );
108
  },
109
 
@@ -205,21 +205,26 @@
205
  this.$( '.happyforms-part__el', $part ).append( this.$( options.optionHTML ) );
206
  },
207
 
208
- onSelectItemLabelChangeCallback: function( id, html, options ) {
209
  var part = this.getPartModel( id );
210
  var $part = this.getPartElement( html );
211
  var option = part.get( 'options' ).get( options.itemID );
212
  var $option = $( '#' + options.itemID, $part );
213
 
214
  $option.text( option.get( 'label' ) );
 
 
 
215
  },
216
 
217
- onSelectItemDefaultChangeCallback: function( id, html, options ) {
218
  var part = this.getPartModel( id );
219
  var $part = this.getPartElement( html );
 
220
  var $option = $( '#' + options.itemID, $part );
221
 
222
  $option.attr( 'selected', true );
 
223
  },
224
 
225
  onSelectItemDeleteCallback: function( id, html, options ) {
103
  html: response,
104
  };
105
 
106
+ happyForms.previewSendBuffered( 'happyforms-form-part-refresh', data );
107
  } );
108
  },
109
 
205
  this.$( '.happyforms-part__el', $part ).append( this.$( options.optionHTML ) );
206
  },
207
 
208
+ onSelectItemLabelChangeCallback: function( id, html, options, $ ) {
209
  var part = this.getPartModel( id );
210
  var $part = this.getPartElement( html );
211
  var option = part.get( 'options' ).get( options.itemID );
212
  var $option = $( '#' + options.itemID, $part );
213
 
214
  $option.text( option.get( 'label' ) );
215
+ $( 'input', $part ).val( option.get( 'label' ) );
216
+
217
+ $.fn.happyformsSelect.call( $part );
218
  },
219
 
220
+ onSelectItemDefaultChangeCallback: function( id, html, options, $ ) {
221
  var part = this.getPartModel( id );
222
  var $part = this.getPartElement( html );
223
+ var option = part.get( 'options' ).get( options.itemID );
224
  var $option = $( '#' + options.itemID, $part );
225
 
226
  $option.attr( 'selected', true );
227
+ $( 'input', $part ).val( option.get( 'label' ) );
228
  },
229
 
230
  onSelectItemDeleteCallback: function( id, html, options ) {
assets/js/parts/part-table.js CHANGED
@@ -85,7 +85,7 @@
85
  html: response,
86
  };
87
 
88
- api.previewer.send( 'happyforms-form-part-refresh', data );
89
  } );
90
  },
91
 
@@ -140,7 +140,7 @@
140
  html: response,
141
  };
142
 
143
- api.previewer.send( 'happyforms-form-part-refresh', data );
144
  } );
145
  },
146
 
@@ -228,7 +228,7 @@
228
  html: response,
229
  };
230
 
231
- api.previewer.send( 'happyforms-form-part-refresh', data );
232
  } );
233
  },
234
 
85
  html: response,
86
  };
87
 
88
+ happyForms.previewSendBuffered( 'happyforms-form-part-refresh', data );
89
  } );
90
  },
91
 
140
  html: response,
141
  };
142
 
143
+ happyForms.previewSendBuffered( 'happyforms-form-part-refresh', data );
144
  } );
145
  },
146
 
228
  html: response,
229
  };
230
 
231
+ happyForms.previewSendBuffered( 'happyforms-form-part-refresh', data );
232
  } );
233
  },
234
 
happyforms.php CHANGED
@@ -5,7 +5,7 @@
5
  * Plugin URI: https://happyforms.me
6
  * Description: Your friendly drag and drop contact form builder for creating contact forms, lead generation forms, feedback forms, quote forms, survey forms and more!
7
  * Author: The Theme Foundry
8
- * Version: 1.5.5
9
  * Author URI: https://thethemefoundry.com
10
  * Upgrade URI: https://thethemefoundry.com
11
  */
@@ -13,7 +13,7 @@
13
  /**
14
  * The current version of the plugin.
15
  */
16
- define( 'HAPPYFORMS_VERSION', '1.5.5' );
17
 
18
  if ( ! function_exists( 'happyforms_plugin_file' ) ):
19
  /**
5
  * Plugin URI: https://happyforms.me
6
  * Description: Your friendly drag and drop contact form builder for creating contact forms, lead generation forms, feedback forms, quote forms, survey forms and more!
7
  * Author: The Theme Foundry
8
+ * Version: 1.5.6
9
  * Author URI: https://thethemefoundry.com
10
  * Upgrade URI: https://thethemefoundry.com
11
  */
13
  /**
14
  * The current version of the plugin.
15
  */
16
+ define( 'HAPPYFORMS_VERSION', '1.5.6' );
17
 
18
  if ( ! function_exists( 'happyforms_plugin_file' ) ):
19
  /**
inc/classes/class-form-controller.php CHANGED
@@ -53,6 +53,12 @@ class HappyForms_Form_Controller {
53
  add_action( 'untrashed_post', array( $this, 'untrashed_post' ) );
54
  add_filter( 'happyforms_frontend_dependencies', array( $this, 'script_dependencies' ), 10, 2 );
55
  add_filter( 'happyforms_form_has_captcha', array( $this, 'has_captcha' ), 10, 2 );
 
 
 
 
 
 
56
 
57
  if ( is_customize_preview() ) {
58
  add_filter( 'happyforms_part_class', array( $this, 'part_class' ) );
@@ -85,15 +91,18 @@ class HappyForms_Form_Controller {
85
  );
86
 
87
  $args = array(
88
- 'labels' => $labels,
89
- 'public' => true,
90
- 'show_in_menu' => false,
91
- 'query_var' => true,
92
- 'rewrite' => array( 'slug' => 'happyform' ),
93
- 'capability_type' => 'page',
94
- 'has_archive' => false,
95
- 'hierarchical' => false,
96
- 'supports' => array( 'author', 'custom-fields' ),
 
 
 
97
  );
98
 
99
  register_post_type( $this->post_type, $args );
@@ -252,6 +261,14 @@ class HappyForms_Form_Controller {
252
  'default' => '',
253
  'sanitize' => 'sanitize_text_field',
254
  ),
 
 
 
 
 
 
 
 
255
  );
256
 
257
  /**
@@ -788,6 +805,27 @@ class HappyForms_Form_Controller {
788
  return $has_captcha;
789
  }
790
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
791
  /**
792
  * Filter: append -editable class to part templates.
793
  *
@@ -811,6 +849,48 @@ class HappyForms_Form_Controller {
811
  return $title;
812
  }
813
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
814
  public function script_dependencies( $deps, $forms ) {
815
  $has_captcha = false;
816
 
53
  add_action( 'untrashed_post', array( $this, 'untrashed_post' ) );
54
  add_filter( 'happyforms_frontend_dependencies', array( $this, 'script_dependencies' ), 10, 2 );
55
  add_filter( 'happyforms_form_has_captcha', array( $this, 'has_captcha' ), 10, 2 );
56
+ add_filter( 'happyforms_get_steps', array( $this, 'steps_add_preview' ), 10, 2 );
57
+ add_filter( 'happyforms_get_template_path', array( $this, 'submit_preview_template' ), 10, 2 );
58
+ add_filter( 'happyforms_get_template_path', array( $this, 'confirm_preview_partial' ), 20, 2 );
59
+ add_filter( 'happyforms_form_class', array( $this, 'form_html_class_preview' ), 10, 2 );
60
+ add_filter( 'happyforms_part_attributes', array( $this, 'part_attributes_preview' ), 10, 4 );
61
+
62
 
63
  if ( is_customize_preview() ) {
64
  add_filter( 'happyforms_part_class', array( $this, 'part_class' ) );
91
  );
92
 
93
  $args = array(
94
+ 'labels' => $labels,
95
+ 'public' => false,
96
+ 'publicly_queryable' => is_customize_preview(),
97
+ 'exclude_from_search' => true,
98
+ 'show_ui' => true,
99
+ 'show_in_menu' => false,
100
+ 'query_var' => true,
101
+ 'rewrite' => array( 'slug' => 'happyform' ),
102
+ 'capability_type' => 'page',
103
+ 'has_archive' => false,
104
+ 'hierarchical' => false,
105
+ 'supports' => array( 'author', 'custom-fields' ),
106
  );
107
 
108
  register_post_type( $this->post_type, $args );
261
  'default' => '',
262
  'sanitize' => 'sanitize_text_field',
263
  ),
264
+ 'preview_before_submit' => array(
265
+ 'default' => 0,
266
+ 'sanitize' => 'happyforms_sanitize_checkbox',
267
+ ),
268
+ 'review_button_label' => array(
269
+ 'default' => __( 'Review submission', 'happyforms' ),
270
+ 'sanitize' => 'sanitize_text_field',
271
+ ),
272
  );
273
 
274
  /**
805
  return $has_captcha;
806
  }
807
 
808
+ public function get_default_steps( $form ) {
809
+ $steps = array(
810
+ 1000 => 'submit',
811
+ );
812
+
813
+ return $steps;
814
+ }
815
+
816
+ public function steps_add_preview( $steps, $form ) {
817
+ if ( $this->requires_confirmation( $form ) ) {
818
+ $steps[100] = 'preview';
819
+ $steps[200] = 'review';
820
+ }
821
+
822
+ return $steps;
823
+ }
824
+
825
+ public function requires_confirmation( $form ) {
826
+ return ( 1 === intval( $form['preview_before_submit'] ) );
827
+ }
828
+
829
  /**
830
  * Filter: append -editable class to part templates.
831
  *
849
  return $title;
850
  }
851
 
852
+ public function submit_preview_template( $path, $form ) {
853
+ if ( happyforms_get_form_property( $form, 'preview_before_submit' )
854
+ && ( 'preview' === happyforms_get_current_step( $form ) )
855
+ && ( 'partials/form-submit' === $path ) ) {
856
+
857
+ $path = 'partials/form-submit-preview';
858
+ }
859
+
860
+ return $path;
861
+ }
862
+
863
+ public function confirm_preview_partial( $path, $form ) {
864
+ if ( happyforms_get_form_property( $form, 'preview_before_submit' )
865
+ && ( 'review' === happyforms_get_current_step( $form ) )
866
+ && ( 'partials/form-submit' === $path ) ) {
867
+
868
+ $path = 'partials/form-confirm-preview';
869
+ }
870
+
871
+ return $path;
872
+ }
873
+
874
+ public function part_attributes_preview( $attributes, $part, $form, $component ) {
875
+ if ( happyforms_get_form_property( $form, 'preview_before_submit' )
876
+ && ( 'review' === happyforms_get_current_step( $form ) ) ) {
877
+
878
+ $attributes[] = 'readonly';
879
+ }
880
+
881
+ return $attributes;
882
+ }
883
+
884
+ public function form_html_class_preview( $classes, $form ) {
885
+ if ( happyforms_get_form_property( $form, 'preview_before_submit' )
886
+ && ( 'review' === happyforms_get_current_step( $form ) ) ) {
887
+
888
+ $classes[] = 'happyforms-form-preview';
889
+ }
890
+
891
+ return $classes;
892
+ }
893
+
894
  public function script_dependencies( $deps, $forms ) {
895
  $has_captcha = false;
896
 
inc/classes/class-message-controller.php CHANGED
@@ -22,13 +22,21 @@ class HappyForms_Message_Controller {
22
 
23
  /**
24
  * The parameter name used to identify a
25
- * message submission request.
26
  *
27
  * @since 1.0
28
  *
29
  * @var string
30
  */
31
- public $submit_parameter = 'happyforms_form_id';
 
 
 
 
 
 
 
 
32
 
33
  /**
34
  * The action name used to identify a
@@ -115,6 +123,12 @@ class HappyForms_Message_Controller {
115
  add_action( 'parse_request', array( $this, 'admin_post' ) );
116
  add_action( 'admin_init', array( $this, 'admin_post' ) );
117
  add_action( 'delete_post', array( $this, 'delete_post' ) );
 
 
 
 
 
 
118
  }
119
 
120
  /**
@@ -163,14 +177,17 @@ class HappyForms_Message_Controller {
163
  );
164
 
165
  $args = array(
166
- 'labels' => $labels,
167
- 'public' => true,
168
- 'show_in_menu' => false,
169
- 'query_var' => true,
170
- 'capability_type' => 'page',
171
- 'has_archive' => false,
172
- 'hierarchical' => false,
173
- 'supports' => array( 'custom-fields' ),
 
 
 
174
  );
175
 
176
  register_post_type( $this->post_type, $args );
@@ -192,11 +209,11 @@ class HappyForms_Message_Controller {
192
  }
193
 
194
  // Check form_id parameter
195
- if ( ! isset ( $_REQUEST[$this->submit_parameter] ) ) {
196
  wp_send_json_error();
197
  }
198
 
199
- $form_id = intval( $_REQUEST[$this->submit_parameter] );
200
 
201
  // Validate nonce
202
  if ( ! isset( $_REQUEST[$this->nonce_name] )
@@ -213,6 +230,12 @@ class HappyForms_Message_Controller {
213
  wp_send_json_error();
214
  }
215
 
 
 
 
 
 
 
216
  // Validate honeypot
217
  if ( happyforms_get_form_controller()->has_spam_protection( $form ) ) {
218
  if ( ! $this->validate_honeypot( $form ) ) {
@@ -229,59 +252,161 @@ class HappyForms_Message_Controller {
229
  }
230
  }
231
 
232
- $result = $this->create( $form );
 
 
 
 
 
 
 
 
 
233
  $session = happyforms_get_session();
 
 
234
 
235
- if ( ! $result ) {
236
  // Add a general error notice at the top
237
  $session->add_error( $form_id, __( 'Your submission contains errors.', 'happyforms' ) );
238
 
 
 
 
 
 
 
239
  /**
240
  * This action fires upon an invalid submission.
241
  *
242
  * @since 1.4
243
  *
244
- * @param WP_Error $result Error data.
245
  * @param array $form Current form data.
246
  *
247
  * @return void
248
  */
249
- do_action( 'happyforms_submission_error', $result, $form );
 
 
 
250
  } else {
251
  // Add a general success notice at the top
252
  $session->add_notice( $form_id, html_entity_decode( $form['confirmation_message'] ) );
253
 
 
 
 
254
  // Empty submitted values
255
  $session->clear_values();
256
 
257
- // Update the unread badge
258
- $this->update_badge_transient();
259
 
260
- /**
261
- * This action fires once a message is succesfully submitted.
262
- *
263
- * @since 1.4
264
- *
265
- * @param array $result Submission data.
266
- * @param array $form Current form data.
267
- *
268
- * @return void
269
- */
270
- do_action( 'happyforms_submission_success', $result, $form );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
271
  }
 
272
 
 
 
 
 
 
 
 
 
 
273
  $response = array();
274
- $response['html'] = $form_controller->render( $form );
275
 
276
- if ( ! is_wp_error( $result ) ) {
277
- if ( ! empty( $form['redirect_url'] ) ) {
278
- $response['redirect'] = $form['redirect_url'];
279
- }
 
 
 
 
 
 
 
 
 
 
 
280
 
 
 
 
 
281
  wp_send_json_success( $response );
282
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
283
 
284
- wp_send_json_error( $response );
 
 
 
 
 
 
 
 
 
 
 
 
285
  }
286
 
287
  /**
@@ -371,66 +496,67 @@ class HappyForms_Message_Controller {
371
  return $captcha_value;
372
  }
373
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
374
  /**
375
  * Create a new message post object.
376
  *
377
  * @since 1.0
378
  *
379
- * @param array $form The message form data.
 
380
  *
381
  * @return int|boolean
382
  */
383
- public function create( $form ) {
384
  $defaults = $this->get_defaults();
385
  $message_meta = wp_parse_args( array(
386
  'form_id' => $form['ID'],
387
  ), $defaults['meta'] );
388
- $message_parts = array();
389
- $success = true;
390
- $session = happyforms_get_session();
391
-
392
- foreach( $form['parts'] as $part ) {
393
- $part_class = happyforms_get_part_library()->get_part( $part['type'] );
394
-
395
- if ( false !== $part_class ) {
396
- $part_id = $part['id'];
397
- $part_name = happyforms_get_part_name( $part, $form );
398
- $sanitized_value = $part_class->sanitize_value( $part, $form );
399
- $validated_value = $part_class->validate_value( $sanitized_value, $part, $form );
400
-
401
- $session->add_value( $part_name, $sanitized_value );
402
-
403
- if ( ! is_wp_error( $validated_value ) ) {
404
- $string_value = happyforms_stringify_part_value( $validated_value, $part, $form );
405
- $message_meta[$part_id] = $string_value;
406
- } else {
407
- $success = false;
408
- $session->add_error( $part_name, $validated_value->get_error_message() );
409
- }
410
- }
411
- }
412
-
413
- if ( ! $success ) {
414
- return false;
415
- }
416
-
417
  $attrs = $defaults['post'] + array( 'meta_input' => $message_meta );
418
  $message_id = wp_insert_post( wp_slash( $attrs ), true );
419
 
420
- if ( ! is_wp_error( $message_id ) ) {
421
- $message = $this->get( $message_id );
422
- $this->email_owner_confirmation( $form, $message );
423
-
424
- if ( 1 !== $form['send_confirmation_email'] ) {
425
- $this->email_user_confirmation( $form, $message );
426
- }
427
-
428
- if ( ! $form['save_entries'] ) {
429
- wp_delete_post( $message_id, true);
430
- }
431
- }
432
-
433
- return true;
434
  }
435
 
436
  /**
22
 
23
  /**
24
  * The parameter name used to identify a
25
+ * submission form
26
  *
27
  * @since 1.0
28
  *
29
  * @var string
30
  */
31
+ public $form_parameter = 'happyforms_form_id';
32
+
33
+ /**
34
+ * The parameter name used to identify a
35
+ * submission form
36
+ *
37
+ * @var string
38
+ */
39
+ public $form_step_parameter = 'happyforms_step';
40
 
41
  /**
42
  * The action name used to identify a
123
  add_action( 'parse_request', array( $this, 'admin_post' ) );
124
  add_action( 'admin_init', array( $this, 'admin_post' ) );
125
  add_action( 'delete_post', array( $this, 'delete_post' ) );
126
+
127
+ // Core multi-step hooks
128
+ add_action( 'happyforms_step', array( $this, 'default_submission_step' ) );
129
+ // Submission preview and review
130
+ add_action( 'happyforms_step', array( $this, 'preview_submission_step' ) );
131
+ add_action( 'happyforms_step', array( $this, 'review_submission_step' ) );
132
  }
133
 
134
  /**
177
  );
178
 
179
  $args = array(
180
+ 'labels' => $labels,
181
+ 'public' => false,
182
+ 'publicly_queryable' => false,
183
+ 'exclude_from_search' => true,
184
+ 'show_ui' => true,
185
+ 'show_in_menu' => false,
186
+ 'query_var' => true,
187
+ 'capability_type' => 'page',
188
+ 'has_archive' => false,
189
+ 'hierarchical' => false,
190
+ 'supports' => array( 'custom-fields' ),
191
  );
192
 
193
  register_post_type( $this->post_type, $args );
209
  }
210
 
211
  // Check form_id parameter
212
+ if ( ! isset ( $_REQUEST[$this->form_parameter] ) ) {
213
  wp_send_json_error();
214
  }
215
 
216
+ $form_id = intval( $_REQUEST[$this->form_parameter] );
217
 
218
  // Validate nonce
219
  if ( ! isset( $_REQUEST[$this->nonce_name] )
230
  wp_send_json_error();
231
  }
232
 
233
+ // Set form step
234
+ $step = isset( $_REQUEST[$this->form_step_parameter] ) ?
235
+ intval( $_REQUEST[$this->form_step_parameter] ) : 0;
236
+
237
+ happyforms_get_session()->set_step( $step );
238
+
239
  // Validate honeypot
240
  if ( happyforms_get_form_controller()->has_spam_protection( $form ) ) {
241
  if ( ! $this->validate_honeypot( $form ) ) {
252
  }
253
  }
254
 
255
+ do_action( 'happyforms_step', $form );
256
+ }
257
+
258
+ public function default_submission_step( $form ) {
259
+ if ( 'submit' !== happyforms_get_current_step( $form ) ) {
260
+ return;
261
+ }
262
+
263
+ $form_id = $form['ID'];
264
+ $form_controller = happyforms_get_form_controller();
265
  $session = happyforms_get_session();
266
+ $submission = $this->validate_submission( $form );
267
+ $response = array();
268
 
269
+ if ( false === $submission ) {
270
  // Add a general error notice at the top
271
  $session->add_error( $form_id, __( 'Your submission contains errors.', 'happyforms' ) );
272
 
273
+ // Reset to start step
274
+ $session->reset_step();
275
+
276
+ // Render the form
277
+ $response['html'] = $form_controller->render( $form );
278
+
279
  /**
280
  * This action fires upon an invalid submission.
281
  *
282
  * @since 1.4
283
  *
284
+ * @param WP_Error $submission Error data.
285
  * @param array $form Current form data.
286
  *
287
  * @return void
288
  */
289
+ do_action( 'happyforms_submission_error', $submission, $form );
290
+
291
+ // Send error response
292
+ wp_send_json_error( $response );
293
  } else {
294
  // Add a general success notice at the top
295
  $session->add_notice( $form_id, html_entity_decode( $form['confirmation_message'] ) );
296
 
297
+ // Reset to start step
298
+ $session->reset_step();
299
+
300
  // Empty submitted values
301
  $session->clear_values();
302
 
303
+ // Create message post
304
+ $message_id = $this->create( $form, $submission );
305
 
306
+ if ( ! is_wp_error( $message_id ) ) {
307
+ // Update the unread badge
308
+ $this->update_badge_transient();
309
+
310
+ if ( ! empty( $form['redirect_url'] ) ) {
311
+ $response['redirect'] = $form['redirect_url'];
312
+ }
313
+
314
+ $message = $this->get( $message_id );
315
+ $this->email_owner_confirmation( $form, $message );
316
+
317
+ if ( 1 !== $form['send_confirmation_email'] ) {
318
+ $this->email_user_confirmation( $form, $message );
319
+ }
320
+
321
+ if ( ! $form['save_entries'] ) {
322
+ wp_delete_post( $message_id, true);
323
+ }
324
+
325
+ /**
326
+ * This action fires once a message is succesfully submitted.
327
+ *
328
+ * @since 1.4
329
+ *
330
+ * @param array $submission Submission data.
331
+ * @param array $form Current form data.
332
+ *
333
+ * @return void
334
+ */
335
+ do_action( 'happyforms_submission_success', $submission, $form );
336
+
337
+ // Render the form
338
+ $response['html'] = $form_controller->render( $form );
339
+
340
+ // Send success response
341
+ wp_send_json_success( $response );
342
+ }
343
  }
344
+ }
345
 
346
+ public function preview_submission_step( $form ) {
347
+ if ( 'preview' !== happyforms_get_current_step( $form ) ) {
348
+ return;
349
+ }
350
+
351
+ $form_id = $form['ID'];
352
+ $form_controller = happyforms_get_form_controller();
353
+ $session = happyforms_get_session();
354
+ $submission = $this->validate_submission( $form );
355
  $response = array();
 
356
 
357
+ if ( false === $submission ) {
358
+ // Add a general error notice at the top
359
+ $session->add_error( $form_id, __( 'Your submission contains errors.', 'happyforms' ) );
360
+
361
+ // Reset to start step
362
+ $session->reset_step();
363
+
364
+ // Render the form
365
+ $response['html'] = $form_controller->render( $form );
366
+
367
+ // Send error response
368
+ wp_send_json_error( $response );
369
+ } else {
370
+ // Advance step
371
+ $session->next_step();
372
 
373
+ // Render the form
374
+ $response['html'] = $form_controller->render( $form );
375
+
376
+ // Send success response
377
  wp_send_json_success( $response );
378
  }
379
+ }
380
+
381
+ public function review_submission_step( $form ) {
382
+ if ( 'review' !== happyforms_get_current_step( $form ) ) {
383
+ return;
384
+ }
385
+
386
+ $form_id = $form['ID'];
387
+ $form_controller = happyforms_get_form_controller();
388
+ $session = happyforms_get_session();
389
+ $submission = $this->validate_submission( $form );
390
+ $response = array();
391
+
392
+ if ( false === $submission ) {
393
+ // Add a general error notice at the top
394
+ $session->add_error( $form_id, __( 'Your submission contains errors.', 'happyforms' ) );
395
+ }
396
 
397
+ // Reset to start step
398
+ $session->reset_step();
399
+
400
+ // Render the form
401
+ $response['html'] = $form_controller->render( $form );
402
+
403
+ if ( false === $submission ) {
404
+ // Send error response
405
+ wp_send_json_error( $response );
406
+ }
407
+
408
+ // Send success response
409
+ wp_send_json_success( $response );
410
  }
411
 
412
  /**
496
  return $captcha_value;
497
  }
498
 
499
+ public function validate_part( $form, $part ) {
500
+ $part_class = happyforms_get_part_library()->get_part( $part['type'] );
501
+
502
+ if ( false !== $part_class ) {
503
+ $part_id = $part['id'];
504
+ $part_name = happyforms_get_part_name( $part, $form );
505
+ $sanitized_value = $part_class->sanitize_value( $part, $form );
506
+ $validated_value = $part_class->validate_value( $sanitized_value, $part, $form );
507
+ $session = happyforms_get_session();
508
+
509
+ $session->add_value( $part_name, $sanitized_value );
510
+
511
+ if ( ! is_wp_error( $validated_value ) ) {
512
+ return $validated_value;
513
+ } else {
514
+ $session->add_error( $part_name, $validated_value->get_error_message() );
515
+ }
516
+ }
517
+
518
+ return false;
519
+ }
520
+
521
+ public function validate_submission( $form ) {
522
+ $submission = array();
523
+ $is_valid = true;
524
+
525
+ foreach( $form['parts'] as $part ) {
526
+ $part_id = $part['id'];
527
+ $validated_value = $this->validate_part( $form, $part );
528
+
529
+ if ( false !== $validated_value ) {
530
+ $string_value = happyforms_stringify_part_value( $validated_value, $part, $form );
531
+ $submission[$part_id] = $string_value;
532
+ } else {
533
+ $is_valid = false;
534
+ }
535
+ }
536
+
537
+ return $is_valid ? $submission : false;
538
+ }
539
+
540
  /**
541
  * Create a new message post object.
542
  *
543
  * @since 1.0
544
  *
545
+ * @param array $form The message form data.
546
+ * @param array $submission The message form data.
547
  *
548
  * @return int|boolean
549
  */
550
+ public function create( $form, $submission ) {
551
  $defaults = $this->get_defaults();
552
  $message_meta = wp_parse_args( array(
553
  'form_id' => $form['ID'],
554
  ), $defaults['meta'] );
555
+ $message_meta = array_merge( $message_meta, $submission );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
556
  $attrs = $defaults['post'] + array( 'meta_input' => $message_meta );
557
  $message_id = wp_insert_post( wp_slash( $attrs ), true );
558
 
559
+ return $message_id;
 
 
 
 
 
 
 
 
 
 
 
 
 
560
  }
561
 
562
  /**
inc/classes/class-session.php CHANGED
@@ -38,6 +38,13 @@ class HappyForms_Session {
38
  */
39
  private $values = array();
40
 
 
 
 
 
 
 
 
41
  /**
42
  * The singleton constructor.
43
  *
@@ -123,6 +130,26 @@ class HappyForms_Session {
123
  $this->values = array();
124
  }
125
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  }
127
 
128
  if ( ! function_exists( 'happyforms_get_session' ) ):
38
  */
39
  private $values = array();
40
 
41
+ /**
42
+ * Current form step
43
+ *
44
+ * @var int
45
+ */
46
+ private $step = 0;
47
+
48
  /**
49
  * The singleton constructor.
50
  *
130
  $this->values = array();
131
  }
132
 
133
+ public function current_step() {
134
+ return $this->step;
135
+ }
136
+
137
+ public function next_step() {
138
+ $this->step = $this->step + 1;
139
+ }
140
+
141
+ public function previous_step() {
142
+ $this->step = max( 0, $this->step - 1 );
143
+ }
144
+
145
+ public function set_step( $step ) {
146
+ $this->step = $step;
147
+ }
148
+
149
+ public function reset_step() {
150
+ $this->step = 0;
151
+ }
152
+
153
  }
154
 
155
  if ( ! function_exists( 'happyforms_get_session' ) ):
inc/classes/parts/class-part-address.php CHANGED
@@ -17,6 +17,7 @@ class HappyForms_Part_Address extends HappyForms_Form_Part {
17
  add_filter( 'happyforms_part_data_attributes', array( $this, 'html_part_data_attributes' ), 10, 3 );
18
  add_filter( 'happyforms_part_value', array( $this, 'get_part_value' ), 10, 4 );
19
  add_filter( 'happyforms_stringify_part_value', array( $this, 'stringify_value' ), 10, 3 );
 
20
  add_filter( 'happyforms_frontend_dependencies', array( $this, 'script_dependencies' ), 10, 2 );
21
 
22
  add_action( 'wp_ajax_' . $this->ajax_action_autocomplete, array( $this, 'ajax_autocomplete' ) );
@@ -318,6 +319,21 @@ class HappyForms_Part_Address extends HappyForms_Form_Part {
318
  return $attributes;
319
  }
320
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
  /**
322
  * Enqueue scripts in customizer area.
323
  *
17
  add_filter( 'happyforms_part_data_attributes', array( $this, 'html_part_data_attributes' ), 10, 3 );
18
  add_filter( 'happyforms_part_value', array( $this, 'get_part_value' ), 10, 4 );
19
  add_filter( 'happyforms_stringify_part_value', array( $this, 'stringify_value' ), 10, 3 );
20
+ add_action( 'happyforms_part_input_before', array( $this, 'preview_input_before' ), 10, 2 );
21
  add_filter( 'happyforms_frontend_dependencies', array( $this, 'script_dependencies' ), 10, 2 );
22
 
23
  add_action( 'wp_ajax_' . $this->ajax_action_autocomplete, array( $this, 'ajax_autocomplete' ) );
319
  return $attributes;
320
  }
321
 
322
+ public function preview_input_before( $part, $form ) {
323
+ if ( ! happyforms_get_form_property( $form, 'preview_before_submit' )
324
+ || ( $this->type !== $part['type'] )
325
+ || ( 'review' !== happyforms_get_current_step( $form ) ) ) {
326
+
327
+ return;
328
+ }
329
+
330
+ $validated_value = $this->validate_value( happyforms_get_part_value( $part, $form ), $part, $form );
331
+ $stringified_value = $this->stringify_value( $validated_value, $part, $form );
332
+ ?>
333
+ <div class="happyforms-part__preview-value"><?php echo $stringified_value; ?></div>
334
+ <?php
335
+ }
336
+
337
  /**
338
  * Enqueue scripts in customizer area.
339
  *
inc/classes/parts/class-part-date.php CHANGED
@@ -11,6 +11,7 @@ class HappyForms_Part_Date extends HappyForms_Form_Part {
11
  add_filter( 'happyforms_part_class', array( $this, 'html_part_class' ), 10, 3 );
12
  add_filter( 'happyforms_part_value', array( $this, 'get_part_value' ), 10, 4 );
13
  add_filter( 'happyforms_stringify_part_value', array( $this, 'stringify_value' ), 10, 3 );
 
14
  add_filter( 'happyforms_frontend_dependencies', array( $this, 'script_dependencies' ), 10, 2 );
15
  }
16
 
@@ -310,6 +311,21 @@ class HappyForms_Part_Date extends HappyForms_Form_Part {
310
  return $class;
311
  }
312
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
  /**
314
  * Enqueue scripts in customizer area.
315
  *
11
  add_filter( 'happyforms_part_class', array( $this, 'html_part_class' ), 10, 3 );
12
  add_filter( 'happyforms_part_value', array( $this, 'get_part_value' ), 10, 4 );
13
  add_filter( 'happyforms_stringify_part_value', array( $this, 'stringify_value' ), 10, 3 );
14
+ add_action( 'happyforms_part_input_before', array( $this, 'preview_input_before' ), 10, 2 );
15
  add_filter( 'happyforms_frontend_dependencies', array( $this, 'script_dependencies' ), 10, 2 );
16
  }
17
 
311
  return $class;
312
  }
313
 
314
+ public function preview_input_before( $part, $form ) {
315
+ if ( ! happyforms_get_form_property( $form, 'preview_before_submit' )
316
+ || ( $this->type !== $part['type'] )
317
+ || ( 'review' !== happyforms_get_current_step( $form ) ) ) {
318
+
319
+ return;
320
+ }
321
+
322
+ $validated_value = $this->validate_value( happyforms_get_part_value( $part, $form ), $part, $form );
323
+ $stringified_value = $this->stringify_value( $validated_value, $part, $form );
324
+ ?>
325
+ <div class="happyforms-part__preview-value"><?php echo $stringified_value; ?></div>
326
+ <?php
327
+ }
328
+
329
  /**
330
  * Enqueue scripts in customizer area.
331
  *
inc/classes/parts/class-part-email.php CHANGED
@@ -146,7 +146,7 @@ class HappyForms_Part_Email extends HappyForms_Form_Part {
146
  return new WP_Error( 'error', __( 'This field is required.', 'happyforms' ) );
147
  }
148
 
149
- if ( ! is_email( $validated_values[0] ) ) {
150
  return new WP_error( 'error', __( 'Not a valid e-mail address.', 'happyforms' ) );
151
  }
152
 
146
  return new WP_Error( 'error', __( 'This field is required.', 'happyforms' ) );
147
  }
148
 
149
+ if ( ! empty( $validated_values[0] ) && ! is_email( $validated_values[0] ) ) {
150
  return new WP_error( 'error', __( 'Not a valid e-mail address.', 'happyforms' ) );
151
  }
152
 
inc/classes/parts/class-part-legal.php CHANGED
@@ -8,6 +8,8 @@ class HappyForms_Part_Legal extends HappyForms_Form_Part {
8
  public function __construct() {
9
  $this->label = __( 'Legal', 'happyforms' );
10
  $this->description = __( 'For requiring fine print before accepting submission.', 'happyforms' );
 
 
11
  }
12
 
13
  /**
@@ -120,6 +122,16 @@ class HappyForms_Part_Legal extends HappyForms_Form_Part {
120
  return $validated_value;
121
  }
122
 
 
 
 
 
 
 
 
 
 
 
123
  /**
124
  * Enqueue scripts in customizer area.
125
  *
8
  public function __construct() {
9
  $this->label = __( 'Legal', 'happyforms' );
10
  $this->description = __( 'For requiring fine print before accepting submission.', 'happyforms' );
11
+
12
+ add_filter( 'happyforms_part_value', array( $this, 'get_part_value' ), 10, 4 );
13
  }
14
 
15
  /**
122
  return $validated_value;
123
  }
124
 
125
+ public function get_part_value( $value, $part, $form, $component ) {
126
+ if ( $this->type === $part['type']
127
+ && ( 'review' !== happyforms_get_current_step( $form ) ) ) {
128
+
129
+ $value = '';
130
+ }
131
+
132
+ return $value;
133
+ }
134
+
135
  /**
136
  * Enqueue scripts in customizer area.
137
  *
inc/classes/parts/class-part-number.php CHANGED
@@ -60,7 +60,7 @@ class HappyForms_Part_Number extends HappyForms_Form_Part {
60
  'sanitize' => 'intval'
61
  ),
62
  'max_value' => array(
63
- 'default' => 1,
64
  'sanitize' => 'intval'
65
  ),
66
  'masked' => array(
@@ -175,10 +175,14 @@ class HappyForms_Part_Number extends HappyForms_Form_Part {
175
  return new WP_Error( 'error', __( 'This field is required.', 'happyforms' ) );
176
  }
177
 
178
- if ( $part['required'] && empty( $validated_values[0] ) ) {
179
  return new WP_Error( 'error', __( 'This field is required.', 'happyforms' ) );
180
  }
181
 
 
 
 
 
182
  if ( isset( $validated_values[1] ) && $validated_values[0] !== $validated_values[1] ) {
183
  return new WP_Error( 'error', __( 'Number and confirmation number are not matching.', 'happyforms' ) );
184
  }
60
  'sanitize' => 'intval'
61
  ),
62
  'max_value' => array(
63
+ 'default' => 10,
64
  'sanitize' => 'intval'
65
  ),
66
  'masked' => array(
175
  return new WP_Error( 'error', __( 'This field is required.', 'happyforms' ) );
176
  }
177
 
178
+ if ( $part['required'] && ! isset( $validated_values[0] ) ) {
179
  return new WP_Error( 'error', __( 'This field is required.', 'happyforms' ) );
180
  }
181
 
182
+ if ( isset( $validated_values[0] ) && ( $validated_values[0] < $part['min_value'] || $validated_values[0] > $part['max_value'] ) ) {
183
+ return new WP_Error( 'error', __( 'This field does not match minimum and maximum allowed value.', 'happyforms' ) );
184
+ }
185
+
186
  if ( isset( $validated_values[1] ) && $validated_values[0] !== $validated_values[1] ) {
187
  return new WP_Error( 'error', __( 'Number and confirmation number are not matching.', 'happyforms' ) );
188
  }
inc/helpers/helper-form-templates.php CHANGED
@@ -11,7 +11,7 @@ if ( ! function_exists( 'happyforms_form_field' ) ):
11
  * @return void
12
  */
13
  function happyforms_form_field( $id ) {
14
- $parameter = happyforms_get_message_controller()->submit_parameter; ?>
15
  <input type="hidden" name="<?php echo esc_attr( $parameter ); ?>" value="<?php echo esc_attr( $id ); ?>" />
16
  <?php
17
  }
@@ -78,11 +78,7 @@ if ( ! function_exists( 'happyforms_submit' ) ):
78
  * @return void
79
  */
80
  function happyforms_submit( $form ) {
81
- ?>
82
- <div class="happyforms-form__part happyforms-part happyforms-part--submit">
83
- <input type="submit" class="happyforms-submit happyforms-button--submit" <?php if ( ! empty( $form['submit_button_label'] ) ): ?>value="<?php echo esc_attr( $form['submit_button_label'] ); ?>"<?php endif; ?><?php if ( happyforms_get_form_property( $form, 'disable_submit_until_valid' ) ) : ?> disabled<?php endif; ?>>
84
- </div>
85
- <?php
86
  }
87
 
88
  endif;
@@ -278,6 +274,57 @@ function happyforms_the_part_value( $part, $form, $component = false ) {
278
 
279
  endif;
280
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
281
  if ( ! function_exists( 'happyforms_get_form_title' ) ):
282
  /**
283
  * Return the form title.
@@ -752,7 +799,6 @@ function happyforms_get_months() {
752
 
753
  endif;
754
 
755
-
756
  if ( ! function_exists( 'happyforms_get_site_date_format' ) ) :
757
 
758
  function happyforms_get_site_date_format() {
@@ -777,8 +823,8 @@ function happyforms_the_countries_dropdown( $part_object, $part, $country_code )
777
  <div class="happyforms-part--phone__country-select happyforms-country-select<?php if ( $part['mask_allow_all_countries'] ) { ?> happyforms-country-select--multiple<?php } ?>">
778
  <div class="happyforms-country-select__selected-country">
779
  <a href="#" class="happyforms-country-select-trigger"></a>
780
- <?php
781
- $countries = $part_object->get_phone_countries_array();
782
  $current_country = 0;
783
 
784
  foreach( $countries as $country ) {
@@ -808,4 +854,95 @@ function happyforms_the_countries_dropdown( $part_object, $part, $country_code )
808
  <?php
809
  }
810
 
811
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  * @return void
12
  */
13
  function happyforms_form_field( $id ) {
14
+ $parameter = happyforms_get_message_controller()->form_parameter; ?>
15
  <input type="hidden" name="<?php echo esc_attr( $parameter ); ?>" value="<?php echo esc_attr( $id ); ?>" />
16
  <?php
17
  }
78
  * @return void
79
  */
80
  function happyforms_submit( $form ) {
81
+ include( happyforms_template_path( 'partials/form-submit', $form ) );
 
 
 
 
82
  }
83
 
84
  endif;
274
 
275
  endif;
276
 
277
+ if ( ! function_exists( 'happyforms_get_part_attributes' ) ):
278
+ /**
279
+ * Returns additional HTML attributes for this form part.
280
+ *
281
+ * @since 1.4
282
+ *
283
+ * @param array $part_id Current part data.
284
+ * @param array $form_id Current form data.
285
+ * @param string $component An optional part sub-component.
286
+ *
287
+ * @return string
288
+ */
289
+ function happyforms_get_part_attributes( $part, $form, $component = false ) {
290
+ /**
291
+ * Filter the default submission value for this form part.
292
+ *
293
+ * @since 1.4
294
+ *
295
+ * @param string $value The default value.
296
+ * @param array $part Current part data.
297
+ * @param array $form Current form data.
298
+ * @param string $component An optional part sub-component.
299
+ *
300
+ * @return string The filtered part attributes.
301
+ */
302
+ return apply_filters( 'happyforms_part_attributes', array(), $part, $form, $component );
303
+ }
304
+
305
+ endif;
306
+
307
+ if ( ! function_exists( 'happyforms_the_part_attributes' ) ):
308
+ /**
309
+ * Output additional HTML attributes for this form part.
310
+ *
311
+ * @since 1.4
312
+ *
313
+ * @param array $part Current part data.
314
+ * @param array $form Current form data.
315
+ * @param string $component An optional part sub-component.
316
+ *
317
+ * @return void
318
+ */
319
+ function happyforms_the_part_attributes( $part, $form, $component = false ) {
320
+ $attributes = happyforms_get_part_attributes( $part, $form, $component );
321
+ $attributes = implode( ' ', $attributes );
322
+
323
+ echo $attributes;
324
+ }
325
+
326
+ endif;
327
+
328
  if ( ! function_exists( 'happyforms_get_form_title' ) ):
329
  /**
330
  * Return the form title.
799
 
800
  endif;
801
 
 
802
  if ( ! function_exists( 'happyforms_get_site_date_format' ) ) :
803
 
804
  function happyforms_get_site_date_format() {
823
  <div class="happyforms-part--phone__country-select happyforms-country-select<?php if ( $part['mask_allow_all_countries'] ) { ?> happyforms-country-select--multiple<?php } ?>">
824
  <div class="happyforms-country-select__selected-country">
825
  <a href="#" class="happyforms-country-select-trigger"></a>
826
+ <?php
827
+ $countries = $part_object->get_phone_countries_array();
828
  $current_country = 0;
829
 
830
  foreach( $countries as $country ) {
854
  <?php
855
  }
856
 
857
+ endif;
858
+
859
+ if ( ! function_exists( 'happyforms_get_steps' ) ) :
860
+
861
+ function happyforms_get_steps( $form ) {
862
+ $steps = happyforms_get_form_controller()->get_default_steps( $form );
863
+ $steps = apply_filters( 'happyforms_get_steps', $steps, $form );
864
+ ksort( $steps );
865
+ $steps = array_values( $steps );
866
+
867
+ return $steps;
868
+ }
869
+
870
+ endif;
871
+
872
+ if ( ! function_exists( 'happyforms_get_current_step' ) ) :
873
+
874
+ function happyforms_get_current_step( $form, $index = false ) {
875
+ $steps = happyforms_get_steps( $form );
876
+ $session = happyforms_get_session();
877
+ $step = $session->current_step();
878
+
879
+ if ( isset( $steps[$step] ) ) {
880
+ return $index ? $step : $steps[$step];
881
+ }
882
+
883
+ return false;
884
+ }
885
+
886
+ endif;
887
+
888
+ if ( ! function_exists( 'happyforms_get_next_step' ) ) :
889
+
890
+ function happyforms_get_next_step( $form, $index = false ) {
891
+ $steps = happyforms_get_steps( $form );
892
+ $session = happyforms_get_session();
893
+ $step = $session->current_step() + 1;
894
+
895
+ if ( isset( $steps[$step] ) ) {
896
+ return $index ? $step : $steps[$step];
897
+ }
898
+
899
+ return false;
900
+ }
901
+
902
+ endif;
903
+
904
+ if ( ! function_exists( 'happyforms_get_last_step' ) ) :
905
+
906
+ function happyforms_get_last_step( $form, $index = false ) {
907
+ $steps = happyforms_get_steps( $form );
908
+ $last_step = count( $steps ) - 1;
909
+
910
+ return $index ? $last_step : $steps[$last_step];
911
+ }
912
+
913
+ endif;
914
+
915
+ if ( ! function_exists( 'happyforms_is_last_step' ) ) :
916
+
917
+ function happyforms_is_last_step( $form, $step = 0 ) {
918
+ $steps = happyforms_get_steps( $form );
919
+ $is_last = ( count( $steps ) - 1 ) === $step;
920
+
921
+ return $is_last;
922
+ }
923
+
924
+ endif;
925
+
926
+ if ( ! function_exists( 'happyforms_step_field' ) ) :
927
+
928
+ function happyforms_step_field( $form ) {
929
+ $session = happyforms_get_session();
930
+ $step = $session->current_step();
931
+ ?>
932
+ <input type="hidden" name="happyforms_step" value="<?php echo $step; ?>" />
933
+ <?php
934
+ }
935
+
936
+ endif;
937
+
938
+ if ( ! function_exists( 'happyforms_template_path' ) ) :
939
+
940
+ function happyforms_template_path( $path, $form = array(), $part = array() ) {
941
+ $path = apply_filters( 'happyforms_get_template_path', $path, $form, $part );
942
+ $path = "/templates/{$path}.php";
943
+ $path = happyforms_get_include_folder() . $path;
944
+
945
+ return $path;
946
+ }
947
+
948
+ endif;
inc/templates/customize-form-setup.php CHANGED
@@ -9,7 +9,7 @@
9
  <div class="customize-control customize-control-checkbox">
10
  <div class="customize-inside-control-row">
11
  <input type="checkbox" id="happyforms-receive-email-alerts" value="1" <% if ( receive_email_alerts ) { %>checked="checked"<% } %> data-attribute="receive_email_alerts" />
12
- <label for="happyforms-receive-email-alerts"><?php _e( 'Receive subscription alerts', 'happyforms' ); ?></label>
13
  </div>
14
  </div>
15
  <div id="happyforms-alert-email-settings"<% if ( receive_email_alerts ) { %> style="display: block"<% } %>>
@@ -57,7 +57,7 @@
57
  <div class="customize-control customize-control-checkbox">
58
  <div class="customize-inside-control-row" data-pointer-target>
59
  <input type="checkbox" id="happyforms-use-captcha" value="1" <% if ( captcha ) { %>checked="checked"<% } %> data-attribute="captcha" />
60
- <label for="happyforms-use-captcha"><?php _e( 'Use', 'happyforms' ); ?> <a href="https://www.google.com/recaptcha" target="_blank"><?php _e( 'Google ReCaptcha', 'happyforms' ); ?></a> <i class="fa fa-question-circle" aria-hidden="true" data-pointer="captcha"></i></label>
61
  </div>
62
  <div id="happyforms-captcha-settings" <% if ( captcha ) { %>style="display: block;"<% } %>>
63
  <p>
@@ -76,6 +76,18 @@
76
  <label for="happyforms-save-entries"><?php _e( 'Save messages for this form', 'happyforms' ); ?> <i class="fa fa-question-circle" aria-hidden="true" data-pointer="save_entries"></i></label>
77
  </div>
78
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
79
  </ul>
80
  </script>
81
  <script type="text/template" id="happyforms-pointer-confirmation_message">
@@ -105,3 +117,6 @@
105
  <script type="text/template" id="happyforms-pointer-save_entries">
106
  <?php _e( 'Keep recipients responses stored in your WordPress database.', 'happyforms' ); ?>
107
  </script>
 
 
 
9
  <div class="customize-control customize-control-checkbox">
10
  <div class="customize-inside-control-row">
11
  <input type="checkbox" id="happyforms-receive-email-alerts" value="1" <% if ( receive_email_alerts ) { %>checked="checked"<% } %> data-attribute="receive_email_alerts" />
12
+ <label for="happyforms-receive-email-alerts"><?php _e( 'Receive submission alerts', 'happyforms' ); ?></label>
13
  </div>
14
  </div>
15
  <div id="happyforms-alert-email-settings"<% if ( receive_email_alerts ) { %> style="display: block"<% } %>>
57
  <div class="customize-control customize-control-checkbox">
58
  <div class="customize-inside-control-row" data-pointer-target>
59
  <input type="checkbox" id="happyforms-use-captcha" value="1" <% if ( captcha ) { %>checked="checked"<% } %> data-attribute="captcha" />
60
+ <label for="happyforms-use-captcha"><?php _e( 'Use', 'happyforms' ); ?> <a href="https://www.google.com/recaptcha" target="_blank" class="external"><?php _e( 'Google ReCaptcha', 'happyforms' ); ?></a> <i class="fa fa-question-circle" aria-hidden="true" data-pointer="captcha"></i></label>
61
  </div>
62
  <div id="happyforms-captcha-settings" <% if ( captcha ) { %>style="display: block;"<% } %>>
63
  <p>
76
  <label for="happyforms-save-entries"><?php _e( 'Save messages for this form', 'happyforms' ); ?> <i class="fa fa-question-circle" aria-hidden="true" data-pointer="save_entries"></i></label>
77
  </div>
78
  </div>
79
+ <div class="customize-control customize-control-checkbox">
80
+ <div class="customize-inside-control-row" data-pointer-target>
81
+ <input type="checkbox" value="1" id="happyforms-preview-before-submit" <% if ( preview_before_submit ) { %>checked="checked"<% } %> data-attribute="preview_before_submit" />
82
+ <label for="happyforms-preview-before-submit"><?php _e( 'Preview values before submission', 'happyforms' ); ?> <i class="fa fa-question-circle" aria-hidden="true" data-pointer="preview_before_submit"></i></label>
83
+ </div>
84
+ </div>
85
+ <div id="happyforms-review-button-label-settings" <% if ( preview_before_submit ) { %>style="display: block;"<% } %>>
86
+ <div class="customize-control">
87
+ <label for="form_review_button_label" class="customize-control-title"><?php _e( 'Review button text', 'happyforms' ); ?></label>
88
+ <input type="text" id="form_review_button_label" value="<%= review_button_label %>" data-attribute="review_button_label" data-pointer-target />
89
+ </div>
90
+ </div>
91
  </ul>
92
  </script>
93
  <script type="text/template" id="happyforms-pointer-confirmation_message">
117
  <script type="text/template" id="happyforms-pointer-save_entries">
118
  <?php _e( 'Keep recipients responses stored in your WordPress database.', 'happyforms' ); ?>
119
  </script>
120
+ <script type="text/template" id="happyforms-pointer-preview_before_submit">
121
+ <?php _e( 'Let your users review their submission before confirming it.', 'happyforms' ); ?>
122
+ </script>
inc/templates/customize-form-steps.php CHANGED
@@ -1,6 +1,27 @@
1
  <script type="text/template" id="happyforms-form-steps-template">
2
  <div class="happyforms-action-buttons">
3
- <% if ( step.index > 1 ) { %><button class="button button-secondary button-hero happyforms-step-previous"><i class="fa fa-lg fa-arrow-circle-o-left" aria-hidden="true"></i> <?php _e( 'Previous', 'happyforms' ); ?></button><% } %><% if ( step.index < step.count ) { %><button class="button button-primary button-hero button-forwards happyforms-step-next"><?php _e( 'Next', 'happyforms' ); ?> <i class="fa fa-lg fa-arrow-circle-o-right" aria-hidden="true"></i></button><% } else { %><button class="button button-primary button-hero button-forwards happyforms-step-save"><?php _e( 'Save form', 'happyforms' ); ?></button><% } %>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  </div>
5
 
6
  <div class="happyforms-step-progress">
1
  <script type="text/template" id="happyforms-form-steps-template">
2
  <div class="happyforms-action-buttons">
3
+ <% if ( step.index > 1 ) { %>
4
+ <%
5
+ var previousStepTitle = '<?php _e( 'Build', 'happyforms' ); ?>';
6
+
7
+ if ( 3 === step.index ) {
8
+ previousStepTitle = '<?php _e( 'Setup', 'happyforms' ); ?>';
9
+ }
10
+ %>
11
+ <button class="button button-secondary button-hero happyforms-step-previous"><i class="fa fa-lg fa-arrow-circle-o-left" aria-hidden="true"></i> <%= previousStepTitle %></button>
12
+ <% } %>
13
+ <% if ( step.index < step.count ) { %>
14
+ <%
15
+ var nextStepTitle = '<?php _e( 'Setup', 'happyforms' ); ?>';
16
+
17
+ if ( 2 === step.index ) {
18
+ nextStepTitle = '<?php _e( 'Style', 'happyforms' ); ?>';
19
+ }
20
+ %>
21
+ <button class="button button-primary button-hero button-forwards happyforms-step-next"><%= nextStepTitle %> <i class="fa fa-lg fa-arrow-circle-o-right" aria-hidden="true"></i></button>
22
+ <% } else { %>
23
+ <button class="button button-primary button-hero button-forwards happyforms-step-save"><?php _e( 'Finish', 'happyforms' ); ?></button>
24
+ <% } %>
25
  </div>
26
 
27
  <div class="happyforms-step-progress">
inc/templates/partials/form-confirm-preview.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <div class="happyforms-form__part happyforms-part happyforms-part--submit">
2
+ <input type="submit" class="happyforms-submit happyforms-button--submit" value="<?php echo esc_attr( happyforms_get_form_property( $form, 'submit_button_label' ) ); ?>" data-step="<?php echo happyforms_get_last_step( $form, true ); ?>" />
3
+ <a href="#" class="submit"><?php _e( 'Edit', 'happyforms' ); ?></a>
4
+ </div>
inc/templates/partials/form-submit-preview.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <div class="happyforms-form__part happyforms-part happyforms-part--submit">
2
+ <input type="submit" class="happyforms-submit happyforms-button--submit" value="<?php echo esc_attr( happyforms_get_form_property( $form, 'review_button_label' ) ); ?>" <?php if ( happyforms_get_form_property( $form, 'disable_submit_until_valid' ) ) : ?> disabled<?php endif; ?>>
3
+ </div>
inc/templates/partials/form-submit.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <div class="happyforms-form__part happyforms-part happyforms-part--submit">
2
+ <input type="submit" class="happyforms-submit happyforms-button--submit" value="<?php echo esc_attr( happyforms_get_form_property( $form, 'submit_button_label' ) ); ?>" <?php if ( happyforms_get_form_property( $form, 'disable_submit_until_valid' ) ) : ?> disabled<?php endif; ?>>
3
+ </div>
inc/templates/parts/customize-address.php CHANGED
@@ -53,12 +53,12 @@
53
  </p>
54
  <p class="description">
55
  <?php printf(
56
- '%s <a href="https://developers.google.com/places/web-service/get-api-key" target="_blank">%s</a>.',
57
  __( 'Address autocompletion requires a', 'happyforms' ),
58
  __( 'Google Places API key', 'happyforms' )
59
  ); ?>
60
  <?php printf(
61
- '%s <a href="https://developers.google.com/maps/documentation/geocoding/start" target="_blank">%s</a>.',
62
  __( 'Geolocation requires a', 'happyforms' ),
63
  __( 'Google Geocoding API key', 'happyforms' )
64
  ); ?>
53
  </p>
54
  <p class="description">
55
  <?php printf(
56
+ '%s <a href="https://developers.google.com/places/web-service/get-api-key" target="_blank" class="external">%s</a>.',
57
  __( 'Address autocompletion requires a', 'happyforms' ),
58
  __( 'Google Places API key', 'happyforms' )
59
  ); ?>
60
  <?php printf(
61
+ '%s <a href="https://developers.google.com/maps/documentation/geocoding/start" target="_blank" class="external">%s</a>.',
62
  __( 'Geolocation requires a', 'happyforms' ),
63
  __( 'Google Geocoding API key', 'happyforms' )
64
  ); ?>
inc/templates/parts/customize-number.php CHANGED
@@ -34,11 +34,11 @@
34
  </p>
35
  <div class="min-max-wrapper happyforms-customize-controls-wrap--side-by-side" style="display: <%= (instance.masked == 0) ? 'flex' : 'none' %>">
36
  <p>
37
- <label for="<%= instance.id %>_min_value"><?php _e( 'Minimum accepted value', 'happyforms' ); ?></label>
38
  <input type="text" id="<%= instance.id %>_min_value" class="widefat title" value="<%= instance.min_value %>" data-bind="min_value" />
39
  </p>
40
  <p>
41
- <label for="<%= instance.id %>_max_value"><?php _e( 'Maximum accepted value', 'happyforms' ); ?></label>
42
  <input type="text" id="<%= instance.id %>_max_value" class="widefat title" value="<%= instance.max_value %>" data-bind="max_value" />
43
  </p>
44
  </div>
34
  </p>
35
  <div class="min-max-wrapper happyforms-customize-controls-wrap--side-by-side" style="display: <%= (instance.masked == 0) ? 'flex' : 'none' %>">
36
  <p>
37
+ <label for="<%= instance.id %>_min_value"><?php _e( 'Minimum value', 'happyforms' ); ?></label>
38
  <input type="text" id="<%= instance.id %>_min_value" class="widefat title" value="<%= instance.min_value %>" data-bind="min_value" />
39
  </p>
40
  <p>
41
+ <label for="<%= instance.id %>_max_value"><?php _e( 'Maximum value', 'happyforms' ); ?></label>
42
  <input type="text" id="<%= instance.id %>_max_value" class="widefat title" value="<%= instance.max_value %>" data-bind="max_value" />
43
  </p>
44
  </div>
inc/templates/parts/customize-phone.php CHANGED
@@ -10,7 +10,7 @@
10
  <option value="above"<%= (instance.label_placement == 'above') ? ' selected' : '' %>><?php _e( 'Above', 'happyforms' ); ?></option>
11
  <option value="left"<%= (instance.label_placement == 'left') ? ' selected' : '' %>><?php _e( 'Left', 'happyforms' ); ?></option>
12
  <option value="below"<%= (instance.label_placement == 'below') ? ' selected' : '' %>><?php _e( 'Below', 'happyforms' ); ?></option>
13
- <option value="inside"<%= (instance.label_placement == 'inside') ? ' selected' : '' %>><?php _e( 'Inside', 'happyforms' ); ?></option>
14
  <option value="as_placeholder"<%= (instance.label_placement == 'as_placeholder') ? ' selected' : '' %>><?php _e( 'Display as placeholder', 'happyforms' ); ?></option>
15
  </select>
16
  </p>
10
  <option value="above"<%= (instance.label_placement == 'above') ? ' selected' : '' %>><?php _e( 'Above', 'happyforms' ); ?></option>
11
  <option value="left"<%= (instance.label_placement == 'left') ? ' selected' : '' %>><?php _e( 'Left', 'happyforms' ); ?></option>
12
  <option value="below"<%= (instance.label_placement == 'below') ? ' selected' : '' %>><?php _e( 'Below', 'happyforms' ); ?></option>
13
+ <option value="inside"<%= (instance.label_placement == 'inside') ? ' selected' : '' %>><?php _e( 'Inside input', 'happyforms' ); ?></option>
14
  <option value="as_placeholder"<%= (instance.label_placement == 'as_placeholder') ? ' selected' : '' %>><?php _e( 'Display as placeholder', 'happyforms' ); ?></option>
15
  </select>
16
  </p>
inc/templates/parts/customize-scale.php CHANGED
@@ -63,11 +63,11 @@
63
  </p>
64
  <div class="happyforms-customize-controls-wrap--side-by-side">
65
  <p>
66
- <label for="<%= instance.id %>_min_label"><?php _e( 'Minimum value label', 'happyforms' ); ?></label>
67
  <input type="text" id="<%= instance.id %>_min_label" class="widefat title" value="<%= instance.min_label %>" data-bind="min_label" />
68
  </p>
69
  <p>
70
- <label for="<%= instance.id %>_max_label"><?php _e( 'Maximum value label', 'happyforms' ); ?></label>
71
  <input type="text" id="<%= instance.id %>_max_label" class="widefat title" value="<%= instance.max_label %>" data-bind="max_label" />
72
  </p>
73
  </div>
63
  </p>
64
  <div class="happyforms-customize-controls-wrap--side-by-side">
65
  <p>
66
+ <label for="<%= instance.id %>_min_label"><?php _e( 'Min value label', 'happyforms' ); ?></label>
67
  <input type="text" id="<%= instance.id %>_min_label" class="widefat title" value="<%= instance.min_label %>" data-bind="min_label" />
68
  </p>
69
  <p>
70
+ <label for="<%= instance.id %>_max_label"><?php _e( 'Max value label', 'happyforms' ); ?></label>
71
  <input type="text" id="<%= instance.id %>_max_label" class="widefat title" value="<%= instance.max_label %>" data-bind="max_label" />
72
  </p>
73
  </div>
inc/templates/parts/frontend-address.php CHANGED
@@ -6,11 +6,14 @@
6
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
7
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
8
  <?php endif; ?>
 
 
 
9
  <?php if ( 'simple' === $part['mode'] ) : ?>
10
  <div class="happyforms-part-el-wrap">
11
  <div class="happyforms-part__el">
12
  <div class="happyforms-part__dummy-input">
13
- <input id="<?php happyforms_the_part_id( $part, $form ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>[full]" class="address-full" type="text" value="<?php happyforms_the_part_value( $part, $form, 'full' ); ?>" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> />
14
  <?php happyforms_geolocation_link( $part ); ?>
15
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
16
  <?php happyforms_the_part_label( $part, $form ); ?>
@@ -22,7 +25,7 @@
22
  <div class="happyforms-part-el-wrap">
23
  <div class="happyforms-part__el">
24
  <div class="happyforms-part__dummy-input">
25
- <input id="<?php happyforms_the_part_id( $part, $form ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>[full]" class="happyforms-part--address__autocomplete address-full" type="text" value="<?php happyforms_the_part_value( $part, $form, 'full' ); ?>" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> autocomplete="off" />
26
  <?php happyforms_geolocation_link( $part ); ?>
27
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
28
  <?php happyforms_the_part_label( $part, $form ); ?>
@@ -35,7 +38,7 @@
35
  <div class="happyforms-part-el-wrap">
36
  <div class="happyforms-part__el">
37
  <div class="happyforms-part__dummy-input">
38
- <input id="<?php happyforms_the_part_id( $part, $form ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>[country]" class="happyforms-part--address__autocomplete address-country" type="text" value="<?php happyforms_the_part_value( $part, $form, 'country' ); ?>" placeholder="<?php _e( 'Country', 'happyforms' ); ?>" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> autocomplete="off" />
39
  <?php happyforms_geolocation_link( $part ); ?>
40
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
41
  <?php happyforms_the_part_label( $part, $form ); ?>
@@ -48,16 +51,19 @@
48
  <div class="happyforms-part-el-wrap">
49
  <div class="happyforms-part__el">
50
  <div class="happyforms-part__dummy-input">
51
- <input id ="<?php happyforms_the_part_id( $part, $form ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>[country]" class="happyforms-part--address__autocomplete address-country" type="text" value="<?php happyforms_the_part_value( $part, $form, 'country' ); ?>" placeholder="<?php _e( 'Country', 'happyforms' ); ?>" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> autocomplete="off" />
52
  <?php happyforms_geolocation_link( $part ); ?>
53
  </div>
54
  <div class="happyforms-part--address__results"></div>
55
  </div>
56
  <div class="happyforms-part__el">
57
- <input name="<?php happyforms_the_part_name( $part, $form ); ?>[city]" class="address-city" type="text" value="<?php happyforms_the_part_value( $part, $form, 'city' ); ?>" placeholder="<?php _e( 'City', 'happyforms' ); ?>" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> />
58
  </div>
59
  </div>
60
  <?php endif; ?>
 
 
 
61
  <?php happyforms_print_part_description( $part ); ?>
62
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
63
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
6
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
7
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
8
  <?php endif; ?>
9
+
10
+ <?php do_action( 'happyforms_part_input_before', $part, $form ); ?>
11
+
12
  <?php if ( 'simple' === $part['mode'] ) : ?>
13
  <div class="happyforms-part-el-wrap">
14
  <div class="happyforms-part__el">
15
  <div class="happyforms-part__dummy-input">
16
+ <input id="<?php happyforms_the_part_id( $part, $form ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>[full]" class="address-full" type="text" value="<?php happyforms_the_part_value( $part, $form, 'full' ); ?>" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> <?php happyforms_the_part_attributes( $part, $form, 'full' ); ?> />
17
  <?php happyforms_geolocation_link( $part ); ?>
18
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
19
  <?php happyforms_the_part_label( $part, $form ); ?>
25
  <div class="happyforms-part-el-wrap">
26
  <div class="happyforms-part__el">
27
  <div class="happyforms-part__dummy-input">
28
+ <input id="<?php happyforms_the_part_id( $part, $form ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>[full]" class="happyforms-part--address__autocomplete address-full" type="text" value="<?php happyforms_the_part_value( $part, $form, 'full' ); ?>" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> autocomplete="off" <?php happyforms_the_part_attributes( $part, $form, 'full' ); ?> />
29
  <?php happyforms_geolocation_link( $part ); ?>
30
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
31
  <?php happyforms_the_part_label( $part, $form ); ?>
38
  <div class="happyforms-part-el-wrap">
39
  <div class="happyforms-part__el">
40
  <div class="happyforms-part__dummy-input">
41
+ <input id="<?php happyforms_the_part_id( $part, $form ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>[country]" class="happyforms-part--address__autocomplete address-country" type="text" value="<?php happyforms_the_part_value( $part, $form, 'country' ); ?>" placeholder="<?php _e( 'Country', 'happyforms' ); ?>" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> autocomplete="off" <?php happyforms_the_part_attributes( $part, $form, 'country' ); ?> />
42
  <?php happyforms_geolocation_link( $part ); ?>
43
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
44
  <?php happyforms_the_part_label( $part, $form ); ?>
51
  <div class="happyforms-part-el-wrap">
52
  <div class="happyforms-part__el">
53
  <div class="happyforms-part__dummy-input">
54
+ <input id ="<?php happyforms_the_part_id( $part, $form ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>[country]" class="happyforms-part--address__autocomplete address-country" type="text" value="<?php happyforms_the_part_value( $part, $form, 'country' ); ?>" placeholder="<?php _e( 'Country', 'happyforms' ); ?>" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> autocomplete="off" <?php happyforms_the_part_attributes( $part, $form, 'country' ); ?> />
55
  <?php happyforms_geolocation_link( $part ); ?>
56
  </div>
57
  <div class="happyforms-part--address__results"></div>
58
  </div>
59
  <div class="happyforms-part__el">
60
+ <input name="<?php happyforms_the_part_name( $part, $form ); ?>[city]" class="address-city" type="text" value="<?php happyforms_the_part_value( $part, $form, 'city' ); ?>" placeholder="<?php _e( 'City', 'happyforms' ); ?>" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> <?php happyforms_the_part_attributes( $part, $form, 'city' ); ?> />
61
  </div>
62
  </div>
63
  <?php endif; ?>
64
+
65
+ <?php do_action( 'happyforms_part_input_after', $part, $form ); ?>
66
+
67
  <?php happyforms_print_part_description( $part ); ?>
68
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
69
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
inc/templates/parts/frontend-checkbox.php CHANGED
@@ -4,6 +4,9 @@
4
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
5
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
6
  <?php endif; ?>
 
 
 
7
  <div class="happyforms-part__el">
8
  <?php
9
  $options = happyforms_get_part_options( $part['options'], $part, $form );
@@ -15,12 +18,15 @@
15
  $checked = ( $is_default || $is_checked ) ? 'checked="checked"' : '';
16
  ?>
17
  <label class="option-label" id="<?php echo esc_attr( $option['id'] ); ?>">
18
- <input type="checkbox" class="happyforms-visuallyhidden" name="<?php happyforms_the_part_name( $part, $form ); ?>[]" value="<?php echo esc_attr( $option['label'] ); ?>" <?php echo $checked; ?>>
19
  <span class="checkmark"><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24"><path fill="currentColor" d="M20.285 2l-11.285 11.567-5.286-5.011-3.714 3.716 9 8.728 15-15.285z"/></svg></span>
20
  <span class="label"><?php echo esc_attr( $option['label'] ); ?></span>
21
  </label>
22
  <?php endforeach; ?>
23
  </div>
 
 
 
24
  <?php happyforms_print_part_description( $part ); ?>
25
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
26
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
4
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
5
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
6
  <?php endif; ?>
7
+
8
+ <?php do_action( 'happyforms_part_input_before', $part, $form ); ?>
9
+
10
  <div class="happyforms-part__el">
11
  <?php
12
  $options = happyforms_get_part_options( $part['options'], $part, $form );
18
  $checked = ( $is_default || $is_checked ) ? 'checked="checked"' : '';
19
  ?>
20
  <label class="option-label" id="<?php echo esc_attr( $option['id'] ); ?>">
21
+ <input type="checkbox" class="happyforms-visuallyhidden" name="<?php happyforms_the_part_name( $part, $form ); ?>[]" value="<?php echo esc_attr( $option['label'] ); ?>" <?php echo $checked; ?> <?php happyforms_the_part_attributes( $part, $form ); ?>>
22
  <span class="checkmark"><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24"><path fill="currentColor" d="M20.285 2l-11.285 11.567-5.286-5.011-3.714 3.716 9 8.728 15-15.285z"/></svg></span>
23
  <span class="label"><?php echo esc_attr( $option['label'] ); ?></span>
24
  </label>
25
  <?php endforeach; ?>
26
  </div>
27
+
28
+ <?php do_action( 'happyforms_part_input_after', $part, $form ); ?>
29
+
30
  <?php happyforms_print_part_description( $part ); ?>
31
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
32
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
inc/templates/parts/frontend-date-day.php CHANGED
@@ -1,6 +1,6 @@
1
- <?php
2
  $current_timestamp = current_time( 'timestamp', false );
3
- $day_value = ( 'current' === $part['default_datetime'] ) ? date( 'j', $current_timestamp ) : intval( happyforms_get_part_value( $part, $form, 'day' ) ); ?>
4
  <div class="happyforms-part-date__date-input">
5
  <div class="happyforms-custom-select" data-searchable="true">
6
  <div class="happyforms-part__select-wrap">
@@ -17,7 +17,7 @@ $day_value = ( 'current' === $part['default_datetime'] ) ? date( 'j', $current_t
17
  $placeholder_value = __( 'Day', 'happyforms' );
18
  }
19
  ?>
20
- <input type="text" value="<?php echo ( ! empty( $default_value ) && $default_value !== 0 ) ? $default_value : ''; ?>" placeholder="<?php echo $placeholder_value; ?>" placeholder="<?php echo $placeholder_value; ?>" class="happyforms-part__el happyforms-part__el--text-input"<?php if ( 1 === $part['required'] ) : ?> required aria-required="true"<?php endif; ?> />
21
 
22
  <ul class="happyforms-part-select__dropdown happyforms-custom-select-dropdown">
23
  <li data-value=""><?php _e( 'Day', 'happyforms' ); ?></li>
@@ -36,7 +36,7 @@ $day_value = ( 'current' === $part['default_datetime'] ) ? date( 'j', $current_t
36
  <?php endfor; ?>
37
  </ul>
38
 
39
- <select name="<?php happyforms_the_part_name( $part, $form ); ?>[day]">
40
  <option value=""><?php _e( 'Day', 'happyforms' ); ?></option>
41
  <?php for ( $i = 1; $i <= 31; $i++ ) : ?>
42
  <option value="<?php echo $i; ?>" <?php selected( $day_value, $i ); ?>><?php echo $i; ?></option>
1
+ <?php
2
  $current_timestamp = current_time( 'timestamp', false );
3
+ $day_value = ( 'current' === $part['default_datetime'] ) ? date( 'j', $current_timestamp ) : intval( happyforms_get_part_value( $part, $form, 'day' ) ); ?>
4
  <div class="happyforms-part-date__date-input">
5
  <div class="happyforms-custom-select" data-searchable="true">
6
  <div class="happyforms-part__select-wrap">
17
  $placeholder_value = __( 'Day', 'happyforms' );
18
  }
19
  ?>
20
+ <input type="text" value="<?php echo ( ! empty( $default_value ) && $default_value !== 0 ) ? $default_value : ''; ?>" placeholder="<?php echo $placeholder_value; ?>" placeholder="<?php echo $placeholder_value; ?>" class="happyforms-part__el happyforms-part__el--text-input"<?php if ( 1 === $part['required'] ) : ?> required aria-required="true"<?php endif; ?> <?php happyforms_the_part_attributes( $part, $form ); ?> />
21
 
22
  <ul class="happyforms-part-select__dropdown happyforms-custom-select-dropdown">
23
  <li data-value=""><?php _e( 'Day', 'happyforms' ); ?></li>
36
  <?php endfor; ?>
37
  </ul>
38
 
39
+ <select name="<?php happyforms_the_part_name( $part, $form ); ?>[day]" <?php happyforms_the_part_attributes( $part, $form ); ?>>
40
  <option value=""><?php _e( 'Day', 'happyforms' ); ?></option>
41
  <?php for ( $i = 1; $i <= 31; $i++ ) : ?>
42
  <option value="<?php echo $i; ?>" <?php selected( $day_value, $i ); ?>><?php echo $i; ?></option>
inc/templates/parts/frontend-date-month.php CHANGED
@@ -1,10 +1,10 @@
1
- <?php
2
  $current_timestamp = current_time( 'timestamp', false );
3
  $month_value = ( 'current' === $part['default_datetime'] ) ? date( 'n', $current_timestamp ) : intval( happyforms_get_part_value( $part, $form, 'month' ) ); ?>
4
  <div class="happyforms-part-date__date-input">
5
  <div class="happyforms-custom-select" data-searchable="true">
6
  <div class="happyforms-part__select-wrap">
7
- <?php
8
  $months = happyforms_get_months();
9
 
10
  $default_value = $month_value;
@@ -19,7 +19,7 @@ $month_value = ( 'current' === $part['default_datetime'] ) ? date( 'n', $current
19
  $placeholder_value = __( 'Month', 'happyforms' );
20
  }
21
  ?>
22
- <input type="text" value="<?php echo ( ! empty( $default_value ) && $default_value !== 0 ) ? $default_value : ''; ?>" placeholder="<?php echo $placeholder_value; ?>" class="happyforms-part__el happyforms-part__el--text-input"<?php if ( 1 === $part['required'] ) : ?> required aria-required="true"<?php endif; ?> />
23
 
24
  <ul class="happyforms-part-select__dropdown happyforms-custom-select-dropdown">
25
  <li data-value=""><?php _e( 'Month', 'happyforms' ); ?></li>
@@ -38,9 +38,9 @@ $month_value = ( 'current' === $part['default_datetime'] ) ? date( 'n', $current
38
  <?php endfor; ?>
39
  </ul>
40
 
41
- <select name="<?php happyforms_the_part_name( $part, $form ); ?>[month]">
42
  <option value=""><?php _e( 'Month', 'happyforms' ); ?></option>
43
-
44
  <?php for ( $i = 1; $i <= 12; $i++ ) : ?>
45
  <option value="<?php echo $i; ?>" <?php selected( $month_value, $i ); ?>><?php echo $months[$i]; ?></option>
46
  <?php endfor; ?>
1
+ <?php
2
  $current_timestamp = current_time( 'timestamp', false );
3
  $month_value = ( 'current' === $part['default_datetime'] ) ? date( 'n', $current_timestamp ) : intval( happyforms_get_part_value( $part, $form, 'month' ) ); ?>
4
  <div class="happyforms-part-date__date-input">
5
  <div class="happyforms-custom-select" data-searchable="true">
6
  <div class="happyforms-part__select-wrap">
7
+ <?php
8
  $months = happyforms_get_months();
9
 
10
  $default_value = $month_value;
19
  $placeholder_value = __( 'Month', 'happyforms' );
20
  }
21
  ?>
22
+ <input type="text" value="<?php echo ( ! empty( $default_value ) && $default_value !== 0 ) ? $default_value : ''; ?>" placeholder="<?php echo $placeholder_value; ?>" class="happyforms-part__el happyforms-part__el--text-input"<?php if ( 1 === $part['required'] ) : ?> required aria-required="true"<?php endif; ?> <?php happyforms_the_part_attributes( $part, $form ); ?> />
23
 
24
  <ul class="happyforms-part-select__dropdown happyforms-custom-select-dropdown">
25
  <li data-value=""><?php _e( 'Month', 'happyforms' ); ?></li>
38
  <?php endfor; ?>
39
  </ul>
40
 
41
+ <select name="<?php happyforms_the_part_name( $part, $form ); ?>[month]" <?php happyforms_the_part_attributes( $part, $form ); ?>>
42
  <option value=""><?php _e( 'Month', 'happyforms' ); ?></option>
43
+
44
  <?php for ( $i = 1; $i <= 12; $i++ ) : ?>
45
  <option value="<?php echo $i; ?>" <?php selected( $month_value, $i ); ?>><?php echo $months[$i]; ?></option>
46
  <?php endfor; ?>
inc/templates/parts/frontend-date.php CHANGED
@@ -7,9 +7,12 @@
7
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
8
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
9
  <?php endif; ?>
 
10
  <div class="happyforms-part__el">
 
 
11
  <?php if ( $part['date_type'] === 'datetime' || $part['date_type'] === 'date' ) : ?>
12
- <?php
13
  if ( 'month_first' === happyforms_get_site_date_format() ) {
14
  require( 'frontend-date-month.php' );
15
  require( 'frontend-date-day.php' );
@@ -35,7 +38,7 @@
35
  $placeholder_value = __( 'Year', 'happyforms' );
36
  }
37
  ?>
38
- <input type="text" value="<?php echo ( ! empty( $default_value ) && $default_value !== 0 ) ? $default_value : ''; ?>" placeholder="<?php echo $placeholder_value; ?>" class="happyforms-part__el happyforms-part__el--text-input"<?php if ( 1 === $part['required'] ) : ?> required aria-required="true"<?php endif; ?> />
39
 
40
  <ul class="happyforms-part-select__dropdown happyforms-custom-select-dropdown">
41
  <li data-value=""><?php _e( 'Year', 'happyforms' ); ?></li>
@@ -58,11 +61,11 @@
58
  ?>
59
  </ul>
60
 
61
- <select name="<?php happyforms_the_part_name( $part, $form ); ?>[year]">
62
  <option value=""><?php _e( 'Year', 'happyforms' ); ?></option>
63
  <?php
64
  $option_template = '<option value="%d" %s>%d</option>';
65
-
66
  if ( 'desc' === $order ) {
67
  for ( $i = $max_year; $i >= $min_year; $i-- ) {
68
  printf( $option_template, $i, selected( $year_value, $i ), $i );
@@ -72,7 +75,7 @@
72
  printf( $option_template, $i, selected( $year_value, $i ), $i );
73
  }
74
  }
75
- ?>
76
  </select>
77
  </div>
78
  </div>
@@ -94,7 +97,7 @@
94
  $hour_value = ( 'current' === $part['default_datetime'] ) ? date( $hour_date_string, $current_timestamp ) : $happyforms_hour_value;
95
  ?>
96
  <div class="happyforms-part--date__input-wrap happyforms-part-date__time-input happyforms-part-date__time-input--hours">
97
- <input type="text" name="<?php happyforms_the_part_name( $part, $form ); ?>[hour]" min="<?php echo $part['min_hour']; ?>" max="<?php echo $part['max_hour']; ?>" maxlength="2" pattern="<?php echo $hour_pattern; ?>" autocomplete="off" value="<?php echo $hour_value; ?>"<?php if ( 1 == $part['required'] ) : ?> required aria-required="true"<?php endif; ?>>
98
  <span class="happyforms-spinner-arrow happyforms-spinner-arrow--up"></span>
99
  <span class="happyforms-spinner-arrow happyforms-spinner-arrow--down"></span>
100
  </div>
@@ -106,7 +109,7 @@
106
  $minute_value = ( 'current' === $part['default_datetime'] ) ? date( 'i', $current_timestamp ) : $happyforms_minute_value;
107
  ?>
108
  <div class="happyforms-part--date__input-wrap happyforms-part-date__time-input happyforms-part-date__time-input--minutes">
109
- <input type="text" name="<?php happyforms_the_part_name( $part, $form ); ?>[minute]" min="0" max="59" step="<?php echo $part['minute_step']; ?>" maxlength="2" pattern="([0-5][0-9])" autocomplete="off" value="<?php echo $minute_value; ?>"<?php if ( 1 == $part['required'] ) : ?> required aria-required="true"<?php endif; ?>>
110
  <span class="happyforms-spinner-arrow happyforms-spinner-arrow--up"></span>
111
  <span class="happyforms-spinner-arrow happyforms-spinner-arrow--down"></span>
112
  </div>
@@ -131,14 +134,14 @@
131
  }
132
  ?>
133
 
134
- <input type="text" value="<?php echo ( ! empty( $default_value ) && $default_value !== 0 ) ? $default_value : ''; ?>" placeholder="<?php echo $placeholder_value; ?>" class="happyforms-part__el happyforms-part__el--text-input"<?php if ( 1 === $part['required'] ) : ?> required aria-required="true"<?php endif; ?> />
135
 
136
  <ul class="happyforms-part-select__dropdown happyforms-custom-select-dropdown">
137
  <li data-value="AM" data-label="AM" class="happyforms-custom-select-dropdown__item default<?php echo ( 'AM' === $default_value ) ? ' current' : ''; ?>" tabindex="0">AM</li>
138
  <li data-value="PM" data-label="PM" class="happyforms-custom-select-dropdown__item<?php echo ( 'PM' === $default_value ) ? ' current' : ''; ?>" tabindex="0">PM</li>
139
  </ul>
140
 
141
- <select name="<?php happyforms_the_part_name( $part, $form ); ?>[period]">
142
  <option value="AM" <?php selected( $period_value, 'AM' ); ?>><?php _e( 'AM', 'happyforms' ); ?></option>
143
  <option value="PM" <?php selected( $period_value, 'PM' ); ?>><?php _e( 'PM', 'happyforms' ); ?></option>
144
  </select>
@@ -147,7 +150,10 @@
147
  </div>
148
  <?php endif; ?>
149
  <?php endif; ?>
 
 
150
  </div>
 
151
  <?php happyforms_print_part_description( $part ); ?>
152
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
153
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
7
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
8
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
9
  <?php endif; ?>
10
+
11
  <div class="happyforms-part__el">
12
+ <?php do_action( 'happyforms_part_input_before', $part, $form ); ?>
13
+
14
  <?php if ( $part['date_type'] === 'datetime' || $part['date_type'] === 'date' ) : ?>
15
+ <?php
16
  if ( 'month_first' === happyforms_get_site_date_format() ) {
17
  require( 'frontend-date-month.php' );
18
  require( 'frontend-date-day.php' );
38
  $placeholder_value = __( 'Year', 'happyforms' );
39
  }
40
  ?>
41
+ <input type="text" value="<?php echo ( ! empty( $default_value ) && $default_value !== 0 ) ? $default_value : ''; ?>" placeholder="<?php echo $placeholder_value; ?>" class="happyforms-part__el happyforms-part__el--text-input"<?php if ( 1 === $part['required'] ) : ?> required aria-required="true"<?php endif; ?> <?php happyforms_the_part_attributes( $part, $form ); ?> />
42
 
43
  <ul class="happyforms-part-select__dropdown happyforms-custom-select-dropdown">
44
  <li data-value=""><?php _e( 'Year', 'happyforms' ); ?></li>
61
  ?>
62
  </ul>
63
 
64
+ <select name="<?php happyforms_the_part_name( $part, $form ); ?>[year]" <?php happyforms_the_part_attributes( $part, $form ); ?>>
65
  <option value=""><?php _e( 'Year', 'happyforms' ); ?></option>
66
  <?php
67
  $option_template = '<option value="%d" %s>%d</option>';
68
+
69
  if ( 'desc' === $order ) {
70
  for ( $i = $max_year; $i >= $min_year; $i-- ) {
71
  printf( $option_template, $i, selected( $year_value, $i ), $i );
75
  printf( $option_template, $i, selected( $year_value, $i ), $i );
76
  }
77
  }
78
+ ?>
79
  </select>
80
  </div>
81
  </div>
97
  $hour_value = ( 'current' === $part['default_datetime'] ) ? date( $hour_date_string, $current_timestamp ) : $happyforms_hour_value;
98
  ?>
99
  <div class="happyforms-part--date__input-wrap happyforms-part-date__time-input happyforms-part-date__time-input--hours">
100
+ <input type="text" name="<?php happyforms_the_part_name( $part, $form ); ?>[hour]" min="<?php echo $part['min_hour']; ?>" max="<?php echo $part['max_hour']; ?>" maxlength="2" pattern="<?php echo $hour_pattern; ?>" autocomplete="off" value="<?php echo $hour_value; ?>"<?php if ( 1 == $part['required'] ) : ?> required aria-required="true"<?php endif; ?> <?php happyforms_the_part_attributes( $part, $form ); ?>>
101
  <span class="happyforms-spinner-arrow happyforms-spinner-arrow--up"></span>
102
  <span class="happyforms-spinner-arrow happyforms-spinner-arrow--down"></span>
103
  </div>
109
  $minute_value = ( 'current' === $part['default_datetime'] ) ? date( 'i', $current_timestamp ) : $happyforms_minute_value;
110
  ?>
111
  <div class="happyforms-part--date__input-wrap happyforms-part-date__time-input happyforms-part-date__time-input--minutes">
112
+ <input type="text" name="<?php happyforms_the_part_name( $part, $form ); ?>[minute]" min="0" max="59" step="<?php echo $part['minute_step']; ?>" maxlength="2" pattern="([0-5][0-9])" autocomplete="off" value="<?php echo $minute_value; ?>"<?php if ( 1 == $part['required'] ) : ?> required aria-required="true"<?php endif; ?> <?php happyforms_the_part_attributes( $part, $form ); ?>>
113
  <span class="happyforms-spinner-arrow happyforms-spinner-arrow--up"></span>
114
  <span class="happyforms-spinner-arrow happyforms-spinner-arrow--down"></span>
115
  </div>
134
  }
135
  ?>
136
 
137
+ <input type="text" value="<?php echo ( ! empty( $default_value ) && $default_value !== 0 ) ? $default_value : ''; ?>" placeholder="<?php echo $placeholder_value; ?>" class="happyforms-part__el happyforms-part__el--text-input"<?php if ( 1 === $part['required'] ) : ?> required aria-required="true"<?php endif; ?> <?php happyforms_the_part_attributes( $part, $form ); ?> />
138
 
139
  <ul class="happyforms-part-select__dropdown happyforms-custom-select-dropdown">
140
  <li data-value="AM" data-label="AM" class="happyforms-custom-select-dropdown__item default<?php echo ( 'AM' === $default_value ) ? ' current' : ''; ?>" tabindex="0">AM</li>
141
  <li data-value="PM" data-label="PM" class="happyforms-custom-select-dropdown__item<?php echo ( 'PM' === $default_value ) ? ' current' : ''; ?>" tabindex="0">PM</li>
142
  </ul>
143
 
144
+ <select name="<?php happyforms_the_part_name( $part, $form ); ?>[period]" <?php happyforms_the_part_attributes( $part, $form ); ?>>
145
  <option value="AM" <?php selected( $period_value, 'AM' ); ?>><?php _e( 'AM', 'happyforms' ); ?></option>
146
  <option value="PM" <?php selected( $period_value, 'PM' ); ?>><?php _e( 'PM', 'happyforms' ); ?></option>
147
  </select>
150
  </div>
151
  <?php endif; ?>
152
  <?php endif; ?>
153
+
154
+ <?php do_action( 'happyforms_part_input_after', $part, $form ); ?>
155
  </div>
156
+
157
  <?php happyforms_print_part_description( $part ); ?>
158
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
159
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
inc/templates/parts/frontend-email.php CHANGED
@@ -6,7 +6,10 @@
6
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
7
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
8
  <?php endif; ?>
9
- <input type="email" id="<?php happyforms_the_part_id( $part, $form ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>" value="<?php happyforms_the_part_value( $part, $form, 0 ); ?>" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>" class="happyforms-part__el happyforms-part__el--text-input" <?php if ( 1 === $part['required'] ) : ?> required aria-required="true"<?php endif; ?> />
 
 
 
10
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
11
  <?php happyforms_the_part_label( $part, $form ); ?>
12
  <?php endif; ?>
@@ -14,13 +17,16 @@
14
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
15
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
16
  <?php endif; ?>
 
 
 
17
  </div>
18
  <?php if ( 1 === intval( $part['confirmation_field'] ) ) : ?>
19
  <div class="happyforms-part-wrap happyforms-part-wrap--confirmation" id="<?php happyforms_the_part_id( $part, $form ); ?>-part_confirmation">
20
  <?php if ( 'as_placeholder' !== $part['label_placement'] ) : ?>
21
  <?php happyforms_the_part_confirmation_label( $part, $form ); ?>
22
  <?php endif; ?>
23
- <input type="email" id="<?php happyforms_the_part_id( $part, $form ); ?>_confirmation" name="<?php happyforms_the_part_name( $part, $form ); ?>_confirmation" value="<?php happyforms_the_part_value( $part, $form, 1 ); ?>" class="happyforms-part__el happyforms-part__el--text-input happyforms-confirmation-input" data-confirmation-of="<?php echo esc_attr( $part['id'] ); ?>" <?php if ( 1 === $part['required'] ) : ?> required aria-required="true"<?php endif; ?> />
24
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
25
  <?php happyforms_the_part_confirmation_label( $part, $form ); ?>
26
  <?php endif; ?>
6
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
7
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
8
  <?php endif; ?>
9
+
10
+ <?php do_action( 'happyforms_part_input_before', $part, $form ); ?>
11
+
12
+ <input type="email" id="<?php happyforms_the_part_id( $part, $form ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>" value="<?php happyforms_the_part_value( $part, $form, 0 ); ?>" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>" class="happyforms-part__el happyforms-part__el--text-input" <?php if ( 1 === $part['required'] ) : ?> required aria-required="true"<?php endif; ?> <?php happyforms_the_part_attributes( $part, $form, 0 ); ?> />
13
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
14
  <?php happyforms_the_part_label( $part, $form ); ?>
15
  <?php endif; ?>
17
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
18
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
19
  <?php endif; ?>
20
+
21
+ <?php do_action( 'happyforms_part_input_after', $part, $form ); ?>
22
+
23
  </div>
24
  <?php if ( 1 === intval( $part['confirmation_field'] ) ) : ?>
25
  <div class="happyforms-part-wrap happyforms-part-wrap--confirmation" id="<?php happyforms_the_part_id( $part, $form ); ?>-part_confirmation">
26
  <?php if ( 'as_placeholder' !== $part['label_placement'] ) : ?>
27
  <?php happyforms_the_part_confirmation_label( $part, $form ); ?>
28
  <?php endif; ?>
29
+ <input type="email" id="<?php happyforms_the_part_id( $part, $form ); ?>_confirmation" name="<?php happyforms_the_part_name( $part, $form ); ?>_confirmation" value="<?php happyforms_the_part_value( $part, $form, 1 ); ?>" class="happyforms-part__el happyforms-part__el--text-input happyforms-confirmation-input" data-confirmation-of="<?php echo esc_attr( $part['id'] ); ?>" <?php if ( 1 === $part['required'] ) : ?> required aria-required="true"<?php endif; ?> <?php happyforms_the_part_attributes( $part, $form, 1 ); ?> />
30
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
31
  <?php happyforms_the_part_confirmation_label( $part, $form ); ?>
32
  <?php endif; ?>
inc/templates/parts/frontend-legal.php CHANGED
@@ -1,16 +1,18 @@
1
  <div class="<?php happyforms_the_part_class( $part, $form ); ?>" id="<?php happyforms_the_part_id( $part, $form ); ?>-part" <?php happyforms_the_part_data_attributes( $part, $form ); ?>>
2
  <div class="happyforms-part-wrap">
3
- <div class="happyforms-part__el">
4
- <?php /*<input id="<?php happyforms_the_part_id( $part, $form ); ?>" type="checkbox" name="<?php happyforms_the_part_name( $part, $form ); ?>" value="yes" required aria-required="true" />
5
- <label for="<?php happyforms_the_part_id( $part, $form ); ?>">
6
- <?php echo html_entity_decode( $part['legal_text'] ); ?>
7
- </label>*/ ?>
8
- <label class="option-label">
9
- <input type="checkbox" class="happyforms-visuallyhidden" id="<?php happyforms_the_part_id( $part, $form ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>" value="yes" required aria-required="true">
10
- <span class="checkmark"><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24"><path fill="currentColor" d="M20.285 2l-11.285 11.567-5.286-5.011-3.714 3.716 9 8.728 15-15.285z"/></svg></span>
11
- <span class="label"><?php echo html_entity_decode( $part['legal_text'] ); ?></span>
12
- </label>
13
- </div>
 
 
14
  </div>
15
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
16
  </div>
1
  <div class="<?php happyforms_the_part_class( $part, $form ); ?>" id="<?php happyforms_the_part_id( $part, $form ); ?>-part" <?php happyforms_the_part_data_attributes( $part, $form ); ?>>
2
  <div class="happyforms-part-wrap">
3
+
4
+ <?php do_action( 'happyforms_part_input_before', $part, $form ); ?>
5
+
6
+ <div class="happyforms-part__el">
7
+ <label class="option-label">
8
+ <input type="checkbox" class="happyforms-visuallyhidden" id="<?php happyforms_the_part_id( $part, $form ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>" value="yes" required aria-required="true" <?php checked( happyforms_get_part_value( $part, $form ), 'yes' ); ?> <?php happyforms_the_part_attributes( $part, $form ); ?>>
9
+ <span class="checkmark"><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24"><path fill="currentColor" d="M20.285 2l-11.285 11.567-5.286-5.011-3.714 3.716 9 8.728 15-15.285z"/></svg></span>
10
+ <span class="label"><?php echo html_entity_decode( $part['legal_text'] ); ?></span>
11
+ </label>
12
+ </div>
13
+
14
+ <?php do_action( 'happyforms_part_input_after', $part, $form ); ?>
15
+
16
  </div>
17
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
18
  </div>
inc/templates/parts/frontend-multi-line-text.php CHANGED
@@ -6,10 +6,16 @@
6
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
7
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
8
  <?php endif; ?>
9
- <textarea id="<?php happyforms_the_part_id( $part, $form ); ?>" class="happyforms-part__el happyforms-part__el--text-input" name="<?php happyforms_the_part_name( $part, $form ); ?>" rows="5" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>"<?php if ( 1 === $part['required'] ) : ?> required aria-required="true"<?php endif; ?>><?php happyforms_the_part_value( $part, $form ); ?></textarea>
 
 
 
10
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
11
  <?php happyforms_the_part_label( $part, $form ); ?>
12
  <?php endif; ?>
 
 
 
13
  <?php happyforms_print_part_description( $part ); ?>
14
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
15
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
6
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
7
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
8
  <?php endif; ?>
9
+
10
+ <?php do_action( 'happyforms_part_input_before', $part, $form ); ?>
11
+
12
+ <textarea id="<?php happyforms_the_part_id( $part, $form ); ?>" class="happyforms-part__el happyforms-part__el--text-input" name="<?php happyforms_the_part_name( $part, $form ); ?>" rows="5" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>"<?php if ( 1 === $part['required'] ) : ?> required aria-required="true"<?php endif; ?> <?php happyforms_the_part_attributes( $part, $form ); ?>><?php happyforms_the_part_value( $part, $form ); ?></textarea>
13
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
14
  <?php happyforms_the_part_label( $part, $form ); ?>
15
  <?php endif; ?>
16
+
17
+ <?php do_action( 'happyforms_part_input_after', $part, $form ); ?>
18
+
19
  <?php happyforms_print_part_description( $part ); ?>
20
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
21
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
inc/templates/parts/frontend-number.php CHANGED
@@ -6,11 +6,17 @@
6
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
7
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
8
  <?php endif; ?>
 
 
 
9
  <?php if ( ! $part['masked'] ) : ?>
10
- <input id="<?php happyforms_the_part_id( $part, $form ); ?>" class="happyforms-part__el happyforms-part__el--text-input" type="number" value="<?php happyforms_the_part_value( $part, $form, 0 ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>" min="<?php echo esc_attr( $part['min_value'] ); ?>" max="<?php echo esc_attr( $part['max_value'] ); ?>" value="<?php echo esc_attr( $part['min_value'] ); ?>" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> />
11
  <?php else: ?>
12
- <input id="<?php happyforms_the_part_id( $part, $form ); ?>" class="happyforms-part__el happyforms-part__el--text-input happyforms-masked-input" type="text" value="<?php happyforms_the_part_value( $part, $form, 0 ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> />
13
  <?php endif; ?>
 
 
 
14
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
15
  <?php happyforms_the_part_label( $part, $form ); ?>
16
  <?php endif; ?>
@@ -25,9 +31,9 @@
25
  <?php happyforms_the_part_confirmation_label( $part, $form ); ?>
26
  <?php endif; ?>
27
  <?php if ( ! $part['masked'] ) : ?>
28
- <input id="<?php happyforms_the_part_id( $part, $form ); ?>_confirmation" class="happyforms-part__el happyforms-part__el--text-input happyforms-confirmation-input" type="number" name="<?php happyforms_the_part_name( $part, $form ); ?>_confirmation" value="<?php happyforms_the_part_value( $part, $form, 1 ); ?>" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>" min="<?php echo esc_attr( $part['min_value'] ); ?>" max="<?php echo esc_attr( $part['max_value'] ); ?>" value="<?php echo esc_attr( $part['min_value'] ); ?>" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> />
29
  <?php else: ?>
30
- <input id="<?php happyforms_the_part_id( $part, $form ); ?>_confirmation" class="happyforms-part__el happyforms-part__el--text-input happyforms-masked-input happyforms-confirmation-input" type="text" name="<?php happyforms_the_part_name( $part, $form ); ?>_confirmation" value="<?php happyforms_the_part_value( $part, $form, 1 ); ?>" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> />
31
  <?php endif; ?>
32
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
33
  <?php happyforms_the_part_confirmation_label( $part, $form ); ?>
6
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
7
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
8
  <?php endif; ?>
9
+
10
+ <?php do_action( 'happyforms_part_input_before', $part, $form ); ?>
11
+
12
  <?php if ( ! $part['masked'] ) : ?>
13
+ <input id="<?php happyforms_the_part_id( $part, $form ); ?>" class="happyforms-part__el happyforms-part__el--text-input" type="number" value="<?php happyforms_the_part_value( $part, $form, 0 ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>" min="<?php echo esc_attr( $part['min_value'] ); ?>" max="<?php echo esc_attr( $part['max_value'] ); ?>" value="<?php echo esc_attr( $part['min_value'] ); ?>" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> <?php happyforms_the_part_attributes( $part, $form, 0 ); ?> />
14
  <?php else: ?>
15
+ <input id="<?php happyforms_the_part_id( $part, $form ); ?>" class="happyforms-part__el happyforms-part__el--text-input happyforms-masked-input" type="text" value="<?php happyforms_the_part_value( $part, $form, 0 ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> <?php happyforms_the_part_attributes( $part, $form, 0 ); ?> />
16
  <?php endif; ?>
17
+
18
+ <?php do_action( 'happyforms_part_input_after', $part, $form ); ?>
19
+
20
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
21
  <?php happyforms_the_part_label( $part, $form ); ?>
22
  <?php endif; ?>
31
  <?php happyforms_the_part_confirmation_label( $part, $form ); ?>
32
  <?php endif; ?>
33
  <?php if ( ! $part['masked'] ) : ?>
34
+ <input id="<?php happyforms_the_part_id( $part, $form ); ?>_confirmation" class="happyforms-part__el happyforms-part__el--text-input happyforms-confirmation-input" type="number" name="<?php happyforms_the_part_name( $part, $form ); ?>_confirmation" value="<?php happyforms_the_part_value( $part, $form, 1 ); ?>" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>" min="<?php echo esc_attr( $part['min_value'] ); ?>" max="<?php echo esc_attr( $part['max_value'] ); ?>" value="<?php echo esc_attr( $part['min_value'] ); ?>" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> <?php happyforms_the_part_attributes( $part, $form, 1 ); ?> />
35
  <?php else: ?>
36
+ <input id="<?php happyforms_the_part_id( $part, $form ); ?>_confirmation" class="happyforms-part__el happyforms-part__el--text-input happyforms-masked-input happyforms-confirmation-input" type="text" name="<?php happyforms_the_part_name( $part, $form ); ?>_confirmation" value="<?php happyforms_the_part_value( $part, $form, 1 ); ?>" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> <?php happyforms_the_part_attributes( $part, $form, 1 ); ?> />
37
  <?php endif; ?>
38
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
39
  <?php happyforms_the_part_confirmation_label( $part, $form ); ?>
inc/templates/parts/frontend-phone.php CHANGED
@@ -6,15 +6,21 @@
6
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
7
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
8
  <?php endif; ?>
 
 
 
9
  <div class="happyforms-part__el">
10
  <?php $code_value = ( ! empty( happyforms_get_part_value( $part, $form, 'code' ) ) ) ? happyforms_get_part_value( $part, $form, 'code' ) : $part['mask_phone_country']; ?>
11
- <input type="hidden" name="<?php happyforms_the_part_name( $part, $form ); ?>[code]" value="<?php echo $code_value; ?>">
12
  <?php happyforms_the_countries_dropdown( $this, $part, $code_value ); ?>
13
- <input id="<?php happyforms_the_part_id( $part, $form ); ?>" type="text" value="<?php happyforms_the_part_value( $part, $form, 'number' ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>[number]" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> />
14
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
15
  <?php happyforms_the_part_label( $part, $form ); ?>
16
  <?php endif; ?>
17
  </div>
 
 
 
18
  <?php happyforms_print_part_description( $part ); ?>
19
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
20
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
@@ -27,7 +33,7 @@
27
  <?php endif; ?>
28
  <div class="happyforms-part__el">
29
  <?php happyforms_the_countries_dropdown( $this, $part, $code_value ); ?>
30
- <input id="<?php happyforms_the_part_id( $part, $form ); ?>_confirmation" type="text" name="<?php happyforms_the_part_name( $part, $form ); ?>[confirmation]" value="<?php happyforms_the_part_value( $part, $form, 'confirmation' ); ?>" class="happyforms-confirmation-input" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> />
31
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
32
  <?php happyforms_the_part_confirmation_label( $part, $form ); ?>
33
  <?php endif; ?>
6
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
7
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
8
  <?php endif; ?>
9
+
10
+ <?php do_action( 'happyforms_part_input_before', $part, $form ); ?>
11
+
12
  <div class="happyforms-part__el">
13
  <?php $code_value = ( ! empty( happyforms_get_part_value( $part, $form, 'code' ) ) ) ? happyforms_get_part_value( $part, $form, 'code' ) : $part['mask_phone_country']; ?>
14
+ <input type="hidden" name="<?php happyforms_the_part_name( $part, $form ); ?>[code]" value="<?php echo $code_value; ?>" <?php happyforms_the_part_attributes( $part, $form, 'code' ); ?> />
15
  <?php happyforms_the_countries_dropdown( $this, $part, $code_value ); ?>
16
+ <input id="<?php happyforms_the_part_id( $part, $form ); ?>" type="text" value="<?php happyforms_the_part_value( $part, $form, 'number' ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>[number]" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> <?php happyforms_the_part_attributes( $part, $form, 'number' ); ?> />
17
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
18
  <?php happyforms_the_part_label( $part, $form ); ?>
19
  <?php endif; ?>
20
  </div>
21
+
22
+ <?php do_action( 'happyforms_part_input_after', $part, $form ); ?>
23
+
24
  <?php happyforms_print_part_description( $part ); ?>
25
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
26
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
33
  <?php endif; ?>
34
  <div class="happyforms-part__el">
35
  <?php happyforms_the_countries_dropdown( $this, $part, $code_value ); ?>
36
+ <input id="<?php happyforms_the_part_id( $part, $form ); ?>_confirmation" type="text" name="<?php happyforms_the_part_name( $part, $form ); ?>[confirmation]" value="<?php happyforms_the_part_value( $part, $form, 'confirmation' ); ?>" class="happyforms-confirmation-input" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> <?php happyforms_the_part_attributes( $part, $form, 1 ); ?> />
37
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
38
  <?php happyforms_the_part_confirmation_label( $part, $form ); ?>
39
  <?php endif; ?>
inc/templates/parts/frontend-placeholder.php CHANGED
@@ -1,6 +1,11 @@
1
  <div class="<?php happyforms_the_part_class( $part, $form ); ?>" id="<?php happyforms_the_part_id( $part, $form ); ?>-part" <?php happyforms_the_part_data_attributes( $part, $form ); ?>>
2
  <div class="happyforms-part-wrap">
3
  <?php happyforms_the_part_label( $part, $form ); ?>
 
 
 
4
  <div class="happyforms-part__el"><?php echo html_entity_decode( $part['placeholder_text'] ); ?></div>
 
 
5
  </div>
6
  </div>
1
  <div class="<?php happyforms_the_part_class( $part, $form ); ?>" id="<?php happyforms_the_part_id( $part, $form ); ?>-part" <?php happyforms_the_part_data_attributes( $part, $form ); ?>>
2
  <div class="happyforms-part-wrap">
3
  <?php happyforms_the_part_label( $part, $form ); ?>
4
+
5
+ <?php do_action( 'happyforms_part_input_before', $part, $form ); ?>
6
+
7
  <div class="happyforms-part__el"><?php echo html_entity_decode( $part['placeholder_text'] ); ?></div>
8
+
9
+ <?php do_action( 'happyforms_part_input_after', $part, $form ); ?>
10
  </div>
11
  </div>
inc/templates/parts/frontend-radio.php CHANGED
@@ -4,6 +4,9 @@
4
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
5
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
6
  <?php endif; ?>
 
 
 
7
  <div class="happyforms-part__el">
8
  <?php
9
  $options = happyforms_get_part_options( $part['options'], $part, $form );
@@ -14,7 +17,7 @@
14
  ?>
15
  <div class="happyforms-part__option happyforms-part-option" id="<?php echo esc_attr( $option['id'] ); ?>">
16
  <label class="option-label">
17
- <input type="radio" class="happyforms-visuallyhidden" name="<?php happyforms_the_part_name( $part, $form ); ?>" value="<?php echo esc_attr( $option['label'] ); ?>" <?php echo $checked; ?>>
18
  <span class="checkmark"><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24"><path fill="currentColor" d="M20.285 2l-11.285 11.567-5.286-5.011-3.714 3.716 9 8.728 15-15.285z"/></svg></span>
19
  <span class="border"></span>
20
  <span class="label"><?php echo esc_attr( $option['label'] ); ?></span>
@@ -27,5 +30,7 @@
27
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
28
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
29
  <?php endif; ?>
 
 
30
  </div>
31
  </div>
4
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
5
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
6
  <?php endif; ?>
7
+
8
+ <?php do_action( 'happyforms_part_input_before', $part, $form ); ?>
9
+
10
  <div class="happyforms-part__el">
11
  <?php
12
  $options = happyforms_get_part_options( $part['options'], $part, $form );
17
  ?>
18
  <div class="happyforms-part__option happyforms-part-option" id="<?php echo esc_attr( $option['id'] ); ?>">
19
  <label class="option-label">
20
+ <input type="radio" class="happyforms-visuallyhidden" name="<?php happyforms_the_part_name( $part, $form ); ?>" value="<?php echo esc_attr( $option['label'] ); ?>" <?php echo $checked; ?> <?php happyforms_the_part_attributes( $part, $form ); ?>>
21
  <span class="checkmark"><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24"><path fill="currentColor" d="M20.285 2l-11.285 11.567-5.286-5.011-3.714 3.716 9 8.728 15-15.285z"/></svg></span>
22
  <span class="border"></span>
23
  <span class="label"><?php echo esc_attr( $option['label'] ); ?></span>
30
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
31
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
32
  <?php endif; ?>
33
+
34
+ <?php do_action( 'happyforms_part_input_after', $part, $form ); ?>
35
  </div>
36
  </div>
inc/templates/parts/frontend-rating.php CHANGED
@@ -1,17 +1,23 @@
1
  <div class="<?php happyforms_the_part_class( $part, $form ); ?>" id="<?php happyforms_the_part_id( $part, $form ); ?>-part" <?php happyforms_the_part_data_attributes( $part, $form ); ?>>
2
  <div class="happyforms-part-wrap">
3
  <?php happyforms_the_part_label( $part, $form ); ?>
 
 
 
4
  <div class="happyforms-part__el">
5
- <input class="happyforms-visuallyhidden" type="radio" value="0" id="<?php echo esc_attr( $part['id'] ); ?>_0" name="<?php happyforms_the_part_name( $part, $form ); ?>" checked>
6
 
7
  <?php for ( $i = 1; $i <= $part['stars_num']; $i++ ) { ?>
8
- <input class="happyforms-visuallyhidden star_<?php echo esc_attr( $i ); ?>" type="radio" value="<?php echo esc_attr( $i ); ?>" id="<?php echo esc_attr( $part['id'] ); ?>_<?php echo esc_attr( $i ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>" <?php checked( happyforms_get_part_value( $part, $form ), $i ); ?>>
9
  <label class="happyforms-star__label" for="<?php echo esc_attr( $part['id'] ); ?>_<?php echo esc_attr( $i ); ?>">
10
  <span class="happyforms-visuallyhidden"><?php echo esc_attr( $i ); ?> <?php _e( 'Stars', 'happyforms' ); ?></span>
11
  <svg class="happyforms-star" viewBox="0 0 512 512" fill=""><path class="happyforms-star__star" d="M512 198.525l-176.89-25.704-79.11-160.291-79.108 160.291-176.892 25.704 128 124.769-30.216 176.176 158.216-83.179 158.216 83.179-30.217-176.176 128.001-124.769z"></path></svg>
12
  </label>
13
  <?php } ?>
14
  </div>
 
 
 
15
  <?php happyforms_print_part_description( $part ); ?>
16
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
17
  </div>
1
  <div class="<?php happyforms_the_part_class( $part, $form ); ?>" id="<?php happyforms_the_part_id( $part, $form ); ?>-part" <?php happyforms_the_part_data_attributes( $part, $form ); ?>>
2
  <div class="happyforms-part-wrap">
3
  <?php happyforms_the_part_label( $part, $form ); ?>
4
+
5
+ <?php do_action( 'happyforms_part_input_before', $part, $form ); ?>
6
+
7
  <div class="happyforms-part__el">
8
+ <input class="happyforms-visuallyhidden" type="radio" value="0" id="<?php echo esc_attr( $part['id'] ); ?>_0" name="<?php happyforms_the_part_name( $part, $form ); ?>" checked <?php happyforms_the_part_attributes( $part, $form ); ?>>
9
 
10
  <?php for ( $i = 1; $i <= $part['stars_num']; $i++ ) { ?>
11
+ <input class="happyforms-visuallyhidden star_<?php echo esc_attr( $i ); ?>" type="radio" value="<?php echo esc_attr( $i ); ?>" id="<?php echo esc_attr( $part['id'] ); ?>_<?php echo esc_attr( $i ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>" <?php checked( happyforms_get_part_value( $part, $form ), $i ); ?> <?php happyforms_the_part_attributes( $part, $form ); ?> />
12
  <label class="happyforms-star__label" for="<?php echo esc_attr( $part['id'] ); ?>_<?php echo esc_attr( $i ); ?>">
13
  <span class="happyforms-visuallyhidden"><?php echo esc_attr( $i ); ?> <?php _e( 'Stars', 'happyforms' ); ?></span>
14
  <svg class="happyforms-star" viewBox="0 0 512 512" fill=""><path class="happyforms-star__star" d="M512 198.525l-176.89-25.704-79.11-160.291-79.108 160.291-176.892 25.704 128 124.769-30.216 176.176 158.216-83.179 158.216 83.179-30.217-176.176 128.001-124.769z"></path></svg>
15
  </label>
16
  <?php } ?>
17
  </div>
18
+
19
+ <?php do_action( 'happyforms_part_input_after', $part, $form ); ?>
20
+
21
  <?php happyforms_print_part_description( $part ); ?>
22
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
23
  </div>
inc/templates/parts/frontend-scale.php CHANGED
@@ -4,22 +4,23 @@
4
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
5
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
6
  <?php endif; ?>
7
- <?php
 
 
 
 
8
  $part_name = happyforms_get_part_name( $part, $form );
9
 
10
  if ( 1 === intval( $part['multiple'] ) ) {
11
  $part_name = $part_name . '[]';
12
  }
13
  ?>
14
- <?php happyforms_print_part_description( $part ); ?>
15
  <div class="happyforms-part--scale__inputwrap">
16
  <div class="happyforms-part--scale__labels">
17
  <span class="label-min"><?php echo $part['min_label']; ?></span>
18
  <span class="label-max"><?php echo $part['max_label']; ?></span>
19
  </div>
20
- <input id="<?php happyforms_the_part_id( $part, $form ); ?>"<?php if ( 1 === intval( $part['multiple'] ) ) : ?> multiple<?php endif; ?> type="range" name="<?php echo $part_name; ?>" step="<?php echo esc_attr( $part['step'] ); ?>" class="happyforms-part__el happyforms-part__el--text-input"
21
- <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?>
22
- min="<?php echo esc_attr( $part['min_value'] ); ?>" max="<?php echo esc_attr( $part['max_value'] ); ?>" value="<?php happyforms_the_part_value( $part, $form ); ?>" />
23
  <output for="<?php happyforms_the_part_id( $part, $form ); ?>">
24
  <span><?php happyforms_the_part_value( $part, $form ); ?></span>
25
  </output>
@@ -29,6 +30,9 @@
29
  </output>
30
  <?php endif; ?>
31
  </div>
 
 
 
32
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
33
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
34
  <?php endif; ?>
4
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
5
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
6
  <?php endif; ?>
7
+ <?php happyforms_print_part_description( $part ); ?>
8
+
9
+ <?php do_action( 'happyforms_part_input_before', $part, $form ); ?>
10
+
11
+ <?php
12
  $part_name = happyforms_get_part_name( $part, $form );
13
 
14
  if ( 1 === intval( $part['multiple'] ) ) {
15
  $part_name = $part_name . '[]';
16
  }
17
  ?>
 
18
  <div class="happyforms-part--scale__inputwrap">
19
  <div class="happyforms-part--scale__labels">
20
  <span class="label-min"><?php echo $part['min_label']; ?></span>
21
  <span class="label-max"><?php echo $part['max_label']; ?></span>
22
  </div>
23
+ <input id="<?php happyforms_the_part_id( $part, $form ); ?>"<?php if ( 1 === intval( $part['multiple'] ) ) : ?> multiple<?php endif; ?> type="range" name="<?php echo $part_name; ?>" step="<?php echo esc_attr( $part['step'] ); ?>" class="happyforms-part__el happyforms-part__el--text-input" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> min="<?php echo esc_attr( $part['min_value'] ); ?>" max="<?php echo esc_attr( $part['max_value'] ); ?>" value="<?php happyforms_the_part_value( $part, $form ); ?>" <?php happyforms_the_part_attributes( $part, $form ); ?> />
 
 
24
  <output for="<?php happyforms_the_part_id( $part, $form ); ?>">
25
  <span><?php happyforms_the_part_value( $part, $form ); ?></span>
26
  </output>
30
  </output>
31
  <?php endif; ?>
32
  </div>
33
+
34
+ <?php do_action( 'happyforms_part_input_after', $part, $form ); ?>
35
+
36
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
37
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
38
  <?php endif; ?>
inc/templates/parts/frontend-select.php CHANGED
@@ -4,18 +4,21 @@
4
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
5
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
6
  <?php endif; ?>
 
 
 
7
  <div class="happyforms-custom-select" data-searchable="<?php echo ( 1 == $part['allow_search'] ) ? 'true' : 'false'; ?>">
8
  <div class="happyforms-part__select-wrap">
9
- <?php
10
  $options = happyforms_get_part_options( $part['options'], $part, $form );
11
 
12
- $default_value = happyforms_the_part_value( $part, $form );
13
  $placeholder_value = '';
14
  $has_value = false;
15
 
16
  while( empty( $default_value ) ) {
17
  foreach( $options as $option ) {
18
- if ( $option['is_default'] ) {
19
  $default_value = $option['label'];
20
  $has_value = true;
21
  }
@@ -28,7 +31,7 @@
28
  $placeholder_value = __( '- Select -', 'happyforms' );
29
  }
30
  ?>
31
- <input id="<?php happyforms_the_part_id( $part, $form ); ?>" type="text" value="<?php echo $default_value; ?>" placeholder="<?php echo $placeholder_value; ?>" class="happyforms-part__el happyforms-part__el--text-input"<?php if ( 1 === $part['required'] ) : ?> required aria-required="true"<?php endif; ?> />
32
 
33
  <ul class="happyforms-custom-select-dropdown">
34
  <li data-value=""><?php _e( '- Select -', 'happyforms' ); ?></li>
@@ -54,7 +57,7 @@
54
  <?php endforeach; ?>
55
  </ul>
56
 
57
- <select id="<?php happyforms_the_part_id( $part, $form ); ?>_select" name="<?php happyforms_the_part_name( $part, $form ); ?>" class="happyforms-part__el">
58
  <option value="">- <?php _e( 'Select', 'happyforms' ); ?> -</option>
59
  <?php
60
  foreach( $options as $option ) :
@@ -66,6 +69,9 @@
66
  </select>
67
  </div>
68
  </div>
 
 
 
69
  <?php happyforms_print_part_description( $part ); ?>
70
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
71
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
4
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
5
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
6
  <?php endif; ?>
7
+
8
+ <?php do_action( 'happyforms_part_input_before', $part, $form ); ?>
9
+
10
  <div class="happyforms-custom-select" data-searchable="<?php echo ( 1 == $part['allow_search'] ) ? 'true' : 'false'; ?>">
11
  <div class="happyforms-part__select-wrap">
12
+ <?php
13
  $options = happyforms_get_part_options( $part['options'], $part, $form );
14
 
15
+ $default_value = happyforms_get_part_value( $part, $form );
16
  $placeholder_value = '';
17
  $has_value = false;
18
 
19
  while( empty( $default_value ) ) {
20
  foreach( $options as $option ) {
21
+ if ( $option['is_default'] === 'true' ) {
22
  $default_value = $option['label'];
23
  $has_value = true;
24
  }
31
  $placeholder_value = __( '- Select -', 'happyforms' );
32
  }
33
  ?>
34
+ <input id="<?php happyforms_the_part_id( $part, $form ); ?>" type="text" value="<?php echo $default_value; ?>" placeholder="<?php echo $placeholder_value; ?>" class="happyforms-part__el happyforms-part__el--text-input"<?php if ( 1 === $part['required'] ) : ?> required aria-required="true"<?php endif; ?> <?php happyforms_the_part_attributes( $part, $form ); ?> />
35
 
36
  <ul class="happyforms-custom-select-dropdown">
37
  <li data-value=""><?php _e( '- Select -', 'happyforms' ); ?></li>
57
  <?php endforeach; ?>
58
  </ul>
59
 
60
+ <select id="<?php happyforms_the_part_id( $part, $form ); ?>_select" name="<?php happyforms_the_part_name( $part, $form ); ?>" class="happyforms-part__el" <?php happyforms_the_part_attributes( $part, $form ); ?>>
61
  <option value="">- <?php _e( 'Select', 'happyforms' ); ?> -</option>
62
  <?php
63
  foreach( $options as $option ) :
69
  </select>
70
  </div>
71
  </div>
72
+
73
+ <?php do_action( 'happyforms_part_input_after', $part, $form ); ?>
74
+
75
  <?php happyforms_print_part_description( $part ); ?>
76
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
77
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
inc/templates/parts/frontend-single-line-text.php CHANGED
@@ -6,10 +6,16 @@
6
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
7
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
8
  <?php endif; ?>
9
- <input id="<?php happyforms_the_part_id( $part, $form ); ?>" type="text" name="<?php happyforms_the_part_name( $part, $form ); ?>" value="<?php happyforms_the_part_value( $part, $form ); ?>" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>" class="happyforms-part__el happyforms-part__el--text-input" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> />
 
 
 
10
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
11
  <?php happyforms_the_part_label( $part, $form ); ?>
12
  <?php endif; ?>
 
 
 
13
  <?php happyforms_print_part_description( $part ); ?>
14
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
15
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
6
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
7
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
8
  <?php endif; ?>
9
+
10
+ <?php do_action( 'happyforms_part_input_before', $part, $form ); ?>
11
+
12
+ <input id="<?php happyforms_the_part_id( $part, $form ); ?>" type="text" name="<?php happyforms_the_part_name( $part, $form ); ?>" value="<?php happyforms_the_part_value( $part, $form ); ?>" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>" class="happyforms-part__el happyforms-part__el--text-input" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> <?php happyforms_the_part_attributes( $part, $form ); ?> />
13
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
14
  <?php happyforms_the_part_label( $part, $form ); ?>
15
  <?php endif; ?>
16
+
17
+ <?php do_action( 'happyforms_part_input_after', $part, $form ); ?>
18
+
19
  <?php happyforms_print_part_description( $part ); ?>
20
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
21
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
inc/templates/parts/frontend-table.php CHANGED
@@ -5,15 +5,18 @@
5
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
6
  <?php endif; ?>
7
  <?php happyforms_print_part_description( $part ); ?>
 
 
 
8
  <div class="happyforms-part__el">
9
- <?php
10
- $columns = happyforms_get_part_options( $part['columns'], $part, $form );
11
- $columns_num = ( is_array( $columns ) ) ? sizeof( $columns ) : 1;
12
  ?>
13
  <div class="happyforms-table">
14
  <div class="happyforms-table__row happyforms-table__row--head">
15
  <div class="happyforms-table__cell" style="width: <?php echo 100 / $columns_num; ?>%"></div>
16
- <?php
17
  foreach( $columns as $column ) : ?>
18
  <div class="happyforms-table__cell happyforms-table__cell--column-title" id="<?php echo esc_attr( $column['id'] ); ?>" style="width: <?php echo 100 / $columns_num; ?>%">
19
  <span><?php echo esc_attr( $column['label'] ); ?></span>
@@ -40,7 +43,7 @@
40
  $checked = $checked ? $checked : checked( happyforms_get_part_value( $part, $form, $row['id'] ), $column['label'], false );
41
  }
42
  ?>
43
- <input type="radio" class="happyforms-visuallyhidden" name="<?php happyforms_the_part_name( $part, $form ); ?>[<?php echo esc_attr( $row['id'] ); ?>]" value="<?php echo esc_attr( $column['label'] ); ?>" <?php echo $checked; ?>>
44
  <span class="checkmark"><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24"><path fill="currentColor" d="M20.285 2l-11.285 11.567-5.286-5.011-3.714 3.716 9 8.728 15-15.285z"/></svg></span>
45
  <span class="border"></span>
46
  <?php else: ?>
@@ -50,7 +53,7 @@
50
  $is_checked = ( is_array( $value ) && ( '' !== $column['label'] ) && in_array( $column['label'], $value ) );
51
  $checked = ( $is_default || $is_checked ) ? 'checked="checked"' : '';
52
  ?>
53
- <input type="checkbox" class="happyforms-visuallyhidden" name="<?php happyforms_the_part_name( $part, $form ); ?>[<?php echo esc_attr( $row['id'] ); ?>][]" value="<?php echo esc_attr( $column['label'] ); ?>" <?php echo $checked; ?>>
54
  <span class="checkmark"><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24"><path fill="currentColor" d="M20.285 2l-11.285 11.567-5.286-5.011-3.714 3.716 9 8.728 15-15.285z"/></svg></span>
55
  <?php endif; ?>
56
  </label>
@@ -60,6 +63,9 @@
60
  <?php endforeach; ?>
61
  </div>
62
  </div>
 
 
 
63
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
64
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
65
  <?php endif; ?>
5
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
6
  <?php endif; ?>
7
  <?php happyforms_print_part_description( $part ); ?>
8
+
9
+ <?php do_action( 'happyforms_part_input_before', $part, $form ); ?>
10
+
11
  <div class="happyforms-part__el">
12
+ <?php
13
+ $columns = happyforms_get_part_options( $part['columns'], $part, $form );
14
+ $columns_num = ( is_array( $columns ) ) ? sizeof( $columns ) : 1;
15
  ?>
16
  <div class="happyforms-table">
17
  <div class="happyforms-table__row happyforms-table__row--head">
18
  <div class="happyforms-table__cell" style="width: <?php echo 100 / $columns_num; ?>%"></div>
19
+ <?php
20
  foreach( $columns as $column ) : ?>
21
  <div class="happyforms-table__cell happyforms-table__cell--column-title" id="<?php echo esc_attr( $column['id'] ); ?>" style="width: <?php echo 100 / $columns_num; ?>%">
22
  <span><?php echo esc_attr( $column['label'] ); ?></span>
43
  $checked = $checked ? $checked : checked( happyforms_get_part_value( $part, $form, $row['id'] ), $column['label'], false );
44
  }
45
  ?>
46
+ <input type="radio" class="happyforms-visuallyhidden" name="<?php happyforms_the_part_name( $part, $form ); ?>[<?php echo esc_attr( $row['id'] ); ?>]" value="<?php echo esc_attr( $column['label'] ); ?>" <?php echo $checked; ?> <?php happyforms_the_part_attributes( $part, $form ); ?>>
47
  <span class="checkmark"><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24"><path fill="currentColor" d="M20.285 2l-11.285 11.567-5.286-5.011-3.714 3.716 9 8.728 15-15.285z"/></svg></span>
48
  <span class="border"></span>
49
  <?php else: ?>
53
  $is_checked = ( is_array( $value ) && ( '' !== $column['label'] ) && in_array( $column['label'], $value ) );
54
  $checked = ( $is_default || $is_checked ) ? 'checked="checked"' : '';
55
  ?>
56
+ <input type="checkbox" class="happyforms-visuallyhidden" name="<?php happyforms_the_part_name( $part, $form ); ?>[<?php echo esc_attr( $row['id'] ); ?>][]" value="<?php echo esc_attr( $column['label'] ); ?>" <?php echo $checked; ?> <?php happyforms_the_part_attributes( $part, $form ); ?>>
57
  <span class="checkmark"><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24"><path fill="currentColor" d="M20.285 2l-11.285 11.567-5.286-5.011-3.714 3.716 9 8.728 15-15.285z"/></svg></span>
58
  <?php endif; ?>
59
  </label>
63
  <?php endforeach; ?>
64
  </div>
65
  </div>
66
+
67
+ <?php do_action( 'happyforms_part_input_after', $part, $form ); ?>
68
+
69
  <?php if ( 'happyforms-form--part-error-notices-below' === happyforms_get_form_property( $form, 'part_error_notices_location' ) || ( '' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) ) : ?>
70
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
71
  <?php endif; ?>
inc/templates/parts/frontend-title.php CHANGED
@@ -1,12 +1,15 @@
1
  <div class="<?php happyforms_the_part_class( $part, $form ); ?>" id="<?php happyforms_the_part_id( $part, $form ); ?>-part" <?php happyforms_the_part_data_attributes( $part, $form ); ?>>
2
  <div class="happyforms-part-wrap">
3
  <?php happyforms_the_part_label( $part, $form ); ?>
 
 
 
4
  <div class="happyforms-custom-select">
5
  <div class="happyforms-part__select-wrap">
6
- <?php
7
  $options = happyforms_get_part_options( $part['options'], $part, $form );
8
 
9
- $default_value = happyforms_the_part_value( $part, $form );
10
  $placeholder_value = '';
11
  $has_value = false;
12
 
@@ -18,7 +21,7 @@
18
  $placeholder_value = __( '- Select -', 'happyforms' );
19
  }
20
  ?>
21
- <input id="<?php happyforms_the_part_id( $part, $form ); ?>" type="text" value="<?php echo $default_value; ?>" placeholder="<?php echo $placeholder_value; ?>" class="happyforms-part__el happyforms-part__el--text-input"<?php if ( 1 === $part['required'] ) : ?> required aria-required="true"<?php endif; ?> />
22
 
23
  <ul class="happyforms-part-select__dropdown happyforms-custom-select-dropdown">
24
  <li data-value=""><?php _e( '- Select -', 'happyforms' ); ?></li>
@@ -39,7 +42,7 @@
39
  <?php endforeach; ?>
40
  </ul>
41
 
42
- <select id="<?php happyforms_the_part_id( $part, $form ); ?>_select" name="<?php happyforms_the_part_name( $part, $form ); ?>" class="happyforms-part__el">
43
  <option value="">- <?php _e( 'Select', 'happyforms' ); ?> -</option>
44
  <?php
45
  foreach( $options as $option ) : ?>
@@ -48,6 +51,9 @@
48
  </select>
49
  </div>
50
  </div>
 
 
 
51
  <?php happyforms_print_part_description( $part ); ?>
52
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
53
  </div>
1
  <div class="<?php happyforms_the_part_class( $part, $form ); ?>" id="<?php happyforms_the_part_id( $part, $form ); ?>-part" <?php happyforms_the_part_data_attributes( $part, $form ); ?>>
2
  <div class="happyforms-part-wrap">
3
  <?php happyforms_the_part_label( $part, $form ); ?>
4
+
5
+ <?php do_action( 'happyforms_part_input_before', $part, $form ); ?>
6
+
7
  <div class="happyforms-custom-select">
8
  <div class="happyforms-part__select-wrap">
9
+ <?php
10
  $options = happyforms_get_part_options( $part['options'], $part, $form );
11
 
12
+ $default_value = happyforms_get_part_value( $part, $form );
13
  $placeholder_value = '';
14
  $has_value = false;
15
 
21
  $placeholder_value = __( '- Select -', 'happyforms' );
22
  }
23
  ?>
24
+ <input id="<?php happyforms_the_part_id( $part, $form ); ?>" type="text" value="<?php echo $default_value; ?>" placeholder="<?php echo $placeholder_value; ?>" class="happyforms-part__el happyforms-part__el--text-input"<?php if ( 1 === $part['required'] ) : ?> required aria-required="true"<?php endif; ?> <?php happyforms_the_part_attributes( $part, $form ); ?> />
25
 
26
  <ul class="happyforms-part-select__dropdown happyforms-custom-select-dropdown">
27
  <li data-value=""><?php _e( '- Select -', 'happyforms' ); ?></li>
42
  <?php endforeach; ?>
43
  </ul>
44
 
45
+ <select id="<?php happyforms_the_part_id( $part, $form ); ?>_select" name="<?php happyforms_the_part_name( $part, $form ); ?>" class="happyforms-part__el" <?php happyforms_the_part_attributes( $part, $form ); ?>>
46
  <option value="">- <?php _e( 'Select', 'happyforms' ); ?> -</option>
47
  <?php
48
  foreach( $options as $option ) : ?>
51
  </select>
52
  </div>
53
  </div>
54
+
55
+ <?php do_action( 'happyforms_part_input_after', $part, $form ); ?>
56
+
57
  <?php happyforms_print_part_description( $part ); ?>
58
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
59
  </div>
inc/templates/parts/frontend-website-url.php CHANGED
@@ -6,7 +6,13 @@
6
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
7
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
8
  <?php endif; ?>
9
- <input id="<?php happyforms_the_part_id( $part, $form ); ?>" type="text" value="<?php happyforms_the_part_value( $part, $form ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>" class="happyforms-part__el happyforms-part__el--text-input" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> />
 
 
 
 
 
 
10
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
11
  <?php happyforms_the_part_label( $part, $form ); ?>
12
  <?php endif; ?>
6
  <?php if ( 'happyforms-form--part-error-notices-above' === happyforms_get_form_property( $form, 'part_error_notices_location' ) ) : ?>
7
  <?php happyforms_message_notices( happyforms_get_part_name( $part, $form ) ); ?>
8
  <?php endif; ?>
9
+
10
+ <?php do_action( 'happyforms_part_input_before', $part, $form ); ?>
11
+
12
+ <input id="<?php happyforms_the_part_id( $part, $form ); ?>" type="text" value="<?php happyforms_the_part_value( $part, $form ); ?>" name="<?php happyforms_the_part_name( $part, $form ); ?>" placeholder="<?php echo esc_attr( $part['placeholder'] ); ?>" class="happyforms-part__el happyforms-part__el--text-input" <?php if ( 1 === $part['required'] ) : ?>required aria-required="true"<?php endif; ?> <?php happyforms_the_part_attributes( $part, $form ); ?> />
13
+
14
+ <?php do_action( 'happyforms_part_input_after', $part, $form ); ?>
15
+
16
  <?php if ( 'as_placeholder' === $part['label_placement'] ) : ?>
17
  <?php happyforms_the_part_label( $part, $form ); ?>
18
  <?php endif; ?>
inc/templates/single-form.php CHANGED
@@ -8,6 +8,8 @@
8
  <?php happyforms_action_field(); ?>
9
  <?php happyforms_form_field( $form['ID'] ); ?>
10
  <?php happyforms_nonce_field( $form ); ?>
 
 
11
  <?php happyforms_the_form_title( $form ); ?>
12
  <?php happyforms_message_notices( $form['ID'] ); ?>
13
 
8
  <?php happyforms_action_field(); ?>
9
  <?php happyforms_form_field( $form['ID'] ); ?>
10
  <?php happyforms_nonce_field( $form ); ?>
11
+ <?php happyforms_step_field( $form ); ?>
12
+
13
  <?php happyforms_the_form_title( $form ); ?>
14
  <?php happyforms_message_notices( $form['ID'] ); ?>
15
 
languages/happyforms.pot CHANGED
@@ -2,9 +2,9 @@
2
  # This file is distributed under the same license as the HappyForms package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: HappyForms 1.5.5\n"
6
  "Report-Msgid-Bugs-To: https://thethemefoundry.com/support/\n"
7
- "POT-Creation-Date: 2018-08-03 09:44:49+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -14,7 +14,7 @@ msgstr ""
14
  "X-Generator: grunt-wp-i18n 0.4.9\n"
15
 
16
  #: inc/classes/class-form-admin.php:155
17
- #: inc/classes/class-form-controller.php:79
18
  msgid "View form"
19
  msgstr ""
20
 
@@ -102,6 +102,7 @@ msgid "Copy to clipboard"
102
  msgstr ""
103
 
104
  #: inc/classes/class-form-admin.php:358
 
105
  msgid "Edit"
106
  msgstr ""
107
 
@@ -124,69 +125,75 @@ msgstr ""
124
  msgid " Copy"
125
  msgstr ""
126
 
127
- #: inc/classes/class-form-controller.php:74
128
- #: inc/classes/class-form-controller.php:84
129
  #: inc/classes/class-happyforms-plugin.php:153
130
  #: inc/classes/class-happyforms-plugin.php:154
131
  msgid "All Forms"
132
  msgstr ""
133
 
134
- #: inc/classes/class-form-controller.php:75
135
  #: inc/classes/class-message-admin.php:317
136
  #: inc/classes/class-message-admin.php:790
137
  msgid "Form"
138
  msgstr ""
139
 
140
- #: inc/classes/class-form-controller.php:76
141
- #: inc/classes/class-form-controller.php:78
142
  msgid "Build form"
143
  msgstr ""
144
 
145
- #: inc/classes/class-form-controller.php:77
146
  msgid "Edit form"
147
  msgstr ""
148
 
149
- #: inc/classes/class-form-controller.php:80
150
  msgid "View forms"
151
  msgstr ""
152
 
153
- #: inc/classes/class-form-controller.php:81
154
  msgid "Search Forms"
155
  msgstr ""
156
 
157
- #: inc/classes/class-form-controller.php:82
158
  msgid "No form found"
159
  msgstr ""
160
 
161
- #: inc/classes/class-form-controller.php:83
162
  msgid "No forms found in Trash"
163
  msgstr ""
164
 
165
- #: inc/classes/class-form-controller.php:175
166
  msgid "Untitled form"
167
  msgstr ""
168
 
169
- #: inc/classes/class-form-controller.php:196
170
- #: inc/classes/class-form-controller.php:220
171
  msgid ""
172
  "Your message has been successfully sent. We appreciate you contacting us "
173
  "and we’ll be in touch soon."
174
  msgstr ""
175
 
176
- #: inc/classes/class-form-controller.php:208
177
  msgid "You received a new message"
178
  msgstr ""
179
 
180
- #: inc/classes/class-form-controller.php:216
181
  msgid "We received your message"
182
  msgstr ""
183
 
184
- #: inc/classes/class-form-controller.php:232
185
  msgid "Submit Form"
186
  msgstr ""
187
 
188
- #: inc/classes/class-form-controller.php:748
189
- #: inc/classes/class-message-controller.php:237
 
 
 
 
 
 
190
  msgid "Your submission contains errors."
191
  msgstr ""
192
 
@@ -639,7 +646,7 @@ msgid "View response #"
639
  msgstr ""
640
 
641
  #: inc/classes/class-message-admin.php:182
642
- #: inc/classes/class-message-controller.php:157
643
  msgid "View response"
644
  msgstr ""
645
 
@@ -768,36 +775,36 @@ msgstr ""
768
  msgid "Unread"
769
  msgstr ""
770
 
771
- #: inc/classes/class-message-controller.php:130
772
  msgid "New submission"
773
  msgstr ""
774
 
775
- #: inc/classes/class-message-controller.php:154
776
- #: inc/classes/class-message-controller.php:162
777
  msgid "All Responses"
778
  msgstr ""
779
 
780
- #: inc/classes/class-message-controller.php:155
781
  msgid "Response"
782
  msgstr ""
783
 
784
- #: inc/classes/class-message-controller.php:156
785
  msgid "Edit response"
786
  msgstr ""
787
 
788
- #: inc/classes/class-message-controller.php:158
789
  msgid "View Responses"
790
  msgstr ""
791
 
792
- #: inc/classes/class-message-controller.php:159
793
  msgid "Search Responses"
794
  msgstr ""
795
 
796
- #: inc/classes/class-message-controller.php:160
797
  msgid "No response found"
798
  msgstr ""
799
 
800
- #: inc/classes/class-message-controller.php:161
801
  msgid "No response found in Trash"
802
  msgstr ""
803
 
@@ -891,7 +898,7 @@ msgid ""
891
  msgstr ""
892
 
893
  #: inc/classes/parts/class-part-address.php:13
894
- #: inc/classes/parts/class-part-address.php:42
895
  msgid "Address"
896
  msgstr ""
897
 
@@ -899,12 +906,12 @@ msgstr ""
899
  msgid "For geographical locations. Includes Google Maps intergration."
900
  msgstr ""
901
 
902
- #: inc/classes/parts/class-part-address.php:192
903
  #: inc/classes/parts/class-part-checkbox.php:165
904
- #: inc/classes/parts/class-part-date.php:193
905
  #: inc/classes/parts/class-part-email.php:142
906
  #: inc/classes/parts/class-part-email.php:146
907
- #: inc/classes/parts/class-part-legal.php:111
908
  #: inc/classes/parts/class-part-multi-line-text.php:141
909
  #: inc/classes/parts/class-part-number.php:175
910
  #: inc/classes/parts/class-part-number.php:179
@@ -951,20 +958,20 @@ msgstr ""
951
  msgid "For formatted day, month, year and or time fields."
952
  msgstr ""
953
 
954
- #: inc/classes/parts/class-part-date.php:31
955
  #: inc/templates/parts/customize-date.php:32
956
  msgid "Date"
957
  msgstr ""
958
 
959
- #: inc/classes/parts/class-part-date.php:225
960
  msgid "Not a valid date."
961
  msgstr ""
962
 
963
- #: inc/classes/parts/class-part-date.php:237
964
  msgid "Hour input does not match minimum and maximum value allowed."
965
  msgstr ""
966
 
967
- #: inc/classes/parts/class-part-date.php:250
968
  msgid "Year input does not match maximum value allowed."
969
  msgstr ""
970
 
@@ -990,7 +997,7 @@ msgid "Email and confirmation email are not matching."
990
  msgstr ""
991
 
992
  #: inc/classes/parts/class-part-legal.php:9
993
- #: inc/classes/parts/class-part-legal.php:43
994
  msgid "Legal"
995
  msgstr ""
996
 
@@ -998,11 +1005,11 @@ msgstr ""
998
  msgid "For requiring fine print before accepting submission."
999
  msgstr ""
1000
 
1001
- #: inc/classes/parts/class-part-legal.php:27
1002
  msgid "I accept terms and conditions."
1003
  msgstr ""
1004
 
1005
- #: inc/classes/parts/class-part-legal.php:116
1006
  msgid "Please accept terms before proceeding."
1007
  msgstr ""
1008
 
@@ -1028,6 +1035,10 @@ msgid "Confirm Number"
1028
  msgstr ""
1029
 
1030
  #: inc/classes/parts/class-part-number.php:183
 
 
 
 
1031
  #: inc/classes/parts/class-part-phone.php:399
1032
  msgid "Number and confirmation number are not matching."
1033
  msgstr ""
@@ -1197,59 +1208,59 @@ msgstr ""
1197
  msgid "How can I access my premium upgrade credentials?"
1198
  msgstr ""
1199
 
1200
- #: inc/helpers/helper-form-templates.php:723
1201
  msgid "Get my location"
1202
  msgstr ""
1203
 
1204
- #: inc/helpers/helper-form-templates.php:723
1205
  msgid "Fetching location…"
1206
  msgstr ""
1207
 
1208
- #: inc/helpers/helper-form-templates.php:734
1209
  msgid "January"
1210
  msgstr ""
1211
 
1212
- #: inc/helpers/helper-form-templates.php:735
1213
  msgid "February"
1214
  msgstr ""
1215
 
1216
- #: inc/helpers/helper-form-templates.php:736
1217
  msgid "March"
1218
  msgstr ""
1219
 
1220
- #: inc/helpers/helper-form-templates.php:737
1221
  msgid "April"
1222
  msgstr ""
1223
 
1224
- #: inc/helpers/helper-form-templates.php:738
1225
  msgid "May"
1226
  msgstr ""
1227
 
1228
- #: inc/helpers/helper-form-templates.php:739
1229
  msgid "June"
1230
  msgstr ""
1231
 
1232
- #: inc/helpers/helper-form-templates.php:740
1233
  msgid "July"
1234
  msgstr ""
1235
 
1236
- #: inc/helpers/helper-form-templates.php:741
1237
  msgid "August"
1238
  msgstr ""
1239
 
1240
- #: inc/helpers/helper-form-templates.php:742
1241
  msgid "September"
1242
  msgstr ""
1243
 
1244
- #: inc/helpers/helper-form-templates.php:743
1245
  msgid "October"
1246
  msgstr ""
1247
 
1248
- #: inc/helpers/helper-form-templates.php:744
1249
  msgid "November"
1250
  msgstr ""
1251
 
1252
- #: inc/helpers/helper-form-templates.php:745
1253
  msgid "December"
1254
  msgstr ""
1255
 
@@ -2303,10 +2314,13 @@ msgid "Add Part"
2303
  msgstr ""
2304
 
2305
  #: inc/templates/customize-form-item.php:21
 
 
2306
  msgid "Setup"
2307
  msgstr ""
2308
 
2309
  #: inc/templates/customize-form-item.php:24
 
2310
  msgid "Style"
2311
  msgstr ""
2312
 
@@ -2341,7 +2355,7 @@ msgid "Confirmation message"
2341
  msgstr ""
2342
 
2343
  #: inc/templates/customize-form-setup.php:12
2344
- msgid "Receive subscription alerts"
2345
  msgstr ""
2346
 
2347
  #: inc/templates/customize-form-setup.php:21
@@ -2390,72 +2404,80 @@ msgid "Save messages for this form"
2390
  msgstr ""
2391
 
2392
  #: inc/templates/customize-form-setup.php:82
 
 
 
 
 
 
 
 
2393
  msgid ""
2394
  "This is the message your users will see after succesfully submitting your "
2395
  "form."
2396
  msgstr ""
2397
 
2398
- #: inc/templates/customize-form-setup.php:85
2399
  msgid ""
2400
  "Add your email address here to receive a confirmation email for each form "
2401
  "response. You can add multiple email addresses by separating each address "
2402
  "with a comma."
2403
  msgstr ""
2404
 
2405
- #: inc/templates/customize-form-setup.php:88
2406
  msgid ""
2407
  "Each time a user submits a message, you'll receive an email with this "
2408
  "subject."
2409
  msgstr ""
2410
 
2411
- #: inc/templates/customize-form-setup.php:91
2412
  msgid ""
2413
  "If your form contains an email field, recipients will receive an email with "
2414
  "this content."
2415
  msgstr ""
2416
 
2417
- #: inc/templates/customize-form-setup.php:94
2418
  msgid ""
2419
  "If your form contains an email field, recipients will receive an email with "
2420
  "this subject."
2421
  msgstr ""
2422
 
2423
- #: inc/templates/customize-form-setup.php:97
2424
  msgid ""
2425
  "By default, recipients will be redirected to the post or page displaying "
2426
  "this form. To set a custom redirect webpage, add a link here."
2427
  msgstr ""
2428
 
2429
- #: inc/templates/customize-form-setup.php:100
2430
  msgid "Protect your form against bots by using HoneyPot security."
2431
  msgstr ""
2432
 
2433
- #: inc/templates/customize-form-setup.php:103
2434
  msgid "Protect your form against bots using your Google ReCaptcha credentials."
2435
  msgstr ""
2436
 
2437
- #: inc/templates/customize-form-setup.php:106
2438
  msgid "Keep recipients responses stored in your WordPress database."
2439
  msgstr ""
2440
 
2441
- #: inc/templates/customize-form-steps.php:3
2442
- msgid "Previous"
2443
  msgstr ""
2444
 
2445
- #: inc/templates/customize-form-steps.php:3
2446
- msgid "Next"
2447
  msgstr ""
2448
 
2449
- #: inc/templates/customize-form-steps.php:3
2450
- msgid "Save form"
2451
  msgstr ""
2452
 
2453
- #: inc/templates/customize-form-steps.php:9
2454
  #: inc/templates/parts/customize-scale.php:75
2455
  msgid "Step"
2456
  msgstr ""
2457
 
2458
- #: inc/templates/customize-form-steps.php:9
2459
  msgid "of"
2460
  msgstr ""
2461
 
@@ -2538,7 +2560,6 @@ msgstr ""
2538
 
2539
  #: inc/templates/parts/customize-address.php:13
2540
  #: inc/templates/parts/customize-multi-line-text.php:13
2541
- #: inc/templates/parts/customize-phone.php:13
2542
  msgid "Inside"
2543
  msgstr ""
2544
 
@@ -2872,6 +2893,7 @@ msgstr ""
2872
 
2873
  #: inc/templates/parts/customize-email.php:13
2874
  #: inc/templates/parts/customize-number.php:13
 
2875
  #: inc/templates/parts/customize-single-line-text.php:13
2876
  #: inc/templates/parts/customize-website-url.php:13
2877
  msgid "Inside input"
@@ -2894,11 +2916,13 @@ msgid "Legal text"
2894
  msgstr ""
2895
 
2896
  #: inc/templates/parts/customize-number.php:37
2897
- msgid "Minimum accepted value"
 
2898
  msgstr ""
2899
 
2900
  #: inc/templates/parts/customize-number.php:41
2901
- msgid "Maximum accepted value"
 
2902
  msgstr ""
2903
 
2904
  #: inc/templates/parts/customize-number.php:53
@@ -2934,14 +2958,6 @@ msgstr ""
2934
  msgid "Make this option default"
2935
  msgstr ""
2936
 
2937
- #: inc/templates/parts/customize-scale.php:31
2938
- msgid "Minimum value"
2939
- msgstr ""
2940
-
2941
- #: inc/templates/parts/customize-scale.php:35
2942
- msgid "Maximum value"
2943
- msgstr ""
2944
-
2945
  #: inc/templates/parts/customize-scale.php:47
2946
  msgid "Allow range select"
2947
  msgstr ""
@@ -2955,11 +2971,11 @@ msgid "Default range to"
2955
  msgstr ""
2956
 
2957
  #: inc/templates/parts/customize-scale.php:66
2958
- msgid "Minimum value label"
2959
  msgstr ""
2960
 
2961
  #: inc/templates/parts/customize-scale.php:70
2962
- msgid "Maximum value label"
2963
  msgstr ""
2964
 
2965
  #: inc/templates/parts/customize-select.php:40
@@ -3008,12 +3024,12 @@ msgstr ""
3008
  msgid "Add row"
3009
  msgstr ""
3010
 
3011
- #: inc/templates/parts/frontend-address.php:38
3012
- #: inc/templates/parts/frontend-address.php:51
3013
  msgid "Country"
3014
  msgstr ""
3015
 
3016
- #: inc/templates/parts/frontend-address.php:57
3017
  msgid "City"
3018
  msgstr ""
3019
 
@@ -3029,37 +3045,37 @@ msgstr ""
3029
  msgid "Month"
3030
  msgstr ""
3031
 
3032
- #: inc/templates/parts/frontend-date.php:35
3033
- #: inc/templates/parts/frontend-date.php:41
3034
- #: inc/templates/parts/frontend-date.php:62
3035
  msgid "Year"
3036
  msgstr ""
3037
 
3038
- #: inc/templates/parts/frontend-date.php:130
3039
  msgid "Period"
3040
  msgstr ""
3041
 
3042
- #: inc/templates/parts/frontend-date.php:142
3043
  msgid "AM"
3044
  msgstr ""
3045
 
3046
- #: inc/templates/parts/frontend-date.php:143
3047
  msgid "PM"
3048
  msgstr ""
3049
 
3050
- #: inc/templates/parts/frontend-rating.php:10
3051
  msgid "Stars"
3052
  msgstr ""
3053
 
3054
- #: inc/templates/parts/frontend-select.php:28
3055
- #: inc/templates/parts/frontend-select.php:34
3056
- #: inc/templates/parts/frontend-title.php:18
3057
- #: inc/templates/parts/frontend-title.php:24
3058
  msgid "- Select -"
3059
  msgstr ""
3060
 
3061
- #: inc/templates/parts/frontend-select.php:58
3062
- #: inc/templates/parts/frontend-title.php:43
3063
  msgid "Select"
3064
  msgstr ""
3065
 
2
  # This file is distributed under the same license as the HappyForms package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: HappyForms 1.5.6\n"
6
  "Report-Msgid-Bugs-To: https://thethemefoundry.com/support/\n"
7
+ "POT-Creation-Date: 2018-08-14 15:34:59+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
14
  "X-Generator: grunt-wp-i18n 0.4.9\n"
15
 
16
  #: inc/classes/class-form-admin.php:155
17
+ #: inc/classes/class-form-controller.php:85
18
  msgid "View form"
19
  msgstr ""
20
 
102
  msgstr ""
103
 
104
  #: inc/classes/class-form-admin.php:358
105
+ #: inc/templates/partials/form-confirm-preview.php:3
106
  msgid "Edit"
107
  msgstr ""
108
 
125
  msgid " Copy"
126
  msgstr ""
127
 
128
+ #: inc/classes/class-form-controller.php:80
129
+ #: inc/classes/class-form-controller.php:90
130
  #: inc/classes/class-happyforms-plugin.php:153
131
  #: inc/classes/class-happyforms-plugin.php:154
132
  msgid "All Forms"
133
  msgstr ""
134
 
135
+ #: inc/classes/class-form-controller.php:81
136
  #: inc/classes/class-message-admin.php:317
137
  #: inc/classes/class-message-admin.php:790
138
  msgid "Form"
139
  msgstr ""
140
 
141
+ #: inc/classes/class-form-controller.php:82
142
+ #: inc/classes/class-form-controller.php:84
143
  msgid "Build form"
144
  msgstr ""
145
 
146
+ #: inc/classes/class-form-controller.php:83
147
  msgid "Edit form"
148
  msgstr ""
149
 
150
+ #: inc/classes/class-form-controller.php:86
151
  msgid "View forms"
152
  msgstr ""
153
 
154
+ #: inc/classes/class-form-controller.php:87
155
  msgid "Search Forms"
156
  msgstr ""
157
 
158
+ #: inc/classes/class-form-controller.php:88
159
  msgid "No form found"
160
  msgstr ""
161
 
162
+ #: inc/classes/class-form-controller.php:89
163
  msgid "No forms found in Trash"
164
  msgstr ""
165
 
166
+ #: inc/classes/class-form-controller.php:184
167
  msgid "Untitled form"
168
  msgstr ""
169
 
170
+ #: inc/classes/class-form-controller.php:205
171
+ #: inc/classes/class-form-controller.php:229
172
  msgid ""
173
  "Your message has been successfully sent. We appreciate you contacting us "
174
  "and we’ll be in touch soon."
175
  msgstr ""
176
 
177
+ #: inc/classes/class-form-controller.php:217
178
  msgid "You received a new message"
179
  msgstr ""
180
 
181
+ #: inc/classes/class-form-controller.php:225
182
  msgid "We received your message"
183
  msgstr ""
184
 
185
+ #: inc/classes/class-form-controller.php:241
186
  msgid "Submit Form"
187
  msgstr ""
188
 
189
+ #: inc/classes/class-form-controller.php:269
190
+ msgid "Review submission"
191
+ msgstr ""
192
+
193
+ #: inc/classes/class-form-controller.php:765
194
+ #: inc/classes/class-message-controller.php:271
195
+ #: inc/classes/class-message-controller.php:359
196
+ #: inc/classes/class-message-controller.php:394
197
  msgid "Your submission contains errors."
198
  msgstr ""
199
 
646
  msgstr ""
647
 
648
  #: inc/classes/class-message-admin.php:182
649
+ #: inc/classes/class-message-controller.php:171
650
  msgid "View response"
651
  msgstr ""
652
 
775
  msgid "Unread"
776
  msgstr ""
777
 
778
+ #: inc/classes/class-message-controller.php:144
779
  msgid "New submission"
780
  msgstr ""
781
 
782
+ #: inc/classes/class-message-controller.php:168
783
+ #: inc/classes/class-message-controller.php:176
784
  msgid "All Responses"
785
  msgstr ""
786
 
787
+ #: inc/classes/class-message-controller.php:169
788
  msgid "Response"
789
  msgstr ""
790
 
791
+ #: inc/classes/class-message-controller.php:170
792
  msgid "Edit response"
793
  msgstr ""
794
 
795
+ #: inc/classes/class-message-controller.php:172
796
  msgid "View Responses"
797
  msgstr ""
798
 
799
+ #: inc/classes/class-message-controller.php:173
800
  msgid "Search Responses"
801
  msgstr ""
802
 
803
+ #: inc/classes/class-message-controller.php:174
804
  msgid "No response found"
805
  msgstr ""
806
 
807
+ #: inc/classes/class-message-controller.php:175
808
  msgid "No response found in Trash"
809
  msgstr ""
810
 
898
  msgstr ""
899
 
900
  #: inc/classes/parts/class-part-address.php:13
901
+ #: inc/classes/parts/class-part-address.php:43
902
  msgid "Address"
903
  msgstr ""
904
 
906
  msgid "For geographical locations. Includes Google Maps intergration."
907
  msgstr ""
908
 
909
+ #: inc/classes/parts/class-part-address.php:193
910
  #: inc/classes/parts/class-part-checkbox.php:165
911
+ #: inc/classes/parts/class-part-date.php:194
912
  #: inc/classes/parts/class-part-email.php:142
913
  #: inc/classes/parts/class-part-email.php:146
914
+ #: inc/classes/parts/class-part-legal.php:113
915
  #: inc/classes/parts/class-part-multi-line-text.php:141
916
  #: inc/classes/parts/class-part-number.php:175
917
  #: inc/classes/parts/class-part-number.php:179
958
  msgid "For formatted day, month, year and or time fields."
959
  msgstr ""
960
 
961
+ #: inc/classes/parts/class-part-date.php:32
962
  #: inc/templates/parts/customize-date.php:32
963
  msgid "Date"
964
  msgstr ""
965
 
966
+ #: inc/classes/parts/class-part-date.php:226
967
  msgid "Not a valid date."
968
  msgstr ""
969
 
970
+ #: inc/classes/parts/class-part-date.php:238
971
  msgid "Hour input does not match minimum and maximum value allowed."
972
  msgstr ""
973
 
974
+ #: inc/classes/parts/class-part-date.php:251
975
  msgid "Year input does not match maximum value allowed."
976
  msgstr ""
977
 
997
  msgstr ""
998
 
999
  #: inc/classes/parts/class-part-legal.php:9
1000
+ #: inc/classes/parts/class-part-legal.php:45
1001
  msgid "Legal"
1002
  msgstr ""
1003
 
1005
  msgid "For requiring fine print before accepting submission."
1006
  msgstr ""
1007
 
1008
+ #: inc/classes/parts/class-part-legal.php:29
1009
  msgid "I accept terms and conditions."
1010
  msgstr ""
1011
 
1012
+ #: inc/classes/parts/class-part-legal.php:118
1013
  msgid "Please accept terms before proceeding."
1014
  msgstr ""
1015
 
1035
  msgstr ""
1036
 
1037
  #: inc/classes/parts/class-part-number.php:183
1038
+ msgid "This field does not match minimum and maximum allowed value."
1039
+ msgstr ""
1040
+
1041
+ #: inc/classes/parts/class-part-number.php:187
1042
  #: inc/classes/parts/class-part-phone.php:399
1043
  msgid "Number and confirmation number are not matching."
1044
  msgstr ""
1208
  msgid "How can I access my premium upgrade credentials?"
1209
  msgstr ""
1210
 
1211
+ #: inc/helpers/helper-form-templates.php:770
1212
  msgid "Get my location"
1213
  msgstr ""
1214
 
1215
+ #: inc/helpers/helper-form-templates.php:770
1216
  msgid "Fetching location…"
1217
  msgstr ""
1218
 
1219
+ #: inc/helpers/helper-form-templates.php:781
1220
  msgid "January"
1221
  msgstr ""
1222
 
1223
+ #: inc/helpers/helper-form-templates.php:782
1224
  msgid "February"
1225
  msgstr ""
1226
 
1227
+ #: inc/helpers/helper-form-templates.php:783
1228
  msgid "March"
1229
  msgstr ""
1230
 
1231
+ #: inc/helpers/helper-form-templates.php:784
1232
  msgid "April"
1233
  msgstr ""
1234
 
1235
+ #: inc/helpers/helper-form-templates.php:785
1236
  msgid "May"
1237
  msgstr ""
1238
 
1239
+ #: inc/helpers/helper-form-templates.php:786
1240
  msgid "June"
1241
  msgstr ""
1242
 
1243
+ #: inc/helpers/helper-form-templates.php:787
1244
  msgid "July"
1245
  msgstr ""
1246
 
1247
+ #: inc/helpers/helper-form-templates.php:788
1248
  msgid "August"
1249
  msgstr ""
1250
 
1251
+ #: inc/helpers/helper-form-templates.php:789
1252
  msgid "September"
1253
  msgstr ""
1254
 
1255
+ #: inc/helpers/helper-form-templates.php:790
1256
  msgid "October"
1257
  msgstr ""
1258
 
1259
+ #: inc/helpers/helper-form-templates.php:791
1260
  msgid "November"
1261
  msgstr ""
1262
 
1263
+ #: inc/helpers/helper-form-templates.php:792
1264
  msgid "December"
1265
  msgstr ""
1266
 
2314
  msgstr ""
2315
 
2316
  #: inc/templates/customize-form-item.php:21
2317
+ #: inc/templates/customize-form-steps.php:8
2318
+ #: inc/templates/customize-form-steps.php:15
2319
  msgid "Setup"
2320
  msgstr ""
2321
 
2322
  #: inc/templates/customize-form-item.php:24
2323
+ #: inc/templates/customize-form-steps.php:18
2324
  msgid "Style"
2325
  msgstr ""
2326
 
2355
  msgstr ""
2356
 
2357
  #: inc/templates/customize-form-setup.php:12
2358
+ msgid "Receive submission alerts"
2359
  msgstr ""
2360
 
2361
  #: inc/templates/customize-form-setup.php:21
2404
  msgstr ""
2405
 
2406
  #: inc/templates/customize-form-setup.php:82
2407
+ msgid "Preview values before submission"
2408
+ msgstr ""
2409
+
2410
+ #: inc/templates/customize-form-setup.php:87
2411
+ msgid "Review button text"
2412
+ msgstr ""
2413
+
2414
+ #: inc/templates/customize-form-setup.php:94
2415
  msgid ""
2416
  "This is the message your users will see after succesfully submitting your "
2417
  "form."
2418
  msgstr ""
2419
 
2420
+ #: inc/templates/customize-form-setup.php:97
2421
  msgid ""
2422
  "Add your email address here to receive a confirmation email for each form "
2423
  "response. You can add multiple email addresses by separating each address "
2424
  "with a comma."
2425
  msgstr ""
2426
 
2427
+ #: inc/templates/customize-form-setup.php:100
2428
  msgid ""
2429
  "Each time a user submits a message, you'll receive an email with this "
2430
  "subject."
2431
  msgstr ""
2432
 
2433
+ #: inc/templates/customize-form-setup.php:103
2434
  msgid ""
2435
  "If your form contains an email field, recipients will receive an email with "
2436
  "this content."
2437
  msgstr ""
2438
 
2439
+ #: inc/templates/customize-form-setup.php:106
2440
  msgid ""
2441
  "If your form contains an email field, recipients will receive an email with "
2442
  "this subject."
2443
  msgstr ""
2444
 
2445
+ #: inc/templates/customize-form-setup.php:109
2446
  msgid ""
2447
  "By default, recipients will be redirected to the post or page displaying "
2448
  "this form. To set a custom redirect webpage, add a link here."
2449
  msgstr ""
2450
 
2451
+ #: inc/templates/customize-form-setup.php:112
2452
  msgid "Protect your form against bots by using HoneyPot security."
2453
  msgstr ""
2454
 
2455
+ #: inc/templates/customize-form-setup.php:115
2456
  msgid "Protect your form against bots using your Google ReCaptcha credentials."
2457
  msgstr ""
2458
 
2459
+ #: inc/templates/customize-form-setup.php:118
2460
  msgid "Keep recipients responses stored in your WordPress database."
2461
  msgstr ""
2462
 
2463
+ #: inc/templates/customize-form-setup.php:121
2464
+ msgid "Let your users review their submission before confirming it."
2465
  msgstr ""
2466
 
2467
+ #: inc/templates/customize-form-steps.php:5
2468
+ msgid "Build"
2469
  msgstr ""
2470
 
2471
+ #: inc/templates/customize-form-steps.php:23
2472
+ msgid "Finish"
2473
  msgstr ""
2474
 
2475
+ #: inc/templates/customize-form-steps.php:30
2476
  #: inc/templates/parts/customize-scale.php:75
2477
  msgid "Step"
2478
  msgstr ""
2479
 
2480
+ #: inc/templates/customize-form-steps.php:30
2481
  msgid "of"
2482
  msgstr ""
2483
 
2560
 
2561
  #: inc/templates/parts/customize-address.php:13
2562
  #: inc/templates/parts/customize-multi-line-text.php:13
 
2563
  msgid "Inside"
2564
  msgstr ""
2565
 
2893
 
2894
  #: inc/templates/parts/customize-email.php:13
2895
  #: inc/templates/parts/customize-number.php:13
2896
+ #: inc/templates/parts/customize-phone.php:13
2897
  #: inc/templates/parts/customize-single-line-text.php:13
2898
  #: inc/templates/parts/customize-website-url.php:13
2899
  msgid "Inside input"
2916
  msgstr ""
2917
 
2918
  #: inc/templates/parts/customize-number.php:37
2919
+ #: inc/templates/parts/customize-scale.php:31
2920
+ msgid "Minimum value"
2921
  msgstr ""
2922
 
2923
  #: inc/templates/parts/customize-number.php:41
2924
+ #: inc/templates/parts/customize-scale.php:35
2925
+ msgid "Maximum value"
2926
  msgstr ""
2927
 
2928
  #: inc/templates/parts/customize-number.php:53
2958
  msgid "Make this option default"
2959
  msgstr ""
2960
 
 
 
 
 
 
 
 
 
2961
  #: inc/templates/parts/customize-scale.php:47
2962
  msgid "Allow range select"
2963
  msgstr ""
2971
  msgstr ""
2972
 
2973
  #: inc/templates/parts/customize-scale.php:66
2974
+ msgid "Min value label"
2975
  msgstr ""
2976
 
2977
  #: inc/templates/parts/customize-scale.php:70
2978
+ msgid "Max value label"
2979
  msgstr ""
2980
 
2981
  #: inc/templates/parts/customize-select.php:40
3024
  msgid "Add row"
3025
  msgstr ""
3026
 
3027
+ #: inc/templates/parts/frontend-address.php:41
3028
+ #: inc/templates/parts/frontend-address.php:54
3029
  msgid "Country"
3030
  msgstr ""
3031
 
3032
+ #: inc/templates/parts/frontend-address.php:60
3033
  msgid "City"
3034
  msgstr ""
3035
 
3045
  msgid "Month"
3046
  msgstr ""
3047
 
3048
+ #: inc/templates/parts/frontend-date.php:38
3049
+ #: inc/templates/parts/frontend-date.php:44
3050
+ #: inc/templates/parts/frontend-date.php:65
3051
  msgid "Year"
3052
  msgstr ""
3053
 
3054
+ #: inc/templates/parts/frontend-date.php:133
3055
  msgid "Period"
3056
  msgstr ""
3057
 
3058
+ #: inc/templates/parts/frontend-date.php:145
3059
  msgid "AM"
3060
  msgstr ""
3061
 
3062
+ #: inc/templates/parts/frontend-date.php:146
3063
  msgid "PM"
3064
  msgstr ""
3065
 
3066
+ #: inc/templates/parts/frontend-rating.php:13
3067
  msgid "Stars"
3068
  msgstr ""
3069
 
3070
+ #: inc/templates/parts/frontend-select.php:31
3071
+ #: inc/templates/parts/frontend-select.php:37
3072
+ #: inc/templates/parts/frontend-title.php:21
3073
+ #: inc/templates/parts/frontend-title.php:27
3074
  msgid "- Select -"
3075
  msgstr ""
3076
 
3077
+ #: inc/templates/parts/frontend-select.php:61
3078
+ #: inc/templates/parts/frontend-title.php:46
3079
  msgid "Select"
3080
  msgstr ""
3081
 
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: contact, contact form, email, feedback form, form, form builder, custom fo
5
  Requires at least: 4.8
6
  Tested up to: 4.9.7
7
  Requires PHP: 5.2.4
8
- Stable tag: 1.5.5
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -75,6 +75,15 @@ Absolutely! HappyForms gets out of the way and is designed to work with any them
75
 
76
  == Changelog ==
77
 
 
 
 
 
 
 
 
 
 
78
  = 1.5.5 =
79
  * New feature: Redesigned dropdowns and a new setting to make Dropdown part searchable.
80
  * New feature: Redesigned Phone part now with country flags and a new searchable country dropdown.
@@ -200,6 +209,9 @@ Absolutely! HappyForms gets out of the way and is designed to work with any them
200
 
201
  == Upgrade Notice ==
202
 
 
 
 
203
  = 1.5.5 =
204
  * Redesigned dropdowns, new look of Phone part, enhanced shortcode, and bug fixes.
205
 
5
  Requires at least: 4.8
6
  Tested up to: 4.9.7
7
  Requires PHP: 5.2.4
8
+ Stable tag: 1.5.6
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
75
 
76
  == Changelog ==
77
 
78
+ = 1.5.6 =
79
+ * New feature: Forms can now show an additional Review step before final submission.
80
+ * Improvement: Previous / Next buttons in form builder got more descriptive labels.
81
+ * Bug fix: Number part didn't allow zero value even when 0 was set as a minimum required value.
82
+ * Bug fix: Email part didn't allow an empty value submitted even when field was not required.
83
+ * Bug fix: Fixes for multiple style issues across all parts in CSS.
84
+ * Bug fix: Welcome screen appearance on RTL layouts.
85
+ * Bug fix: Forms and Responses were appearing in public searches and queries.
86
+
87
  = 1.5.5 =
88
  * New feature: Redesigned dropdowns and a new setting to make Dropdown part searchable.
89
  * New feature: Redesigned Phone part now with country flags and a new searchable country dropdown.
209
 
210
  == Upgrade Notice ==
211
 
212
+ = 1.5.6 =
213
+ * Form previews, Customize improvements and bugfixes.
214
+
215
  = 1.5.5 =
216
  * Redesigned dropdowns, new look of Phone part, enhanced shortcode, and bug fixes.
217