1import { Controller } from '@hotwired/stimulus'; 2import { Dialog } from 'components/dialog/component'; 3 4/** 5 * Drives the Contact Sales chrome; Rails and Turbo own the form itself. 6 * Shared across subapps: imports nothing from `app/`, `site/`, or `admin/`. 7 */ 8export default class extends Controller { 9 static targets = ['frame', 'hiwm', 'fatalTemplate', 'dialog']; 10 static values = { handleEvent: Boolean }; 11 12 /** 13 * Caches the pristine form markup and, when configured, opens on the global 14 * `openContactModal` event. 15 * 16 * @returns {void} 17 */ 18 connect () { 19 if (this.hasFrameTarget) this._pristineFrame = this.frameTarget.innerHTML; 20 21 if (this.handleEventValue) { 22 this._openListener = () => this.open(); 23 window.addEventListener('openContactModal', this._openListener); 24 } 25 } 26 27 /** 28 * Tears down the global listeners. 29 * 30 * @returns {void} 31 */ 32 disconnect () { 33 if (this._openListener) window.removeEventListener('openContactModal', this._openListener); 34 } 35 36 /** 37 * Opens the dialog with a fresh form. Embedded mode renders no dialog. 38 * 39 * @param {Event} [event] 40 * @returns {void} 41 */ 42 open (event) { 43 event?.preventDefault(); 44 if (!this.hasDialogTarget || this.dialogTarget.open) return; 45 46 this._resetForm(); 47 Dialog.for(this.dialogTarget).open(); 48 } 49 50 /** 51 * Closes the dialog. 52 * 53 * @param {Event} [event] 54 * @returns {void} 55 */ 56 close (event) { 57 event?.preventDefault(); 58 if (this.hasDialogTarget) Dialog.for(this.dialogTarget).close(); 59 } 60 61 /** 62 * Flags that a human interacted with the form, satisfying the server-side 63 * `hiwm` check. 64 * 65 * @returns {void} 66 */ 67 markHuman () { 68 this.hiwmTargets.forEach((input) => { input.value = 'yes'; }); 69 } 70 71 /** 72 * Renders the fallback panel when the frame submission fails outside 73 * validation (a network error or a 5xx with no matching frame). 74 * 75 * @param {Event} event 76 * @returns {void} 77 */ 78 frameError (event) { 79 if (!this.hasFrameTarget || !this.hasFatalTemplateTarget) return; 80 81 event.preventDefault(); 82 this.frameTarget.replaceChildren(this.fatalTemplateTarget.content.cloneNode(true)); 83 } 84 85 /** 86 * Restores the pristine form markup so every open starts fresh. Skipped when 87 * the frame is already pristine, which would needlessly unbind the form. 88 * 89 * @returns {void} 90 */ 91 _resetForm () { 92 if (this.hasFrameTarget && this._pristineFrame !== undefined && this.frameTarget.innerHTML !== this._pristineFrame) 93 this.frameTarget.innerHTML = this._pristineFrame; 94 } 95}
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.