1import { Controller } from "@hotwired/stimulus" 2 3// Connects to data-controller="admin--pictures--infinite-scroll" 4export default class extends Controller { 5 static targets = ['pictureList', 'picturesEnd'] 6 static values = { picker: Boolean, default: false } 7 8 connect () { 9 // Should be a stimulus action, but issues getting it to recognize alt + arrow keys 10 this.keydownHandler = (event) => { 11 if (event.altKey && event.key == 'ArrowDown') { this.loadMore() } 12 } 13 document.addEventListener('keydown', this.keydownHandler) 14 15 let callback = (entries, _observer) => { entries.forEach((entry) => { if (entry.isIntersecting) { this.loadMore(); } }) } 16 this.observer = new IntersectionObserver(callback, { threshold: 1.0 }); 17 this.observer.observe(this.picturesEndTarget); 18 } 19 20 disconnect () { 21 document.removeEventListener('keydown', this.keydownHandler) 22 this.observer?.disconnect() 23 } 24 25 loadMore () { 26 let pagesRequestedElem = this.picturesEndTarget.querySelector('[data-pages-requested]'); 27 if (!pagesRequestedElem) { return; } 28 let nextPage = ++pagesRequestedElem.dataset.pagesRequested; 29 pagesRequestedElem.dataset.pagesRequested = nextPage; 30 let isPicker = this.pickerValue ? '&picker=true' : ''; 31 let turboFrame = this.element.closest('turbo-frame'); 32 let frameSearch = turboFrame?.src ? new URL(turboFrame.src).search : ''; 33 let searchParams = frameSearch || location.search; 34 let params = `${searchParams}&page=${nextPage}&scroll_request=true${isPicker}`.replace(/^\?/, '&') 35 fetch(`/admin/pictures/infinite_scroll?${params}`, 36 { headers: { 'Accept': 'text/vnd.turbo-stream.html' }, method: 'GET' }) 37 .then(response => response.text()) 38 .then(html => Turbo.renderStreamMessage(html)) 39 .catch((error) => { console.log(error); }) 40 } 41}
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.