1import { Controller } from "@hotwired/stimulus"; 2import { Turbo } from "@hotwired/turbo-rails"; 3 4export default class extends Controller { 5 static targets = ["display", "form", "input"]; // Targets for the display, form, and input fields 6 static values = { 7 showErrors: Boolean, // Whether to show errors 8 url: String, // URL for the form 9 }; 10 11 connect() { 12 if (this.showErrorsValue) { 13 this.showEdit(); 14 } 15 this.inputTarget.addEventListener("keydown", this.handleKeydown.bind(this)); 16 } 17 18 disconnect() { 19 this.inputTarget.removeEventListener("keydown", this.handleKeydown.bind(this)); 20 } 21 22 handleKeydown(event) { 23 if (event.key === "Escape") { 24 event.preventDefault(); 25 this.hideEdit(); 26 } else if (event.key === "Enter" && !event.shiftKey) { 27 event.preventDefault(); 28 this.save(event); 29 } 30 } 31 32 showEdit() { 33 this.displayTarget.classList.add("hidden"); 34 this.formTarget.classList.remove("hidden"); 35 this.inputTarget.focus(); 36 this.inputTarget.select(); 37 } 38 39 hideEdit() { 40 this.displayTarget.classList.remove("hidden"); 41 this.formTarget.classList.add("hidden"); 42 } 43 44 save(event) { 45 event.preventDefault(); 46 47 const value = this.inputTarget.value.trim(); 48 if (!value) return; 49 50 if (this.hasUrlValue) { 51 // If URL value is provided, submit via AJAX 52 const formData = new FormData(); 53 formData.append("title", value); 54 55 fetch(this.urlValue, { 56 method: "PATCH", 57 headers: { 58 "X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').content, 59 Accept: "text/vnd.turbo-stream.html", 60 }, 61 body: formData, 62 }) 63 .then((response) => { 64 if (response.ok) { 65 return response.text(); 66 } else { 67 console.error("Failed to update"); 68 throw new Error("Update failed"); 69 } 70 }) 71 .then((html) => { 72 // Let Turbo handle the stream response 73 const parser = new DOMParser(); 74 const doc = parser.parseFromString(html, "text/html"); 75 const streamElement = doc.querySelector("turbo-stream"); 76 if (streamElement) { 77 Turbo.renderStreamMessage(html); 78 } else { 79 // Fallback to local update if no turbo stream response 80 this.updateDisplayText(value); 81 this.hideEdit(); 82 } 83 }) 84 .catch((error) => { 85 console.error("Error:", error); 86 }); 87 } else { 88 // If no URL, just update the display text locally 89 this.updateDisplayText(value); 90 this.hideEdit(); 91 } 92 } 93 94 updateDisplayText(value) { 95 const displayText = this.displayTarget.querySelector("span"); 96 if (displayText) { 97 displayText.textContent = value; 98 } 99 } 100};
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.