feat(navigate-away-prompt): prompt on actual value change only

Store the initial FormData of a form and only prompt if any current value is actually different than the corresponding initial value (i.e. do not trigger prompt just by change events)
This commit is contained in:
Sarah Vaupel 2019-08-27 17:55:21 +02:00
parent 2512d69e67
commit 293ab6dc62
4 changed files with 47 additions and 16 deletions

View File

@ -4,6 +4,7 @@
],
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose": true }]
["@babel/plugin-proposal-class-properties", { "loose": true }],
["@babel/transform-runtime"]
]
}

View File

@ -2,6 +2,16 @@ 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';
/**
* Key generator from an arbitrary number of FormData objects.
* @param {...any} formDatas FormData objects
*/
function* generatorFromFormDatas(...formDatas) {
for (let formData of formDatas) {
yield* formData.keys();
}
}
const NAVIGATE_AWAY_PROMPT_INITIALIZED_CLASS = 'navigate-away-prompt--initialized';
const NAVIGATE_AWAY_PROMPT_UTIL_OPTOUT = '[uw-no-navigate-away-prompt]';
@ -12,7 +22,7 @@ export class NavigateAwayPrompt {
_element;
_touched = false;
_initFormData;
_unloadDueToSubmit = false;
constructor(element) {
@ -21,6 +31,7 @@ export class NavigateAwayPrompt {
}
this._element = element;
this._initFormData = new FormData(this._element);
if (this._element.classList.contains(NAVIGATE_AWAY_PROMPT_INITIALIZED_CLASS)) {
return false;
@ -40,10 +51,6 @@ export class NavigateAwayPrompt {
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);
@ -55,9 +62,20 @@ export class NavigateAwayPrompt {
}
_beforeUnloadHandler = (event) => {
// compare every value of the current FormData with every corresponding value of the initial FormData and set formDataHasChanged to true if there is at least one change
const currentFormData = new FormData(this._element);
var formDataHasChanged = false;
for (let key of generatorFromFormDatas(this._initFormData, currentFormData)) {
if (currentFormData.get(key) !== this._initFormData.get(key)) {
formDataHasChanged = true;
break;
}
}
// 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) {
// user (i.e. if the current FormData is equal to the initial FormData)
// or the unload event was initiated by a form submit
if (!formDataHasChanged || this._unloadDueToSubmit) {
return false;
}

26
package-lock.json generated
View File

@ -1155,6 +1155,18 @@
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-transform-runtime": {
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.5.5.tgz",
"integrity": "sha512-6Xmeidsun5rkwnGfMOp6/z9nSzWpHFNVr2Jx7kwoq4mVatQfQx5S56drBgEHF+XQbKOdIaOiMIINvp/kAwMN+w==",
"dev": true,
"requires": {
"@babel/helper-module-imports": "^7.0.0",
"@babel/helper-plugin-utils": "^7.0.0",
"resolve": "^1.8.1",
"semver": "^5.5.1"
}
},
"@babel/plugin-transform-shorthand-properties": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz",
@ -1285,19 +1297,17 @@
}
},
"@babel/runtime": {
"version": "7.4.5",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.5.tgz",
"integrity": "sha512-TuI4qpWZP6lGOGIuGWtp9sPluqYICmbk8T/1vpSysqJxRPkudh/ofFWyqdcMsDf2s7KvDL4/YHgKyvcS3g9CJQ==",
"dev": true,
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.5.5.tgz",
"integrity": "sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==",
"requires": {
"regenerator-runtime": "^0.13.2"
},
"dependencies": {
"regenerator-runtime": {
"version": "0.13.2",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz",
"integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==",
"dev": true
"version": "0.13.3",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz",
"integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw=="
}
}
},

View File

@ -53,6 +53,7 @@
"@babel/core": "^7.5.5",
"@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/plugin-proposal-decorators": "^7.4.4",
"@babel/plugin-transform-runtime": "^7.5.5",
"@babel/preset-env": "^7.5.5",
"@commitlint/cli": "^8.1.0",
"@commitlint/config-conventional": "^8.1.0",
@ -89,6 +90,7 @@
"webpack-cli": "^3.3.7"
},
"dependencies": {
"@babel/runtime": "^7.5.5",
"moment": "^2.24.0",
"npm": "^6.11.2",
"tail.datetime": "git+https://git@github.com/uni2work/tail.DateTime.git#update-view-on-select"