minsky-kit
Version:
Kit of components for MINSKY web agency
306 lines (240 loc) • 8.5 kB
JavaScript
/* eslint no-console: "off" */
// imports
import EventDispatcher from './EventDispatcher';
import PluginManager from './PluginManager';
import MQManager from './MQManager';
import InstanceManager from './InstanceManager';
import Ticker from './Ticker';
import Config from '../Config';
import VCookieConsent from '../components/VCookieConsent';
// private static
const id = 0;
// shared tickers
const DEBOUNCE_MS = 125;
const debouncers = {
resize: initDebouncer(onWindowResizeDebounce),
delayedResize: initDebouncer(onWindowResizeDelayedDebounce),
scroll: initDebouncer(onWindowScrollDebounce),
delayedScroll: initDebouncer(onWindowScrollDelayedDebounce),
};
// class
export default class MainApp extends EventDispatcher {
// constructor
constructor(args = {}, objectName = 'Minsky App') {
args.autoInit = false;
args.debug = args.debug || false;
// call super constructor
super(args, objectName);
// set properties
this.id = id + 1;
// dev mode check
if (Config.globals.mode === 'development') document.querySelector('html').classList.add('env-dev');
// logged in state
this.loggedIn = document.body.classList.contains('page--loggedIn');
// add app shortcut to global M variable
if (!window.M) window.M = {};
if (!window.M.Apps) window.M.Apps = [];
M.Apps.push(this);
// init instances
this.mqManager = new MQManager({ debounce: Config.mqManager.debounce });
this._im = new InstanceManager(); // https://bitbucket.org/Minsky_WebAgency/minsky-kit/src/master/documentation/InstanceManager.md
// add eventlisteners
// this.mqManager.on('', this.blm.add('onMqHit', onMqHit));
this.mqManager.on('matchChanges', this.blm.add('onMqMatchChanges', onMqMatchChanges));
// add media queries
this.mqManager.add(Config.mqManager.queries);
// force-check all media queries
this.mqManager.check();
// end init
if (Config.app.showReadyMessage) MainApp.showReadyMessage();
// cookie consent
if ((!this.loggedIn || Config.vCookieConsent.loggedInUsers) && Config.vCookieConsent.active) {
this.vCookieConsent = new (args.VCookieConsent || VCookieConsent)(Config.vCookieConsent);
// make adjusting vCookieConsent config possible before initializing
this.GDPRSetup();
this.vCookieConsent.init();
// add dispatch events to certain events from vCookieConsent so you get those event trigers on all instances from the instance manager
this.vCookieConsent.on('onConsent', this.blm.add('onSetConsent', onSetConsent));
this.vCookieConsent.on('onChange', this.blm.add('onConsentChange', onConsentChange));
}
// add extra window listeners
window.addEventListener('resize', this.blm.add('onWindowResize', onWindowResize));
window.addEventListener('scroll', this.blm.add('onWindowScroll', onWindowScroll));
}
// methods
reInitialize() {
this.mqManager.resetMatches();
this.mqManager.check();
}
GDPRSetup() {
super.GDPRSetup();
}
refresh() {
// run plugins
plugins.run('refresh', {}, this);
this.log('Refresh');
}
resize() {
// run plugins
plugins.run('resize', {}, this);
this.log('resize');
}
debouncedResize() {
// run plugins
plugins.run('debouncedResize', {}, this);
this.log('debouncedResize');
}
delayedDebouncedResize() {
// run plugins
plugins.run('delayedDebouncedResize', {}, this);
this.log('delayedDebouncedResize');
}
scroll() {
// run plugins
plugins.run('scroll', {}, this);
this.log('scroll');
}
debouncedScroll() {
// run plugins
plugins.run('debouncedScroll', {}, this);
this.log('debouncedScroll');
}
delayedDebouncedScroll() {
// run plugins
plugins.run('delayedDebouncedScroll', {}, this);
this.log('delayedDebouncedScroll');
}
debug(key, value = null) {
value = value !== null ? value : !Config.logger.activate[key];
this.log('Toggle debug for ', key, 'to', value);
Config.logger.activate[key] = value;
}
destroy() {
// run plugins
plugins.run('destroy', {}, this);
// destroy all instances known to the app
// libmgr is a singleton and thus can not be destroyed
this.instances.destroy('*');
this.instances.destroy();
this.mqManager.destroy();
// call super
super.destroy();
}
// statics
static showReadyMessage() {
console.log(...Config.app.readyMessage);
}
// statics
static get plugins() {
return plugins;
}
get plugins() {
return plugins;
}
}
// utils
function mqBasedInits(definitions = []) {
this.log('Perform MQ definition based inits', definitions);
definitions.forEach((definition) => {
// get method to run
if (definition.matches) {
const key = `on${definition.name.substring(0, 1).toUpperCase()}${definition.name.substring(1)}`;
const method = this[key];
// run plugin and method
if (method) {
plugins.run(key, {}, this);
method.call(this);
}
}
});
}
function initDebouncer(listener) {
const ticker = new Ticker({
timeout: DEBOUNCE_MS,
data: {
instances: [],
},
});
ticker.on('timeout', listener);
return ticker;
}
function runDebouncer(debouncer, method, e) {
debouncer.data.instances.forEach((instance) => {
method.call(instance, e);
});
debouncer.data.length = 0;
debouncer.reset();
}
function addInstanceToDebouncer(debouncer, instance) {
if (debouncer.data.instances.indexOf(instance) === -1) {
debouncer.data.instances.push(instance);
}
}
// event handelrs
function onMqMatchChanges(e) {
mqBasedInits.call(this, e.data.definitions);
}
function onWindowScroll(e) {
// run method
this.scroll(e);
// track instances for debounced triggers
addInstanceToDebouncer(debouncers.scroll, this);
addInstanceToDebouncer(debouncers.delayedScroll, this);
// run tickers for debounced listeners
debouncers.scroll.start();
debouncers.delayedScroll.start(true);
}
function onWindowResize(e) {
// run method
this.resize(e);
// track instances for debounced triggers
addInstanceToDebouncer(debouncers.resize, this);
addInstanceToDebouncer(debouncers.delayedResize, this);
// run tickers for debounced listeners
debouncers.resize.start();
debouncers.delayedResize.start(true);
}
// pass method so that obfuscation won't generate bugs
function onWindowScrollDebounce() {
runDebouncer(this, this.data.instances[0].debouncedScroll);
}
function onWindowScrollDelayedDebounce() {
runDebouncer(this, this.data.instances[0].delayedDebouncedScroll);
}
function onWindowResizeDebounce() {
runDebouncer(this, this.data.instances[0].debouncedResize);
}
function onWindowResizeDelayedDebounce() {
runDebouncer(this, this.data.instances[0].delayedDebouncedResize);
}
function onSetConsent(e) {
this.log('consent change detected, updating all instances with new consent settings');
const { instances } = this._im;
for (const k of Object.keys(instances)) {
const instanceList = instances[k];
for (const instance of instanceList) {
// only perform action on instances with the "setConsent" method
if (instance.setConsent) instance.setConsent(e.data);
}
}
}
function onConsentChange(e) {
this.log('consent change detected, updating all instances with new consent settings');
const { instances } = this._im;
for (const k of Object.keys(instances)) {
const instanceList = instances[k];
for (const instance of instanceList) {
if (instance.consentChange) instance.consentChange(e.data);
}
}
}
export function containsOneOfTheseClasses(el, classes) {
for (const c of classes) {
if (el.classList.contains(c)) return true;
}
return false;
}
// add parent to pluginManager
let plugins = new PluginManager({
Target: MainApp,
});