1import { Controller } from "@hotwired/stimulus"; 2 3// Drives the screening question modal: the option pickers write into hidden fields rather 4// than submitting, and only the options that apply to what the recruiter picked stay on 5// screen. The server clears whatever does not apply anyway, so the hiding is about not 6// asking for it, not about what gets saved. 7export default class extends Controller { 8 static targets = ["answerType", "booleanOptions", "followupAnswer", "followupQuestion", "idealAnswer", "autoReject"]; 9 10 connect() { 11 this.refresh(); 12 } 13 14 // action: "screening-question-form#choose" on each dropdown item 15 choose(event) { 16 const dropdown = event.currentTarget.closest(".ip-dropdown"); 17 18 dropdown.querySelector("input[type=hidden]").value = event.currentTarget.dataset.value; 19 20 this.syncDropdowns(); 21 this.refresh(); 22 23 // dropdown_controller closes on submit or on this event, and choosing an option does 24 // neither on its own. 25 document.dispatchEvent(new Event("closeDropdowns")); 26 } 27 28 // Puts every picker's trigger label and tick where its hidden field says they belong, so 29 // one code path covers choosing an option and resetting the form. 30 syncDropdowns() { 31 this.element.querySelectorAll(".ip-dropdown").forEach((dropdown) => { 32 const input = dropdown.querySelector("input[type=hidden]"); 33 if (!input) return; 34 35 dropdown.querySelectorAll("[data-value]").forEach((option) => { 36 const chosen = option.dataset.value === input.value; 37 const check = option.querySelector(".ip-dropdown-check"); 38 39 if (check) check.style.visibility = chosen ? "visible" : "hidden"; 40 if (chosen) dropdown.querySelector(":scope > button span").textContent = option.dataset.triggerLabel; 41 }); 42 }); 43 } 44 45 refresh() { 46 const freeText = this.answerTypeTarget.value === "free_text"; 47 48 this.booleanOptionsTargets.forEach((option) => { 49 option.hidden = freeText; 50 }); 51 52 // A hidden required field blocks submission with a message nobody can see, so the 53 // follow-up only becomes required once it is on screen and actually being asked. 54 const asksFollowup = !freeText && this.followupAnswerTarget.value !== ""; 55 56 this.followupQuestionTarget.hidden = !asksFollowup; 57 this.followupQuestionTarget.querySelector("input").required = asksFollowup; 58 59 // With no ideal answer there is nothing to reject against. The server collapses that 60 // combination on save; hiding the toggle is how the modal stops offering it. 61 this.autoRejectTarget.hidden = freeText || this.idealAnswerTarget.value === ""; 62 } 63 64 // action: "turbo:submit-end->screening-question-form#submitEnd" 65 submitEnd(event) { 66 if (!event.detail.success) return; 67 68 this.element.reset(); 69 this.syncDropdowns(); 70 this.refresh(); 71 this.element.closest("dialog").close(); 72 } 73}
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.