PageSourceSearch

https://www.theatrefolk.com/assets/controllers/search_form_controller-a18a8dc0.js

js theatrefolk.com collected 2026-10-03 19:08:54 UTC 2,901 bytes, 74 lines download raw bytes

1import { Controller } from '@hotwired/stimulus'
2import debounce from 'debounce'
3import { pushHistory } from 'src/turbo_history'
4
5// Connects to data-controller="form"
6export default class extends Controller {
7  static targets = ['dropdown', 'loading', 'results']
8
9  connect() {
10    this.submit = debounce(this.submit.bind(this), 250)
11    this.boundPaginate = this.paginate.bind(this)
12    this.boundKeepFieldValues = this.keepFieldValues.bind(this)
13    // Pagy's links load the next page as a turbo_stream, which leaves the URL
14    // alone. The nav can sit outside the form, so listen on the document.
15    document.addEventListener('click', this.boundPaginate)
16    // Back and Forward between search URLs are Turbo restores (see
17    // src/turbo_history), from the snapshot Turbo takes when the page is left.
18    document.addEventListener('turbo:before-cache', this.boundKeepFieldValues)
19  }
20
21  disconnect() {
22    document.removeEventListener('click', this.boundPaginate)
23    document.removeEventListener('turbo:before-cache', this.boundKeepFieldValues)
24  }
25
26  // A snapshot is a clone of the DOM, and a clone carries each field's value
27  // attribute, not what was typed or ticked since. Write the live state into
28  // the attributes so a restored snapshot shows the search it has results for.
29  keepFieldValues() {
30    for (const field of this.element.elements) {
31      if (field.type === 'checkbox' || field.type === 'radio') {
32        field.toggleAttribute('checked', field.checked)
33      } else if (field instanceof HTMLInputElement && field.type !== 'password' && field.type !== 'file') {
34        field.setAttribute('value', field.value)
35      }
36    }
37  }
38
39  submit() {
40    const params = new URLSearchParams(new FormData(this.element))
41    const frame = this.element.dataset.turboFrame && document.getElementById(this.element.dataset.turboFrame)
42
43    if (frame) {
44      frame.src = `${this.element.action}?${params}`
45    } else {
46      if (this.hasLoadingTarget) {
47        this.loadingTarget.classList.remove('hidden')
48        this.resultsTarget.classList.add('hidden')
49      }
50      this.element.requestSubmit()
51    }
52
53    pushHistory(`${window.location.origin}${window.location.pathname}?${params}`)
54  }
55
56  // Record a page link's URL in history so a reload, a shared link or Back
57  // lands on that page. Turbo still fetches the stream itself.
58  paginate(event) {
59    if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return
60
61    const link = event.target.closest('nav a[data-turbo-stream][href]')
62    if (!link) return
63
64    const url = new URL(link.href, window.location.href)
65    if (url.pathname !== new URL(this.element.action, window.location.href).pathname) return
66    if (url.href === window.location.href) return
67
68    pushHistory(url.href)
69  }
70
71  resetDropdown() {
72    this.dropdownTarget.value = this.dropdownTarget.dataset.defaultId
73  }
74}

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.