parent
01e61f9bfd
commit
baf8b18dc3
@ -1,9 +1,11 @@
|
||||
import * as toposort from 'toposort';
|
||||
|
||||
const DEBUG_MODE = /localhost/.test(window.location.href) ? 2 : 0;
|
||||
|
||||
export class UtilRegistry {
|
||||
|
||||
_registeredUtils = [];
|
||||
_activeUtilInstances = [];
|
||||
_registeredUtils = new Array();
|
||||
_activeUtilInstances = new Array();
|
||||
_appInstance;
|
||||
|
||||
/**
|
||||
@ -50,12 +52,35 @@ export class UtilRegistry {
|
||||
this._appInstance = appInstance;
|
||||
}
|
||||
|
||||
initAll(scope) {
|
||||
let startedInstances = [];
|
||||
initAll(scope = document.body) {
|
||||
let startedInstances = new Array();
|
||||
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 (DEBUG_MODE > 2) {
|
||||
console.log('starting utilInstance', { util: utilInstance.util.name, utilInstance });
|
||||
}
|
||||
|
||||
const instance = utilInstance.instance;
|
||||
if (instance && typeof instance.start === 'function') {
|
||||
instance.start.bind(instance)();
|
||||
@ -77,7 +102,7 @@ export class UtilRegistry {
|
||||
console.log('setting up util', { util });
|
||||
}
|
||||
|
||||
let instances = [];
|
||||
let instances = new Array();
|
||||
|
||||
if (util) {
|
||||
const elements = this._findUtilElements(util, scope);
|
||||
@ -140,3 +165,58 @@ export class UtilRegistry {
|
||||
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_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.
|
||||
* @param {...any} formDatas FormData objects
|
||||
@ -31,37 +34,50 @@ export class NavigateAwayPrompt {
|
||||
}
|
||||
|
||||
this._element = element;
|
||||
this._initFormData = new FormData(this._element);
|
||||
|
||||
if (this._element.classList.contains(NAVIGATE_AWAY_PROMPT_INITIALIZED_CLASS)) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 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;
|
||||
return;
|
||||
}
|
||||
|
||||
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._unloadDueToSubmit = true;
|
||||
});
|
||||
|
||||
// mark initialized
|
||||
this._element.classList.add(NAVIGATE_AWAY_PROMPT_INITIALIZED_CLASS);
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
const currentFormData = new FormData(this._element);
|
||||
let formDataHasChanged = false;
|
||||
|
||||
3
package-lock.json
generated
3
package-lock.json
generated
@ -19553,8 +19553,7 @@
|
||||
"toposort": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
|
||||
"integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=",
|
||||
"dev": true
|
||||
"integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA="
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.4.3",
|
||||
|
||||
@ -125,6 +125,7 @@
|
||||
"npm": "^6.14.5",
|
||||
"sodium-javascript": "^0.5.6",
|
||||
"tail.datetime": "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/tail.DateTime.git#master",
|
||||
"toposort": "^2.0.2",
|
||||
"whatwg-fetch": "^3.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user