PluginProbe
FormLayer / 1.0.7
FormLayer v1.0.7
1.0.9 1.0.8 1.0.7 1.0.6 trunk 1.0.3 1.0.4 1.0.5
formlayer / assets / js / frontend.js

frontend.js in FormLayer 1.0.7, at assets/js/frontend.js

176 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 jQuery(document).ready(function($){
2
3 $('.formlayer-form').on('submit', function(e){
4 e.preventDefault();
5
6 let $form = $(this);
7 $submit_Btn = $form.find('.formlayer-submit-btn'),
8 $status = $form.find('.formlayer-form-status'),
9 formId = $form.data('form-id');
10
11 $submit_Btn.prop('disabled', true).addClass('loading');
12 $status.html('').removeClass('formlayer-success-message formlayer-error-message');
13
14 var formData = new FormData(this);
15
16 // Client-side Validation
17 var errors = [];
18
19 // Email Confirmation Match
20 $form.find('.formlayer-email-confirm').each(function(){
21 var matchName = $(this).data('match');
22 var originalVal = $form.find('input[name="' + matchName + '"]').val();
23 if($(this).val() !== originalVal){
24 errors.push('Emails do not match.');
25 }
26 });
27
28 // Digit Limit Validation
29 $form.find('input[type="number"][maxlength]').each(function(){
30 var limit = parseInt($(this).attr('maxlength'));
31 if($(this).val().length > limit){
32 errors.push('Value exceeds maximum digit limit of ' + limit);
33 }
34 });
35
36 // URL Validation
37 $form.find('input[data-validate-url="1"]').each(function(){
38 var val = $(this).val();
39 if(val && !val.match(/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/)){
40 errors.push('Please enter a valid URL.');
41 }
42 });
43
44 // URL HTTPS Only Validation
45 $form.find('input[data-https-only="1"]').each(function(){
46 var val = $(this).val();
47 if(val && !val.startsWith('https://')){
48 errors.push('Only HTTPS URLs are allowed.');
49 }
50 });
51
52 if(errors.length > 0){
53 $status.addClass('formlayer-error-message').html(errors.join('<br>'));
54 $submit_Btn.prop('disabled', false).removeClass('loading');
55 return;
56 }
57
58 formData.append('action', 'formlayer_submit_form');
59 formData.append('nonce', formlayer_data.nonce);
60 formData.append('form_id', formId);
61
62 $.ajax({
63 url: formlayer_data.ajax_url,
64 method: 'POST',
65 data: formData,
66 processData: false,
67 contentType: false,
68 success: function(response){
69 $submit_Btn.prop('disabled', false).removeClass('loading');
70
71 if(response.success){
72 var settings = response.data.settings || {};
73 var confirmation = settings.confirmations || { type: 'message', message: 'Thank you! Your form has been submitted successfully.', hide_form: true };
74
75 if(confirmation.type === 'redirect' && confirmation.redirect_url){
76 $status.addClass('formlayer-success-message').html('Redirecting...');
77 window.location.href = confirmation.redirect_url;
78 }else{
79 if(confirmation.hide_form !== false){
80 $form.find('.formlayer-form-fields-wrapper').hide();
81 }
82 $form[0].reset();
83 $status.addClass('formlayer-success-message').html(confirmation.message || 'Thank you! Your form has been submitted successfully.');
84 }
85 }else{
86 $status.addClass('formlayer-error-message').html(response.data.message || 'An error occurred.');
87 }
88 },
89 error: function(jqXHR, textStatus, errorThrown){
90 $submit_Btn.prop('disabled', false).removeClass('loading');
91 console.error('Submission error:', textStatus, errorThrown, jqXHR.responseText);
92
93 // User friendly message instead of technical parsererror
94 var msg = 'An unexpected error occurred. Please try again.';
95 if(textStatus === 'timeout') msg = 'Request timed out. Please check your connection.';
96
97 $status.addClass('formlayer-error-message').html(msg);
98 }
99 });
100 });
101 // Rating Field Interaction
102 $('.formlayer-rating .dashicons').on('click', function(){
103 var value = $(this).data('value');
104 var $container = $(this).closest('.formlayer-rating');
105 $container.find('input').val(value);
106 $container.find('.dashicons').removeClass('active');
107 $(this).addClass('active').prevAll().addClass('active');
108 });
109
110 $('.formlayer-rating .dashicons').on('mouseenter', function(){
111 $(this).addClass('hover').prevAll().addClass('hover');
112 $(this).nextAll().removeClass('hover');
113 }).on('mouseleave', '.formlayer-rating .dashicons', function(){
114 $('.formlayer-rating .dashicons').removeClass('hover');
115 });
116
117 // File & Image Upload Preview
118 $('.formlayer-file-real').on('change', function(e){
119 let input = this,
120 $wrap = $(input).closest('.formlayer-field-wrap'),
121 $chosenName = $wrap.find('.formlayer-file-chosen-name');
122
123 // Remove any existing preview container
124 $wrap.find('.formlayer-file-preview-container').remove();
125
126 if (input.files && input.files[0]) {
127 let file = input.files[0];
128 $chosenName.text(file.name);
129
130 // Create preview container
131 let $previewContainer = $(`
132 <div class="formlayer-file-preview-container" style="margin-top:10px; display:flex; align-items:center; gap:12px; padding:10px; border:1px dashed #ccc; border-radius:6px; background:#f9f9f9; max-width: 100%;">
133 <img class="formlayer-file-preview-img" src="" style="width:60px; height:60px; border-radius:4px; display:none; object-fit:cover; border:1px solid #ddd; background:#fff;">
134 <span class="formlayer-file-preview-icon dashicons dashicons-document" style="font-size:36px; width:36px; height:36px; display:none; color:#5525d6; line-height:36px;"></span>
135 <div style="display:flex; flex-direction:column; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; text-align:left; margin-right: auto;">
136 <span class="formlayer-file-preview-name" style="font-size:13px; font-weight:600; color:#333; overflow:hidden; text-overflow:ellipsis; max-width: 200px;"></span>
137 <span class="formlayer-file-preview-size" style="font-size:11px; color:#777; margin-top: 2px;"></span>
138 </div>
139 <span class="formlayer-file-preview-remove dashicons dashicons-no-alt" style="cursor:pointer; color:#999; font-size:20px; width:20px; height:20px; line-height:20px; text-align:center; transition:color 0.2s;" onmouseover="this.style.color='#d9534f'" onmouseout="this.style.color='#999'"></span>
140 </div>
141 `);
142
143 $previewContainer.find('.formlayer-file-preview-name').text(file.name);
144
145 // Format size
146 let sizeStr = (file.size / 1024).toFixed(1) + ' KB';
147 if (file.size > 1024 * 1024) {
148 sizeStr = (file.size / (1024 * 1024)).toFixed(1) + ' MB';
149 }
150 $previewContainer.find('.formlayer-file-preview-size').text(sizeStr);
151
152 // Show preview image if it's an image
153 if (file.type.match('image.*')) {
154 let reader = new FileReader();
155 reader.onload = function(e) {
156 $previewContainer.find('.formlayer-file-preview-img').attr('src', e.target.result).show();
157 }
158 reader.readAsDataURL(file);
159 } else {
160 $previewContainer.find('.formlayer-file-preview-icon').show();
161 }
162
163 // Add click event for remove cross button
164 $previewContainer.find('.formlayer-file-preview-remove').on('click', function(){
165 $(input).val('');
166 $chosenName.text('No file chosen');
167 $previewContainer.remove();
168 });
169
170 $wrap.append($previewContainer);
171 } else {
172 $chosenName.text('No file chosen');
173 }
174 });
175 });
176