{"version":3,"file":"form_controller-C8o5-k8o.js","sources":["../../../frontend/common/controllers/form_controller.js"],"sourcesContent":["import { Controller } from '@hotwired/stimulus'\n\n/**\n * Controller extends native form and adds some perks:\n * - Syncs input and checkboxes state that have same name\n * - `button[data-form-target=\"submit\"]` - disables button when form state isn't changed\n * - `form[data-form-lock-on-change-value]` - locks window if form changed but not saved\n * - `form[data-form-update-url-value]` - Adds form state to page query once submitted\n */\nexport default class extends Controller {\n  static targets = ['submit']\n\n  static values = {\n    lockOnChange: Boolean,\n    updateUrl: Boolean,\n    preventSubmitOnEnter: Boolean\n  }\n\n  initialState = ''\n\n  isDirty = false\n\n  get shouldLockWindow() {\n    return this.lockOnChangeValue\n  }\n\n  get shouldUpdateUrl() {\n    return this.updateUrlValue\n  }\n\n  connect() {\n    this.initialState = this.currentState\n    this.updateElements()\n\n    this.element.addEventListener('input', this.handleFormChange)\n    this.element.addEventListener('change', this.handleFormChange)\n    this.element.addEventListener('submit', this.handleFormSubmit)\n\n    if (this.shouldUpdateUrl) {\n      window.addEventListener('popstate', this.onPopStateListener)\n    }\n\n    window.addEventListener('turbo:before-fetch-response', event => {\n      const { response } = event.detail.fetchResponse\n      if (response.redirected) {\n        event.preventDefault()\n        window.location.href = response.url\n        // Turn on Turbo Visit once migrated from Videos\n        // Turbo.visit(response.url)\n      }\n    })\n\n    if (this.preventSubmitOnEnterValue) {\n      this.element.addEventListener('keydown', this.onKeyDownListener)\n    }\n  }\n\n  disconnect() {\n    this.element.removeEventListener('input', this.handleFormChange)\n    this.element.removeEventListener('change', this.handleFormChange)\n    this.element.removeEventListener('submit', this.handleFormSubmit)\n    this.element.removeEventListener('keydown', this.onKeyDownListener)\n    this.unlockWindow()\n  }\n\n  onKeyDownListener = event => {\n    if (event.key === 'Enter') {\n      event.preventDefault()\n    }\n  }\n\n  onPopStateListener = event => {\n    if (event.state.turbo_frame_history) {\n      window.Turbo.visit(document.location.href, { action: 'replace' })\n    } else {\n      window.location.replace(document.location.href)\n    }\n  }\n\n  handleFormChange = () => {\n    const isDirty = this.initialState !== this.currentState\n    const hasChanged = isDirty !== this.isDirty\n\n    if (!hasChanged) return\n\n    this.isDirty = isDirty\n\n    if (isDirty && this.shouldLockWindow) this.lockWindow()\n    else this.unlockWindow()\n\n    this.updateElements()\n  }\n\n  handleFormSubmit = () => {\n    this.unlockWindow()\n    this.isDirty = false\n    this.initialState = this.currentState\n\n    if (this.shouldUpdateUrl) {\n      window.history.pushState(\n        { turbo_frame_history: true },\n        document.title,\n        `${document.location.pathname}?${this.currentState}`\n      )\n    }\n  }\n\n  /**\n   * Sync form elements with the same `name` inside the form\n   */\n  syncElements(originElement) {\n    if (!originElement?.name) return\n\n    const isCheckbox = originElement.type === 'checkbox' || originElement.type === 'radio'\n\n    Array.from(\n      this.element.querySelectorAll(\n        `[name=\"${originElement.name}\"]${isCheckbox ? `[value=\"${originElement.value}\"]` : ''}`\n      )\n    )\n      .filter(element => element !== originElement)\n      .forEach(element => {\n        // eslint-disable-next-line no-param-reassign\n        if (isCheckbox) {\n          element.checked = originElement.checked\n          return\n        }\n\n        // eslint-disable-next-line no-param-reassign\n        element.value = originElement.value\n      })\n  }\n\n  updateElements() {\n    const buttons = [...this.submitTargets]\n\n    buttons.forEach(el => {\n      if (el.classList.contains('u-button')) {\n        // eslint-disable-next-line no-param-reassign\n        el.dataset.pending = !this.isDirty\n      } else {\n        // eslint-disable-next-line no-param-reassign\n        el.disabled = !this.isDirty\n      }\n    })\n  }\n\n  unlockWindow() {\n    window.onbeforeunload = undefined\n  }\n\n  lockWindow() {\n    window.onbeforeunload = () => ''\n  }\n\n  get currentState() {\n    const state = new FormData(this.element)\n    state.delete('utf8')\n    state.delete('authenticity_token')\n    state.delete('format')\n    return new URLSearchParams(state).toString()\n  }\n}\n"],"names":["FormController","Controller","__publicField","event","isDirty","response","originElement","isCheckbox","element","el","state"],"mappings":"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"}