1"use strict"; 2 3jQuery(document).ready(function ($) { 4 const previousButton = document.querySelector("#rsvp-previous-btn"); 5 const nextButton = document.querySelector("#rsvp-next-btn"); 6 const submitButton = document.querySelector("#rsvp-submit-btn"); 7 const tabTargets = document.querySelectorAll(".rsvp-tab-item"); 8 const tabPanels = document.querySelectorAll(".rsvp-tabpanel"); 9 10 const validEmail = 11 /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 12 const isEmpty = (str) => !!parseInt(str); 13 let currentStep = 0; 14 15 const numberOfAttendeeWrapper = document.querySelector( 16 ".number-of-attendee-wrapper" 17 ); 18 const notGoingReason = document.querySelector(".not-going-reason-wrapper"); 19 20 jQuery('input:radio[name="etn_rsvp_value"]').on("change", function (e) { 21 if (e.currentTarget.value === "not_going") { 22 nextButton.classList.add("hidden"); 23 numberOfAttendeeWrapper.classList.add("hidden"); 24 notGoingReason.classList.remove("hidden"); 25 submitButton.classList.remove("hidden"); 26 submitButton.removeAttribute("disabled"); 27 } else { 28 nextButton.classList.remove("hidden"); 29 numberOfAttendeeWrapper.classList.remove("hidden"); 30 notGoingReason.classList.add("hidden"); 31 submitButton.classList.add("hidden"); 32 submitButton.setAttribute("disabled", true); 33 } 34 }); 35 36 // Toggle attendee section 37 const attendeeToggler = jQuery(".view-all-button"); 38 const attendeeGrid = jQuery(".rsvp-attendee-grid"); 39 40 attendeeToggler.on("click", function () { 41 attendeeGrid.slideToggle(function () { 42 attendeeToggler.text( 43 attendeeGrid.is(":visible") ? "Hide Attendees" : "View All attendees" 44 ); 45 }); 46 }); 47 48 // Validate first input on load 49 validateEntry(); 50 51 // Next: Change UI relative to current step and account for button permissions 52 if (nextButton == null) { 53 return; 54 } 55 56 nextButton.addEventListener("click", (event) => { 57 event.preventDefault(); 58 59 // Hide current tab 60 tabPanels[currentStep].classList.add("hidden"); 61 tabTargets[currentStep].classList.remove("active"); 62 tabTargets[currentStep].classList.add("done"); 63 64 // Show next tab 65 tabPanels[currentStep + 1].classList.remove("hidden"); 66 tabTargets[currentStep + 1].classList.add("active"); 67 currentStep += 1; 68 69 validateEntry(); 70 updateStatusDisplay(); 71 // generate multiple form based on attendee number 72 obj.generate_attendee_form($("#rsvp-next-btn")); 73 }); 74 75 // Previous: Change UI relative to current step and account for button permissions 76 previousButton.addEventListener("click", (event) => { 77 event.preventDefault(); 78 79 // Hide current tab 80 tabPanels[currentStep].classList.add("hidden"); 81 tabTargets[currentStep].classList.remove("active"); 82 83 // Show previous tab 84 tabPanels[currentStep - 1].classList.remove("hidden"); 85 tabTargets[currentStep - 1].classList.add("active"); 86 tabTargets[currentStep - 1].classList.remove("done"); 87 currentStep -= 1; 88 89 nextButton.removeAttribute("disabled"); 90 updateStatusDisplay(); 91 // re-open the response form 92 $(".response-form").fadeIn(); 93 }); 94 95 function updateStatusDisplay() { 96 // If on the last step, hide the next button and show submit 97 if (currentStep === tabTargets.length - 1) { 98 nextButton.classList.add("hidden"); 99 previousButton.classList.remove("hidden"); 100 submitButton.classList.remove("hidden"); 101 validateEntry(); 102 103 // If it's the first step hide the previous button 104 } else if (currentStep === 0) { 105 nextButton.classList.remove("hidden"); 106 previousButton.classList.add("hidden"); 107 submitButton.classList.add("hidden"); 108 // In all other instances display both buttons 109 } else { 110 nextButton.classList.remove("hidden"); 111 previousButton.classList.remove("hidden"); 112 submitButton.classList.add("hidden"); 113 } 114 } 115
116 // Validate form entries. 117 function validateEntry() { 118 if (submitButton === null) { 119 return; 120 } 121 122 submitButton.setAttribute("disabled", true); 123 nextButton.setAttribute("disabled", true); 124 125 // Validate attendee number name and email address 126 const numberOfAttendee = document.querySelector(".number-of-attendee"); 127 const attendeeName = document.querySelector(".attendee-name"); 128 const attendeeEmail = document.querySelector(".attendee-email"); 129 const validateNameAndEmail = [ 130 numberOfAttendee, 131 attendeeName, 132 attendeeEmail, 133 ]; 134 135 validateNameAndEmail.forEach((inputElement) => { 136 inputElement.addEventListener("keyup", function () { 137 const RSVPAvailability = parseInt( 138 numberOfAttendee.getAttribute("data-available-rsvp") 139 ); 140 const isAvailable = RSVPAvailability >= numberOfAttendee.value; 141 const RSVPRemaining = parseInt( 142 numberOfAttendee.getAttribute("data-remaining-capacity") 143 ); 144 const isRemaining = RSVPRemaining >= numberOfAttendee.value; 145 const isValid = numberOfAttendee.value > 0; 146 const isEmailValid = validEmail.test( 147 String(attendeeEmail?.value).toLowerCase() 148 ); 149 150 // Handel form element error message 151 const numberErrorNote = document.querySelector( 152 ".attendee-number-error" 153 ); 154 const nameError = document.querySelector(".attendee-name-error"); 155 const emailError = document.querySelector(".attendee-email-error"); 156 157 nameError.innerHTML = ""; 158 emailError.innerHTML = ""; 159 numberErrorNote.innerHTML = ""; 160 161 attendeeName.classList.remove("input-error"); 162 attendeeEmail.classList.remove("input-error"); 163 numberOfAttendee.classList.remove("input-error"); 164 165 // Show error message based on input state. 166 if (!isValid) { 167 numberErrorNote.innerHTML = "Please enter a positive number."; 168 numberOfAttendee.classList.add("input-error"); 169 } else if (!isAvailable) { 170 numberErrorNote.innerHTML = 171 "Input quantity exceeded max submission limit."; 172 numberOfAttendee.classList.add("input-error"); 173 } else if (!isRemaining) { 174 numberErrorNote.innerHTML = 175 "Input quantity exceeded max capacity limit."; 176 numberOfAttendee.classList.add("input-error"); 177 nextButton.setAttribute("disabled", true); 178 } 179 if (attendeeName.value === "") { 180 nameError.innerHTML = "Please enter attendee name."; 181 attendeeName.classList.add("input-error"); 182 } 183 if (!isEmailValid) { 184 emailError.innerHTML = "Enter a valid email address."; 185 attendeeEmail.classList.add("input-error"); 186 } 187 188 // Disable next button based on input values 189 if ( 190 !isEmpty(numberOfAttendee.value) || 191 !isAvailable || 192 !isEmailValid || 193 !isRemaining || 194 attendeeName.value === "" 195 ) { 196 nextButton.setAttribute("disabled", true); 197 submitButton.setAttribute("disabled", true); 198 } else { 199 nextButton.removeAttribute("disabled"); 200 submitButton.removeAttribute("disabled"); 201 } 202 }); 203 }); 204 } 205 206 /* 207 * Select element 208 */ 209 var rsvp_form = $(".rsvp_submit"); 210 var rsvp_submit_btn = $(".rsvp-submit-btn"); 211 var attendee_checked = $("#different-attendee-checkbox"); 212 var submission_message = $(".rsvp-submission-message"); 213 var rsvp_tab = $(".rsvp-tab-wrapper"); 214 215 var obj = { 216 /* 217 * Re format data 218 */ 219 serializeObject(serializedArray) { 220 var serializedObj = {}; 221 const result = serializedArray.reduce((acc, d) => { 222 let idx = acc.findIndex((a) => a.name === d.name); 223 let val = d.value; 224 225 if (idx > -1) { 226 acc[idx].value.push(val); 227 } else { 228 if (d.name.includes("[]")) { 229 acc.push({ name: d.name, value: [val] }); 230 } else { 231 acc.push({ name: d.name, value: val }); 232 } 233 } 234 235 return acc; 236 }, []); 237 238 result.forEach(function (i) { 239 if (i.name.includes("[]")) { 240 var input_name = i.name.replace("[]", ""); 241 serializedObj[input_name] = i.value; 242 } else { 243 serializedObj[i.name] = i.value; 244 } 245 }); 246 247 return serializedObj; 248 }, 249 250 /** 251 * get total attendee 252 * @returns 253 */ 254 get_total_attendee() { 255 var attendee_num = parseInt($("#number-of-attendee").val()); 256 var total_form = attendee_num <= 1 ? 1 : attendee_num; 257 return total_form; 258 }, 259 260 /** 261 * Append attendee form based on attendee number 262 * @returns 263 */ 264 attendee_form_generate() { 265 var is_checked = true; 266 var submit_btn = $("#rsvp-submit-btn"); 267 if (attendee_checked) { 268 var name = ""; 269 var email = ""; 270 attendee_checked.on("change", function () { 271 var total_form = obj.get_total_attendee(); 272 is_checked = attendee_checked.is(":checked"); 273 if (is_checked) { 274 attendee_checked.attr("checked", true); 275 name = $(`#attendee-name-0`).val(); 276 email = $(`#attendee-email-0`).val(); 277 submit_btn.attr("disabled", false); 278 } else { 279 name = ""; 280 email = ""; 281 attendee_checked.removeAttr("checked"); 282 submit_btn.attr("disabled", true); 283 } 284 285 for (let index = 0; index < total_form; index++) { 286 const element = index + 1; 287 // remove data 288 $(`#attendee-name-${element}`).val(name); 289 $(`#attendee-email-${element}`).val(email); 290 } 291 }); 292 } 293 return is_checked; 294 }, 295 296 /** 297 * Get attendee value and check validation 298 */
299 get_attendee_value() { 300 var total_form = obj.get_total_attendee(); 301 for (let index = 0; index <= total_form; index++) { 302 const attendee_name = $(`#attendee-name-${index}`); 303 const attendee_email = $(`#attendee-email-${index}`); 304 const nameError = $(`.attendee-name-error-${index}`); 305 const emailError = $(`.attendee-email-error-${index}`); 306 307 const attendee_name_value = attendee_name.val(); 308 const attendee_email_value = attendee_email.val(); 309 const isEmailValid = validEmail.test( 310 String(attendee_email_value).toLowerCase() 311 ); 312 313 if (attendee_name_value === "") { 314 attendee_name.addClass("input-error"); 315 nameError.text("Please enter attendee name."); 316 } else { 317 attendee_name.removeClass("input-error"); 318 nameError.text(""); 319 } 320 if (attendee_email_value === "" || !isEmailValid) { 321 attendee_email.addClass("input-error"); 322 emailError.text("Enter a valid email address."); 323 } else { 324 attendee_email.removeClass("input-error"); 325 emailError.text(""); 326 } 327 328 // Disable next button based on input values 329 if (attendee_name_value === "" || !isEmailValid) { 330 submitButton.setAttribute("disabled", true); 331 } else { 332 submitButton.removeAttribute("disabled"); 333 } 334 } 335 }, 336 337 /** 338 * Generate attendee form 339 * @param {*} e 340 */ 341 generate_attendee_form($this) { 342 var total_form = obj.get_total_attendee(); 343 var html = ""; 344 var name = ""; 345 var email = ""; 346 347 if (parseInt(total_form) > 0) { 348 var is_checked = true; 349 if (is_checked) { 350 name = $(`#attendee-name-0`).val(); 351 email = $(`#attendee-email-0`).val(); 352 } else { 353 name = ""; 354 email = ""; 355 } 356 // remove existing wrapper and then insert 357 $(".rsvp-attendee-wrapper").remove(); 358 for (let index = 0; index < total_form; index++) { 359 html += `<div class="rsvp-attendee-wrapper"> 360 <h2>${localized_rsvp_data?.attendee_title} - ${index + 1}</h2> 361 <div class="rsvp-form-element"> 362 <label for="attendee-name-${index + 1}">Name</label> 363 <input name="attendee_name[]" id="attendee-name-${ 364 index + 1 365 }" type="text" value='${name}' placeholder="Enter name of attendee"> 366 <div class="rsvp-error-message attendee-name-error-${index + 1}"></div> 367 </div> 368 <div class="rsvp-form-element"> 369 <label for="attendee-email-${index + 1}">Email</label> 370 <input name="attendee_email[]" id="attendee-email-${ 371 index + 1 372 }" type="email" value='${email}' placeholder="Enter email of attendee"> 373 <div class="rsvp-error-message attendee-email-error-${index + 1}"></div> 374 </div> 375 376 </div>`; 377 } 378 $this.fadeOut(); 379 $(".response-form").fadeOut(); 380 $(".rsvp-attendee-form").empty().append(html); 381 $(".rsvp-submit-btn").removeClass("etn-d-none").fadeIn(); 382 // get attendee value 383 obj.get_attendee_value(); 384 } 385 }, 386 387 /* 388 * Submit data 389 */ 390 submit_rsvp_form(e) { 391 e.preventDefault(); 392 393 // receive form data 394 var values = obj.serializeObject($(this).serializeArray()); 395 396 $.ajax({
397 method: "POST", 398 url: localized_rsvp_data?.ajax_url || "", 399 data: { action: "etn_rsvp_insert", fields: JSON.stringify(values) }, 400 beforeSend: function () { 401 rsvp_submit_btn.addClass("etn-button-loading"); 402 }, 403 success: function (response) { 404 rsvp_submit_btn.removeClass("etn-button-loading"); 405 rsvp_tab.fadeOut(); 406 rsvp_form.fadeOut(); 407 submission_message.fadeIn(); 408 }, 409 }); 410 }, 411 }; 412 413 /** 414 * Rsvp form submit from frontend 415 */ 416 rsvp_form.submit(obj.submit_rsvp_form); 417 418 /** 419 * Rsvp attendee form check un/check 420 */ 421 obj.attendee_form_generate(); 422 423 /** 424 * Generate attendee form on next click 425 */ 426 $(".rsvp-next-btn").on("click", function () { 427 obj.generate_attendee_form($(this)); 428 }); 429 430 /** 431 * On key up validation 432 */ 433 434 if ($(".rsvp-attendee-form").length > 0) { 435 $(".rsvp-attendee-form").on("keyup", function () { 436 obj.get_attendee_value(); 437 }); 438 } 439});
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.