PageSourceSearch

https://bikeindex.org/assets/controllers/org/search_column_setting…af7497d658ceedd09a13af227661dc3ab5dd4502.js

js bikeindex.org collected 2026-10-01 10:24:29 UTC 2,961 bytes, 84 lines download raw bytes

1import { Controller } from '@hotwired/stimulus'
2
3/* global localStorage */
4
5// Connects to data-controller='org--search-column-settings'
6export default class extends Controller {
7  static targets = ['checkboxes']
8  static values = { enabledColumns: Array, assignBikeSticker: Boolean }
9
10  connect () {
11    this.refreshEnabledColumns()
12    // The registrations search renders the checkboxes inside the results frame, which
13    // hasn't loaded yet - the frame's own render is what applies the stored selection there
14    if (this.hasCheckboxesTarget) this.selectStoredVisibleColumns()
15    document.addEventListener('turbo:frame-render', this.handleFrameRender)
16  }
17
18  disconnect () {
19    document.removeEventListener('turbo:frame-render', this.handleFrameRender)
20  }
21
22  // The checkboxes render inside the results frame, so a search replaces them unchecked -
23  // re-read the stored selection rather than applying what's in the DOM
24  handleFrameRender = (event) => {
25    if (!this.element.contains(event.target) || !this.hasCheckboxesTarget) return
26    this.refreshEnabledColumns()
27    this.selectStoredVisibleColumns()
28  }
29
30  refreshEnabledColumns () {
31    // Stimulus Array values return a fresh copy on each read, so mutating
32    // via push won't persist (and assign_bike_sticker_cell is ignored)
33    // build the full array, then assign it once.
34    const columns = [...this.element.querySelectorAll('th.hideableColumn')].map(th =>
35      [...th.classList].find(c => c.endsWith('_cell'))
36    ).filter(Boolean)
37
38    if (this.assignBikeStickerValue) {
39      columns.push('assign_bike_sticker_cell')
40    }
41
42    this.enabledColumnsValue = columns
43  }
44
45  // An always-visible column's checkbox is disabled, and stays checked
46  get toggleableCheckboxes () {
47    return this.checkboxesTarget.querySelectorAll('input[type=checkbox]:not(:disabled)')
48  }
49
50  selectStoredVisibleColumns () {
51    const stored = localStorage.getItem('orgRegistrationColumns')
52    let columns = null
53    if (stored) {
54      try { columns = JSON.parse(stored) } catch { localStorage.removeItem('orgRegistrationColumns') }
55    }
56
57    this.toggleableCheckboxes.forEach(cb => {
58      cb.checked = columns ? columns.includes(cb.name) : cb.dataset.default === 'true'
59    })
60    this.updateVisibleColumns()
61  }
62
63  updateVisibleColumns () {
64    const checked = []
65    this.toggleableCheckboxes.forEach(cb => {
66      if (cb.checked) checked.push(cb.name)
67    })
68    localStorage.setItem('orgRegistrationColumns', JSON.stringify(checked))
69
70    if (this.assignBikeStickerValue) {
71      checked.push('assign_bike_sticker_cell')
72    }
73
74    this.enabledColumnsValue.forEach(col => {
75      const isVisible = checked.includes(col)
76      this.element.querySelectorAll(`.${col}`).forEach(el => {
77        el.classList.toggle('tw:hidden', !isVisible)
78      })
79    })
80
81    // Re-apply first/last visible column border styles via ui-table controller
82    window.dispatchEvent(new Event('ui-table:refresh'))
83  }
84};

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.