PageSourceSearch

https://www.impactpool.org/assets/controllers/screening_question_form_controller-b46b6293.js

js impactpool.org collected 2026-10-02 04:13:26 UTC 2,866 bytes, 73 lines download raw bytes

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.