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.