From 9d49de4382d8c67e69bfcb9e2569243dd57430c5 Mon Sep 17 00:00:00 2001 From: Felix Hamann Date: Tue, 21 May 2019 21:54:32 +0200 Subject: [PATCH] add navigate away prompt js utility --- static/js/utils/form.js | 80 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/static/js/utils/form.js b/static/js/utils/form.js index e610a7c0b..3cbbbd852 100644 --- a/static/js/utils/form.js +++ b/static/js/utils/form.js @@ -247,6 +247,86 @@ setup: interactiveFieldsetUtil, }); + /** + * + * Navigate Away Prompt Utility + * This utility asks the user if (s)he really wants to navigate away + * from a page containing a form if (s)he already touched an input. + * Form-Submits will not trigger the prompt. + * Utility will ignore forms that contain auto submit elements (buttons, inputs). + * + * Attribute: [none] + * (automatically setup on all form tags that dont automatically submit, see AutoSubmitButtonUtil) + * + * Example usage: + * (any page with a form) + */ + + var NAVIGATE_AWAY_PROMPT_UTIL_NAME = 'navigateAwayPrompt'; + var NAVIGATE_AWAY_PROMPT_UTIL_SELECTOR = 'form'; + + var NAVIGATE_AWAY_PROMPT_INITIALIZED_CLASS = 'navigate-away-prompt--initialized'; + + var navigateAwayPromptUtil = function(element) { + var touched = false; + var unloadDueToSubmit = false; + + function init() { + if (!element) { + throw new Error('Navigate Away Prompt utility needs to be passed an element!'); + } + + if (element.classList.contains(NAVIGATE_AWAY_PROMPT_INITIALIZED_CLASS)) { + return false; + } + + // ignore forms that get submitted automatically + if (element.querySelector(AUTO_SUBMIT_BUTTON_UTIL_SELECTOR) || element.querySelector(AUTO_SUBMIT_INPUT_UTIL_SELECTOR)) { + return false; + } + + window.addEventListener('beforeunload', beforeUnloadHandler); + + element.addEventListener('submit', function() { + unloadDueToSubmit = true; + }); + element.addEventListener('change', function() { + touched = true; + unloadDueToSubmit = false; + }); + + // mark initialized + element.classList.add(NAVIGATE_AWAY_PROMPT_INITIALIZED_CLASS); + + return { + name: NAVIGATE_AWAY_PROMPT_UTIL_NAME, + element: element, + destroy: function() { + window.removeEventListener('beforeunload', beforeUnloadHandler); + }, + }; + } + + function beforeUnloadHandler(event) { + if (!touched || unloadDueToSubmit) { + return false; + } + + // cancel the unload event. This is the standard to force the prompt to appear. + event.preventDefault(); + // for all non standard compliant browsers we return a truthy value to activate the prompt. + return true; + } + + return init(); + }; + + formUtilities.push({ + name: NAVIGATE_AWAY_PROMPT_UTIL_NAME, + selector: NAVIGATE_AWAY_PROMPT_UTIL_SELECTOR, + setup: navigateAwayPromptUtil, + }); + /** * * Auto Submit Button Utility