1$(function() 2{ 3 $('[data-form-type="blocs-form"] input,[data-form-type="blocs-form"] textarea,[data-form-type="blocs-form"] select').jqBootstrapValidation( 4 { 5 preventSubmit: true, 6 submitSuccess: function($form, event) 7 { 8 if(!$form.attr('action')) // Check form doesnt have action attribute 9 { 10 event.preventDefault(); // prevent default submit behaviour 11 12 // Honeypot Check 13 const $hp = $form.find('[data-honeypot]'); 14 if ($hp.length && ($hp.val() || '').trim().length) { 15 $form.trigger('reset'); 16 return; 17 } 18 19 // Timestamp Check 20 const $ts = $form.find('[data-blocsapp-form-ts]'); 21 if ($ts.length) { 22 const started = parseInt($ts.val(), 10); 23 const elapsedMs = Date.now() - (isNaN(started) ? 0 : started); 24 if (!started || elapsedMs < 3000) { 25 $form.trigger('reset'); 26 return; 27 } 28 } 29 30 var processorFile = getProcessorPath($form); 31 32 // Create Form Data 33 var formData = new FormData(); 34 35 // Loop over fields and append 36 $form.find("input, textarea, select").each(function () 37 { 38 if ($(this).is('[data-honeypot], [data-blocsapp-form-ts]')) return; // Skip fields; 39 40 if (this.type === 'file') 41 { 42 if (this.files && this.files.length) { 43 44 const DEFAULT_PER_FILE = 5 * 1024 * 1024; // 5MB 45 const DEFAULT_TOTAL = 10 * 1024 * 1024; // 10MB total 46 47 // Read Max Size data attributes (MB â bytes) 48 const maxPerFile = this.dataset.maxFileSize ? parseFloat(this.dataset.maxFileSize) * 1024 * 1024 : DEFAULT_PER_FILE; 49 const maxTotal = this.dataset.maxFileTotal ? parseFloat(this.dataset.maxFileTotal) * 1024 * 1024 : DEFAULT_TOTAL; 50 51 let key = (this.name || this.id); 52 53 if (this.multiple && !key.endsWith('[]')) { 54 key += '[]'; 55 } 56 57 let totalSize = 0; 58 59 for (let i = 0; i < this.files.length; i++) { 60 61 const file = this.files[i]; 62 63 // Per-file limit 64 if (file.size > maxPerFile) 65 { 66 const size = Math.round(maxPerFile / (1024 * 1024)); 67 showFormErrorMessage(file.name + ' exceeds the '+size+'MB size limit.'); 68 return false; 69 } 70 71 totalSize += file.size; 72 73 // Total limit 74 if (totalSize > maxTotal) { 75 showFormErrorMessage('Total attachments must not exceed 10MB.'); 76 return false; 77 } 78 79 formData.append(key, file); 80 } 81 } 82 83 return; 84 } 85 86 if (this.type === 'checkbox') 87 { 88 formData.append(this.name || this.id, $(this).is(':checked') ? 'True' : 'False'); 89 return; 90 } 91 92 if (this.type === 'radio') 93 { 94 let isChecked = $(this).is(':checked') ? 'True' : 'False'; 95 let value = $(this).val() + ' = ' + isChecked; 96 formData.append(this.id, value); 97 return; 98 } 99 100 if (this.tagName === 'SELECT') 101 { 102 const val = $(this).val(); 103 if (Array.isArray(val)) { 104 formData.append(this.id, val.join(',')); 105 } else { 106 formData.append(this.id, val); 107 } 108 return; 109 } 110 111 // Text Input Fields & Text Areas 112 formData.append(this.name || this.id, $(this).val()); 113 }); 114 115 $.ajax({ 116 url: processorFile, 117 type: "POST", 118 data: formData, 119 cache: false, 120 processData: false, 121 contentType: false, 122 success: function(data) // Success 123 { 124 if (!$form.find('#form-feedback-alert').length) // Add Alert Container 125 { 126 $form.append("<div id='form-feedback-alert' class='mt-2'></div>"); 127 } 128 129 if (data == 'capture-error' || data == 'capture-connection-error') // Capture Error 130 { 131 var type = (data === 'capture-connection-error') ? 'fail' : 'warning'; 132 const message = $form.find('.g-recaptcha').attr('data-capture-'+type); 133 let alert = "<div class='alert alert-danger' role='alert'><button type='button' class='btn-close float-end' data-bs-dismiss='alert' aria-hidden='true'></button>"+message+"</div>"; 134 $form.find('#form-feedback-alert').html(alert); 135 } 136 else // Success 137 { 138 $form.trigger("reset"); // Clear Form 139 140 if ($form.is('[data-success-msg]')) // Show Success Message 141 { 142 const message = $form.attr('data-success-msg'); 143 let alert = "<div class='alert alert-success' role='alert'><button type='button' class='btn-close float-end' data-bs-dismiss='alert' aria-hidden='true'></button>"+message+"</div>"; 144 $form.find('#form-feedback-alert').html(alert); 145 } 146 else if ($form.is('[data-success-item-id]')) // Show Item Based on ID 147 { 148 let targetID = $form.attr('data-success-item-id'); 149 $(targetID).show(); 150 } 151 else if ($form.is('[data-custom-interaction-success-id]')) // Custom Interaction 152 { 153 let name = $form.attr('data-custom-interaction-success-id'); 154 const customInteraction = window[name]; 155 156 if (typeof customInteraction === 'function') { 157 customInteraction(); 158 } 159 } 160 else // Re-Direct 161 { 162 window.location.replace($form.attr('data-success-url')); 163 } 164 } 165 }, 166 error: function(xhr, status, error) // Error Posting Form 167 { 168 let errorMessage = $form.attr('data-fail-msg'); 169 var response = $.parseJSON(xhr.responseText); 170 171 if (response.code == 'upload_limit') // Handle Server Max File Size Limit 172 { 173 errorMessage = 'Sorry, your file is too large. This form supports files up to ' + response.info + '. Please choose a smaller file.'; 174 } 175 176 showFormErrorMessage(errorMessage); 177 178 // Log Error 179 console.log("Form Error: " + response.message); 180 }, 181 }); 182 183 // Show Error Message 184 function showFormErrorMessage(message) 185 { 186 if ($('#form-alert').length == 0) 187 { 188 $form.append("<div id='form-alert'class='alert alert-danger mt-2' role='alert'><button type='button' class='btn-close float-end' data-bs-dismiss='alert' aria-hidden='true'></button><span>"+message+"</span></div>"); 189 } 190 } 191 } 192 }, 193 filter: function() // Handle hidden form elements 194 { 195 return $(this).is(":visible"); 196 }, 197 }); 198 199 // Get Path to processor PHP file 200 function getProcessorPath(form) 201 { 202 var path = siteRelativeURLPath+"includes/"+form.attr('id')+".php"; 203 204 if (form.attr('template-path')) // Check For Template Path (Wordpress) 205 { 206 path = form.attr('template-path')+"/includes/"+form.attr('id')+".php"; 207 } 208 209 return path 210 } 211});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.