163 lines
4.7 KiB
JavaScript
163 lines
4.7 KiB
JavaScript
/* jshint esnext: true */
|
|
import { APP_NAME, $document, $barba } from './utils/environment';
|
|
|
|
import globals from './globals';
|
|
|
|
import { arrayContains, removeFromArray } from './utils/array';
|
|
import { getNodeData } from './utils/html';
|
|
import { isFunction } from './utils/is';
|
|
|
|
// Basic modules
|
|
import * as modules from './modules';
|
|
|
|
const MODULE_NAME = 'App';
|
|
const EVENT_NAMESPACE = `${APP_NAME}.${MODULE_NAME}`;
|
|
|
|
export const EVENT = {
|
|
INIT_MODULES: `initModules.${EVENT_NAMESPACE}`,
|
|
INIT_SCOPED_MODULES: `initScopedModules.${EVENT_NAMESPACE}`,
|
|
DELETE_SCOPED_MODULES: `deleteScopedModules.${EVENT_NAMESPACE}`
|
|
};
|
|
|
|
class App {
|
|
constructor() {
|
|
this.modules = modules;
|
|
this.currentModules = [];
|
|
|
|
$document.on(EVENT.INIT_MODULES, (event) => {
|
|
this.initGlobals(event.firstBlood)
|
|
.deleteModules(event)
|
|
.initModules(event);
|
|
});
|
|
|
|
$document.on(EVENT.INIT_SCOPED_MODULES, (event) => {
|
|
this.initModules(event);
|
|
});
|
|
|
|
$document.on(EVENT.DELETE_SCOPED_MODULES, (event) => {
|
|
this.deleteModules(event);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Destroy all existing modules or a specific scope of modules
|
|
* @param {Object} event The event being triggered.
|
|
* @return {Object} Self (allows chaining)
|
|
*/
|
|
deleteModules(event) {
|
|
let destroyAll = true;
|
|
let moduleIds = [];
|
|
|
|
// Check for scope first
|
|
if (event.$scope instanceof jQuery && event.$scope.length > 0) {
|
|
// Modules within scope
|
|
const $modules = event.$scope.find('[data-module]');
|
|
|
|
// Determine their uids
|
|
moduleIds = $.makeArray($modules.map(function(index) {
|
|
return $modules.eq(index).data('uid');
|
|
}));
|
|
|
|
if (moduleIds.length > 0) {
|
|
destroyAll = false;
|
|
} else {
|
|
return this;
|
|
}
|
|
}
|
|
|
|
// Loop modules and destroying all of them, or specific ones
|
|
let i = this.currentModules.length;
|
|
|
|
while (i--) {
|
|
if (destroyAll || arrayContains(moduleIds, this.currentModules[i].uid)) {
|
|
removeFromArray(moduleIds, this.currentModules[i].uid);
|
|
this.currentModules[i].destroy();
|
|
this.currentModules.splice(i);
|
|
}
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Execute global functions and settings
|
|
* Allows you to initialize global modules only once if you need
|
|
* (ex.: when using Barba.js or SmoothState.js)
|
|
* @return {Object} Self (allows chaining)
|
|
*/
|
|
initGlobals(firstBlood) {
|
|
globals(firstBlood);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Find modules and initialize them
|
|
* @param {Object} event The event being triggered.
|
|
* @return {Object} Self (allows chaining)
|
|
*/
|
|
initModules(event) {
|
|
// Elements with module
|
|
let $moduleEls = [];
|
|
|
|
// If first blood, load all modules in the DOM
|
|
// If scoped, render elements with modules
|
|
// If Barba, load modules contained in Barba container
|
|
if (event.firstBlood) {
|
|
$moduleEls = $document.find('[data-module]');
|
|
} else if (event.$scope instanceof jQuery && event.$scope.length > 0) {
|
|
$moduleEls = event.$scope.find('[data-module]');
|
|
} else if (event.isBarba) {
|
|
$moduleEls = $barba.find('[data-module]');
|
|
}
|
|
|
|
// Loop through elements
|
|
let i = 0;
|
|
const elsLen = $moduleEls.length;
|
|
|
|
for (; i < elsLen; i++) {
|
|
|
|
// Current element
|
|
let el = $moduleEls[i];
|
|
|
|
// All data- attributes considered as options
|
|
let options = getNodeData(el);
|
|
|
|
// Add current DOM element and jQuery element
|
|
options.el = el;
|
|
options.$el = $moduleEls.eq(i);
|
|
|
|
// Module does exist at this point
|
|
let attr = options.module;
|
|
|
|
// Splitting modules found in the data-attribute
|
|
let moduleIdents = attr.split(/[,\s]+/g);
|
|
|
|
// Loop modules
|
|
let j = 0;
|
|
let modulesLen = moduleIdents.length;
|
|
|
|
for (; j < modulesLen; j++) {
|
|
let moduleAttr = moduleIdents[j];
|
|
|
|
if (typeof this.modules[moduleAttr] === 'function') {
|
|
let module = new this.modules[moduleAttr](options);
|
|
this.currentModules.push(module);
|
|
module.init();
|
|
}
|
|
}
|
|
}
|
|
|
|
return this;
|
|
}
|
|
}
|
|
|
|
// IIFE for loading the application
|
|
// ==========================================================================
|
|
(function() {
|
|
new App();
|
|
$document.triggerHandler({
|
|
type: EVENT.INIT_MODULES,
|
|
firstBlood: true
|
|
});
|
|
})();
|