Added scoped module deletion
- Ability to search through a DOM element and destroy any modules within it - Added an init() hook on AbstractModule. Used to execute any code that does not belong in a constructor (which is most of what we do)
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
/* jshint esnext: true */
|
||||
import { $document } from './utils/environment';
|
||||
import { getNodeData } from './utils/html';
|
||||
|
||||
// Global functions and tools
|
||||
import globals from './globals';
|
||||
|
||||
import { arrayContains, removeFromArray } from './utils/array';
|
||||
import { getNodeData } from './utils/html';
|
||||
import { isFunction } from './utils/is';
|
||||
|
||||
// Basic modules
|
||||
@@ -16,27 +17,52 @@ class App {
|
||||
|
||||
$document.on('initModules.App', (event) => {
|
||||
this.initGlobals(event.firstBlood)
|
||||
.deleteModules()
|
||||
.deleteModules(event)
|
||||
.initModules(event);
|
||||
});
|
||||
|
||||
$document.on('initScopedModules.App', (event) => {
|
||||
this.initModules(event);
|
||||
});
|
||||
|
||||
$document.on('deleteScopedModules.App', (event) => {
|
||||
this.deleteModules(event);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy all existing modules
|
||||
* @return {Object} this Allows chaining
|
||||
* Destroy all existing modules or a specific scope of modules
|
||||
* @param {Object} event The event being triggered.
|
||||
* @return {Object} Self (allows chaining)
|
||||
*/
|
||||
deleteModules() {
|
||||
// Loop modules
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Loop modules and destroying all of them, or specific ones
|
||||
let i = this.currentModules.length;
|
||||
|
||||
// Destroy all modules
|
||||
while (i--) {
|
||||
this.currentModules[i].destroy();
|
||||
this.currentModules.splice(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;
|
||||
@@ -46,7 +72,7 @@ class App {
|
||||
* 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} this Allows chaining
|
||||
* @return {Object} Self (allows chaining)
|
||||
*/
|
||||
initGlobals(firstBlood) {
|
||||
globals(firstBlood);
|
||||
@@ -60,34 +86,34 @@ class App {
|
||||
*/
|
||||
initModules(event) {
|
||||
// Elements with module
|
||||
let moduleEls;
|
||||
let $moduleEls = [];
|
||||
|
||||
// If first blood, load all modules in the DOM
|
||||
// If scoped, render elements with modules
|
||||
// If not, load modules contained in Barba container
|
||||
// If Barba, load modules contained in Barba container
|
||||
if (event.firstBlood) {
|
||||
moduleEls = document.querySelectorAll('[data-module]');
|
||||
} else if (typeof event.scope !== 'undefined' && isFunction(event.scope.querySelectorAll)) {
|
||||
moduleEls = event.scope.querySelectorAll('[data-module]');
|
||||
} else {
|
||||
moduleEls = document.getElementById('js-barba-wrapper').querySelectorAll('[data-module]');
|
||||
$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 = $('#js-barba-wrapper').find('[data-module]');
|
||||
}
|
||||
|
||||
// Loop through elements
|
||||
let i = 0;
|
||||
const elsLen = moduleEls.length;
|
||||
const elsLen = $moduleEls.length;
|
||||
|
||||
for (; i < elsLen; i++) {
|
||||
|
||||
// Current element
|
||||
let el = moduleEls[i];
|
||||
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 = $(el);
|
||||
options.$el = $moduleEls.eq(i);
|
||||
|
||||
// Module does exist at this point
|
||||
let attr = options.module;
|
||||
@@ -105,6 +131,7 @@ class App {
|
||||
if (typeof this.modules[moduleAttr] === 'function') {
|
||||
let module = new this.modules[moduleAttr](options);
|
||||
this.currentModules.push(module);
|
||||
module.init();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,12 @@ export default class
|
||||
|
||||
// Generate a unique module identifier
|
||||
this.uid = 'm-' + uid++;
|
||||
// Use jQuery's data API to "store it in the DOM"
|
||||
this.$el.data('uid', this.uid);
|
||||
}
|
||||
|
||||
init() {}
|
||||
|
||||
destroy()
|
||||
{
|
||||
if (this.$el) {
|
||||
|
||||
@@ -32,7 +32,7 @@ function DefaultTransition(options) {
|
||||
|
||||
$document.triggerHandler({
|
||||
type: 'initModules.App',
|
||||
firstBlood: false
|
||||
isBarba: true
|
||||
});
|
||||
|
||||
$html
|
||||
|
||||
Reference in New Issue
Block a user