PageSourceSearch

https://railsblocks.com/assets/controllers/autosubmit_controller-4…c4e5a5857a8cdf7e6db9c87266a1bfc006563423.js

js railsblocks.com collected 2026-09-25 20:22:48 UTC 3,151 bytes, 107 lines download raw bytes

1import { Controller } from "@hotwired/stimulus";
2export default class extends Controller {
3  static targets = ["select"];
4  static values = {
5    delay: { type: Number, default: 300 }, // Delay in ms before submitting
6  };
7
8  connect() {
9    // Handle select elements
10    this.selectTargets.forEach((select) => {
11      select.addEventListener("change", () => {
12        this.element.requestSubmit();
13      });
14    });
15
16    // Handle input events for search fields
17    this.element.querySelectorAll('input[type="search"], input[type="text"]').forEach((input) => {
18      input.addEventListener("input", (e) => this.debouncedSubmit(e));
19    });
20
21    // Restore focus immediately on connect
22    this.restoreFocusFromStorage();
23  }
24
25  disconnect() {
26    clearTimeout(this.timeout);
27  }
28
29  // Called directly from data-action="autosubmit#submit"
30  submit() {
31    this.saveFocusState();
32    this.element.requestSubmit();
33  }
34
35  debouncedSubmit(event) {
36    clearTimeout(this.timeout);
37
38    this.timeout = setTimeout(() => {
39      this.saveFocusState();
40      this.element.requestSubmit();
41    }, this.delayValue);
42  }
43
44  saveFocusState() {
45    const activeElement = document.activeElement;
46    if (activeElement && this.element.contains(activeElement) && activeElement.name) {
47      // Store focus data in sessionStorage so it survives controller reconnection
48      const focusData = {
49        inputName: activeElement.name,
50        timestamp: Date.now(),
51      };
52      sessionStorage.setItem("autosubmit_focus_restore", JSON.stringify(focusData));
53    }
54  }
55
56  restoreFocusFromStorage() {
57    const stored = sessionStorage.getItem("autosubmit_focus_restore");
58    if (!stored) return;
59
60    try {
61      const focusData = JSON.parse(stored);
62      // Only restore if it was saved recently (within 3 seconds)
63      if (Date.now() - focusData.timestamp > 3000) {
64        sessionStorage.removeItem("autosubmit_focus_restore");
65        return;
66      }
67
68      // Find the input by name
69      const input = this.element.querySelector(`[name="${focusData.inputName}"]`);
70      if (input) {
71        // Clear the stored data first to prevent re-triggering
72        sessionStorage.removeItem("autosubmit_focus_restore");
73
74        // Focus immediately
75        input.focus();
76
77        // Move cursor to end of input value
78        if (input.type === "text" || input.type === "search") {
79          try {
80            const valueLength = input.value.length;
81            input.setSelectionRange(valueLength, valueLength);
82          } catch (e) {
83            // Some inputs don't support setSelectionRange
84          }
85        }
86      }
87    } catch (e) {
88      sessionStorage.removeItem("autosubmit_focus_restore");
89    }
90  }
91}
92
93/**
94 * Autosubmit Controller
95 *
96 * Automatically submits a form when inputs change, with debouncing for text inputs.
97 * Maintains focus on the active input after Turbo replaces the content.
98 *
99 * Usage:
100 *   <form data-controller="autosubmit"
101 *         data-autosubmit-delay-value="300"
102 *         data-turbo-frame="my-frame">
103 *
104 *     <select data-autosubmit-target="select">...</select>
105 *     <input type="text" name="search">
106 *   </form>
107 */;

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.