parent
01e61f9bfd
commit
baf8b18dc3
@ -1,9 +1,11 @@
|
|||||||
|
import * as toposort from 'toposort';
|
||||||
|
|
||||||
const DEBUG_MODE = /localhost/.test(window.location.href) ? 2 : 0;
|
const DEBUG_MODE = /localhost/.test(window.location.href) ? 2 : 0;
|
||||||
|
|
||||||
export class UtilRegistry {
|
export class UtilRegistry {
|
||||||
|
|
||||||
_registeredUtils = [];
|
_registeredUtils = new Array();
|
||||||
_activeUtilInstances = [];
|
_activeUtilInstances = new Array();
|
||||||
_appInstance;
|
_appInstance;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,12 +52,35 @@ export class UtilRegistry {
|
|||||||
this._appInstance = appInstance;
|
this._appInstance = appInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
initAll(scope) {
|
initAll(scope = document.body) {
|
||||||
let startedInstances = [];
|
let startedInstances = new Array();
|
||||||
const setupInstances = this._registeredUtils.map((util) => this.setup(util, scope)).flat();
|
const setupInstances = this._registeredUtils.map((util) => this.setup(util, scope)).flat();
|
||||||
|
|
||||||
setupInstances.forEach((utilInstance) => {
|
const orderedInstances = setupInstances.filter(_isStartOrdered);
|
||||||
|
|
||||||
|
if (DEBUG_MODE > 3) {
|
||||||
|
console.log({ setupInstances, orderedInstances });
|
||||||
|
}
|
||||||
|
|
||||||
|
const startDependencies = new Array();
|
||||||
|
for (const utilInstance of orderedInstances) {
|
||||||
|
for (const otherInstance of setupInstances) {
|
||||||
|
const startOrder = _startOrder(utilInstance, otherInstance);
|
||||||
|
if (typeof startOrder !== 'undefined')
|
||||||
|
startDependencies.push(startOrder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEBUG_MODE > 2) {
|
||||||
|
console.log('starting instances', { setupInstances, startDependencies, order: toposort.array(setupInstances, startDependencies) });
|
||||||
|
}
|
||||||
|
|
||||||
|
toposort.array(setupInstances, startDependencies).forEach((utilInstance) => {
|
||||||
if (utilInstance) {
|
if (utilInstance) {
|
||||||
|
if (DEBUG_MODE > 2) {
|
||||||
|
console.log('starting utilInstance', { util: utilInstance.util.name, utilInstance });
|
||||||
|
}
|
||||||
|
|
||||||
const instance = utilInstance.instance;
|
const instance = utilInstance.instance;
|
||||||
if (instance && typeof instance.start === 'function') {
|
if (instance && typeof instance.start === 'function') {
|
||||||
instance.start.bind(instance)();
|
instance.start.bind(instance)();
|
||||||
@ -77,7 +102,7 @@ export class UtilRegistry {
|
|||||||
console.log('setting up util', { util });
|
console.log('setting up util', { util });
|
||||||
}
|
}
|
||||||
|
|
||||||
let instances = [];
|
let instances = new Array();
|
||||||
|
|
||||||
if (util) {
|
if (util) {
|
||||||
const elements = this._findUtilElements(util, scope);
|
const elements = this._findUtilElements(util, scope);
|
||||||
@ -140,3 +165,58 @@ export class UtilRegistry {
|
|||||||
this._activeUtilInstances = this._activeUtilInstances.filter((util) => !!util);
|
this._activeUtilInstances = this._activeUtilInstances.filter((util) => !!util);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _startOrder(utilInstance, otherInstance) {
|
||||||
|
if (utilInstance.element !== otherInstance.element && !(utilInstance.element.contains(otherInstance.element) || otherInstance.element.contains(utilInstance.element)))
|
||||||
|
return undefined;
|
||||||
|
|
||||||
|
if (utilInstance === otherInstance)
|
||||||
|
return undefined;
|
||||||
|
|
||||||
|
if (!_isStartOrdered(utilInstance) || !otherInstance.instance || !otherInstance.util)
|
||||||
|
return undefined;
|
||||||
|
|
||||||
|
function orderParam(name) {
|
||||||
|
if (typeof utilInstance.instance[name] === 'function')
|
||||||
|
return !!utilInstance.instance[name](otherInstance.instance);
|
||||||
|
if (typeof utilInstance.util[name] === 'function')
|
||||||
|
return !!utilInstance.util[name](otherInstance.instance);
|
||||||
|
else if (Array.isArray(utilInstance.instance[name]))
|
||||||
|
return utilInstance.instance[name].some(constr => otherInstance.util === constr);
|
||||||
|
else if (Array.isArray(utilInstance.util[name]))
|
||||||
|
return utilInstance.util[name].some(constr => otherInstance.util === constr);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const after = orderParam('startAfter');
|
||||||
|
const before = orderParam('startBefore');
|
||||||
|
|
||||||
|
if (DEBUG_MODE > 3) {
|
||||||
|
console.log('compared instances for ordering', { utilInstance, otherInstance }, { after, before });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (after && before) {
|
||||||
|
console.error({ utilInstance, otherInstance });
|
||||||
|
throw new Error(`Incompatible start ordering: ${utilInstance.instance.constructor.name} and ${otherInstance.instance.constructor.name}`);
|
||||||
|
} else if (after)
|
||||||
|
return [otherInstance, utilInstance];
|
||||||
|
else if (before)
|
||||||
|
return [utilInstance, otherInstance];
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _isStartOrdered(utilInstance) {
|
||||||
|
if (!utilInstance || !utilInstance.instance || !utilInstance.util)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
function isOrderParam(name) {
|
||||||
|
return typeof utilInstance.instance[name] === 'function' ||
|
||||||
|
typeof utilInstance.util[name] === 'function' ||
|
||||||
|
Array.isArray(utilInstance.instance[name]) ||
|
||||||
|
Array.isArray(utilInstance.util[name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return isOrderParam('startBefore') || isOrderParam('startAfter');
|
||||||
|
}
|
||||||
|
|||||||
@ -2,6 +2,9 @@ import { Utility } from '../../core/utility';
|
|||||||
import { AUTO_SUBMIT_BUTTON_UTIL_SELECTOR } from './auto-submit-button';
|
import { AUTO_SUBMIT_BUTTON_UTIL_SELECTOR } from './auto-submit-button';
|
||||||
import { AUTO_SUBMIT_INPUT_UTIL_SELECTOR } from './auto-submit-input';
|
import { AUTO_SUBMIT_INPUT_UTIL_SELECTOR } from './auto-submit-input';
|
||||||
|
|
||||||
|
import { InteractiveFieldset } from './interactive-fieldset';
|
||||||
|
import { Datepicker } from './datepicker';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key generator from an arbitrary number of FormData objects.
|
* Key generator from an arbitrary number of FormData objects.
|
||||||
* @param {...any} formDatas FormData objects
|
* @param {...any} formDatas FormData objects
|
||||||
@ -31,37 +34,50 @@ export class NavigateAwayPrompt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._element = element;
|
this._element = element;
|
||||||
this._initFormData = new FormData(this._element);
|
|
||||||
|
|
||||||
if (this._element.classList.contains(NAVIGATE_AWAY_PROMPT_INITIALIZED_CLASS)) {
|
if (this._element.classList.contains(NAVIGATE_AWAY_PROMPT_INITIALIZED_CLASS)) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore forms that get submitted automatically
|
// ignore forms that get submitted automatically
|
||||||
if (this._element.querySelector(AUTO_SUBMIT_BUTTON_UTIL_SELECTOR) || this._element.querySelector(AUTO_SUBMIT_INPUT_UTIL_SELECTOR)) {
|
if (this._element.querySelector(AUTO_SUBMIT_BUTTON_UTIL_SELECTOR) || this._element.querySelector(AUTO_SUBMIT_INPUT_UTIL_SELECTOR)) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._element.matches(NAVIGATE_AWAY_PROMPT_UTIL_OPTOUT)) {
|
if (this._element.matches(NAVIGATE_AWAY_PROMPT_UTIL_OPTOUT)) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('beforeunload', this._beforeUnloadHandler);
|
// mark initialized
|
||||||
|
this._element.classList.add(NAVIGATE_AWAY_PROMPT_INITIALIZED_CLASS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static startAfter = [ Datepicker, InteractiveFieldset ];
|
||||||
|
|
||||||
|
start() {
|
||||||
|
if (!this._isActive())
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._initFormData = new FormData(this._element);
|
||||||
|
window.addEventListener('beforeunload', this._beforeUnloadHandler.bind(this));
|
||||||
|
|
||||||
this._element.addEventListener('submit', () => {
|
this._element.addEventListener('submit', () => {
|
||||||
this._unloadDueToSubmit = true;
|
this._unloadDueToSubmit = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// mark initialized
|
|
||||||
this._element.classList.add(NAVIGATE_AWAY_PROMPT_INITIALIZED_CLASS);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
window.removeEventListener('beforeunload', this._beforeUnloadHandler);
|
this._element.classList.remove(NAVIGATE_AWAY_PROMPT_INITIALIZED_CLASS);
|
||||||
}
|
}
|
||||||
|
|
||||||
_beforeUnloadHandler = (event) => {
|
_isActive() {
|
||||||
|
return this._element.classList.contains(NAVIGATE_AWAY_PROMPT_INITIALIZED_CLASS);
|
||||||
|
}
|
||||||
|
|
||||||
|
_beforeUnloadHandler(event) {
|
||||||
|
if (!this._isActive() || !this._initFormData)
|
||||||
|
return;
|
||||||
|
|
||||||
// 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
|
// 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);
|
const currentFormData = new FormData(this._element);
|
||||||
let formDataHasChanged = false;
|
let formDataHasChanged = false;
|
||||||
|
|||||||
3
package-lock.json
generated
3
package-lock.json
generated
@ -19553,8 +19553,7 @@
|
|||||||
"toposort": {
|
"toposort": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
|
||||||
"integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=",
|
"integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"tough-cookie": {
|
"tough-cookie": {
|
||||||
"version": "2.4.3",
|
"version": "2.4.3",
|
||||||
|
|||||||
@ -125,6 +125,7 @@
|
|||||||
"npm": "^6.14.5",
|
"npm": "^6.14.5",
|
||||||
"sodium-javascript": "^0.5.6",
|
"sodium-javascript": "^0.5.6",
|
||||||
"tail.datetime": "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/tail.DateTime.git#master",
|
"tail.datetime": "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/tail.DateTime.git#master",
|
||||||
|
"toposort": "^2.0.2",
|
||||||
"whatwg-fetch": "^3.0.0"
|
"whatwg-fetch": "^3.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user