1import { Controller } from '@hotwired/stimulus'; 2 3/** 4 * Apex ImageDisplay Controller 5 * 6 * Listens for imageUploadComplete events and updates the display 7 * with the newly uploaded image. 8 * 9 * Targets: 10 * - image: Element to set background-image on 11 * - container: Container to show/hide 12 */ 13export default class extends Controller { 14 15 static targets = ['image', 'container']; 16 static imageBlobPath = 'rails/active_storage/blobs'; 17 18 connect() { 19 this.boundDisplayImage = this.displayImage.bind(this); 20 document.addEventListener('imageUploadComplete', this.boundDisplayImage); 21 } 22 23 disconnect() { 24 document.removeEventListener('imageUploadComplete', this.boundDisplayImage); 25 } 26 27 displayImage(event) { 28 const filename = event.detail.filename; 29 const signedId = event.detail.signed_id; 30 const imageUrl = `/${this.constructor.imageBlobPath}/${signedId}/${filename}`; 31 32 fetch(imageUrl) 33 .then((response) => response.url) 34 .then((resolvedUrl) => { 35 if (this.hasImageTarget) { 36 this.imageTarget.setAttribute('style', `background-image: url(${resolvedUrl})`); 37 } 38 if (this.hasContainerTarget) { 39 this.containerTarget.classList.remove('d-none'); 40 // Hide the placeholder (first ELEMENT sibling). Using `firstChild` 41 // here would catch the leading text/whitespace node Slim emits 42 // between siblings and `classList.add` would throw on it, leaving 43 // the placeholder visible behind the freshly-shown container. 44 const placeholder = this.containerTarget.parentElement?.firstElementChild; 45 if (placeholder && placeholder !== this.containerTarget) { 46 placeholder.classList.add('d-none'); 47 } 48 } 49 }) 50 .catch((error) => { 51 console.error('Error fetching image:', error); 52 }); 53 } 54 55}
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.