import { Utility } from "../../core/utility"; import { AUTO_SUBMIT_BUTTON_UTIL_SELECTOR } from "./auto-submit-button"; import { AUTO_SUBMIT_INPUT_UTIL_SELECTOR } from "./auto-submit-input"; const NAVIGATE_AWAY_PROMPT_INITIALIZED_CLASS = 'navigate-away-prompt--initialized'; @Utility({ selector: 'form', }) export class NavigateAwayPrompt { _element; _touched = false; _unloadDueToSubmit = false; constructor(element) { if (!element) { throw new Error('Navigate Away Prompt utility needs to be passed an element!'); } this._element = element; if (this._element.classList.contains(NAVIGATE_AWAY_PROMPT_INITIALIZED_CLASS)) { return false; } // ignore forms that get submitted automatically if (this._element.querySelector(AUTO_SUBMIT_BUTTON_UTIL_SELECTOR) || this._element.querySelector(AUTO_SUBMIT_INPUT_UTIL_SELECTOR)) { return false; } window.addEventListener('beforeunload', this._beforeUnloadHandler); this._element.addEventListener('submit', () => { this._unloadDueToSubmit = true; }); this._element.addEventListener('change', () => { this._touched = true; this._unloadDueToSubmit = false; }); // mark initialized this._element.classList.add(NAVIGATE_AWAY_PROMPT_INITIALIZED_CLASS); } destroy() { window.removeEventListener('beforeunload', this._beforeUnloadHandler); } _beforeUnloadHandler = (event) => { // allow the event to happen if the form was not touched by the // user or the unload event was initiated by a form submit if (!this._touched || this._unloadDueToSubmit) { return false; } // cancel the unload event. This is the standard to force the prompt to appear. event.preventDefault(); // chrome event.returnValue = true; // for all non standard compliant browsers we return a truthy value to activate the prompt. return true; } }