Module JS
This library allows you standardize each module-like Element
throughout your single-page web application. A module can essentially be anything, but it usually represents an independent
component (like a modal, or a carousel for example).
The idea behind this library is to provide a common interface between all the modules you may want to use on your site.
Which all means less code, less work, and less things to unit test.
Installation
In order to use this package, you can use one of the pre-built files if you want to quickly get started,
without any dependencies.
Or, alternatively you can install as an npm package:
npm i module-js
Then, you can and import
or require
it, if you are using a build system like Browserify.
NOTE: Node v7 is also recommended if using this package as an NPM module.
Usage
Each module that you have on your site/app will generally be tied to an HTML/DOM element on the page, which you pass to
the Module class to create an instance. Then you'll have access to all the helpful methods below.
For our example, we'll use an element that represents our modal container (assuming there is already an element in the DOM
with the id of "modal-container").
let modalContainer = document.getElementById('modal-container');
let modalModule = new Module(modalContainer, {
styles: 'http://path/to/modal/styles.css',
template: 'http://path/to/modal/template.hbs',
data: 'http://path/to/modal/api/data',
loadedClass: 'modal-loaded'
});
Once your instance is created, you can call the built-in methods on it. For instance, calling load()
on the Modal instance (demonstrated below) will load module along with its template, styles, and even fetch the module's data using the
options we've specified above. Once loaded, it will also add the loadedClass
specified to the module's modalContainer
element.
modalInstance.load();
NOTE: since a handlebars file was used as the template
option above, calling load
will inject the data JSON response
from the `data`` url specified into the handlebars file.
Extending
Out of the box, the Module class will provide a few helpful methods. But the real power comes when you begin to have
your components extend it with their
own custom implementations. From there, you can override the default abstract methods to add logic that is custom to each
specific module. Here is an example of how to create a Modal class that extends the module class and has
custom loading functionality.
class MyCustomModule extends Module {
load () {
return super.load().then(() => {
});
}
}
As you can see above, you can overridethe load method of the parent Module class and call it whenever you want. We recommend
that you call the Module class's method via super
when overriding any of the methods to ensure you get all internal functionality.
Options
When instantiating a module, you can pass it options:
let modalContainer = document.getElementById('modal-container');
let modalModule = new Module(modalContainer, {
styles: 'http://path/to/modal/styles.css',
template: 'http://path/to/modal/template.hbs',
data: 'http://path/to/modal/api/data',
loadedClass: 'modal-loaded',
activeClass: 'modal-shown',
disabledClass: 'modal-disabled',
errorClass: 'modal-has-error'
});
Option | Type | Description |
---|
styles | Array/String | Array of stylesheet urls to be loaded (or single url string) |
template | String | HTMLElement |
data | Object/String | The url to the data or the data object that should be loaded into the module's template |
requestOptions | Object | The set of request options that will be passed to the fetch call when fetching data |
loadedClass | String | The CSS class that will be applied to the module element when it is loaded |
activeClass | String | The CSS class that will be applied to the module element when it is shown |
disabledClass | String | The CSS class that will be applied to the module element when it is disabled |
errorClass | String | The CSS class that will be applied to the module when error occurs |
onLoad | Function | A function that fires when module is loaded |
onShow | Function | A function that fires when module is shown |
onHide | Function | A function that fires when module is hidden |
onEnable | Function | A function that fires when module is enabled |
onDisable | Function | A function that fires when module is disabled |
Methods
Your module will get some useful methods whenever an instance of it is created.
load()
Your module instance will have a .load() method when it is instantiated. When called, it will load all templates, styles,
and data passed into the options above, apply your module's loadedClass
and, when done, will call
your onLoad
callback option (if specified).
You can also do some custom load handling tasks. Below you can see how a Carousel class can be created that loads
some assets asynchronously when the load() method is called.
class Carousel extends Module {
load () {
return super.load();
}
};
let carousel = new Carousel();
carousel.load();
waitForTransition()
Let's say you have the problem (that many of us have) where you need to detect the completion of your module element's
CSS transition
in javascript before your code can continue. Given the following CSS...
.animate {
transition-property: background-color;
transition-duration: 100ms;
transition-timing-function: ease-out;
}
You can call the waitForTransition
method to wait until your Module finishes its transition before doing other
things in your javascript code. Like so:
var modal = new Module(document.getElementByTagName('div')[0]);
modal.classList.add('animate');
modal.waitForTransition().then(() => {
console.log('transition complete!');
});
show()
The show() method can be called when you want to set your module to its "active" state. It adds the css
activeClass
to your Module element. If you have css that transitions your element when the activeClass
is applied,
you can utilize the returned promise to wait until after the element has transitioned.
let myModule = new Module(document.getElementById('my-module'));
myModule.show().then(function () {
})
hide()
The hide() method can be called when you want to set your module to its "inactive" state, which essentially just removes
the activeClass
. If there any css transitions that take place when the activeClass
is removed, you can use the promise
it returns to wait until the animation completes.
let myModule = new Module(document.getElementById('my-module'));
myModule.hide().then(function () {
})
fetchData()
A method that fetches the data for the Module using the API url supplied as the data
option.
let mod = new Module(document.getElementById('my-module'), {
data: 'path/to/mydata'
});
mod.fetchData().then(function (data) {
})
getStyles()
Loads the css stylesheets supplied via the styles
option.
let mod = new Module(document.getElementById('my-module'), {
styles: ['path/to/my/style.css', 'path/to/my/second/style.css']
});
mod.getStyles().then(function () {
})
getTemplate()
Loads the template supplied via the template
option.
Supports .html and Handlebars (.hbs) files.
let mod = new Module(document.getElementById('my-module'), {
template: 'path/to/template.hbs'
});
let data = {my: 'value'};
mod.getTemplate(data).then(function (html) {
this.el.textContent = html;
})
getClosestAncestorElementByClassName(cssClass, [target])
Traverses upwards from the target
until finding an ancestor element with the cssClass
provided.
The target
is optional and, if not passed, the Module instance el
is used.
disable()
The disable() method can be called to add the css disabledClass
to your Module element and set your module to a state
in which it can no longer be interacted with.
let myModule = new Module(document.getElementById('my-module'));
myModule.disable();
enable()
The enable() method does the opposite of the disable()
method above, removing the disabledClass
from your Module element.
let myModule = new Module(document.getElementById('my-module'));
myModule.enable();
error()
The error() method can be called when you want to manually trigger an error in your module, which adds the errorClass
to your Module element.
NOTE: the error() method is called automatically when the load() call on your module fails.
let myModule = new Module(document.getElementById('my-module'));
myModule.error();
Properties
loadStatus
A property that you can query in order to find out where in the loading process a module is.
This will return a string representing one of three states: notLoaded
, loading
, loaded
.
Sub-Modules
Each module instance provides a subModules
object to which you can attach additional modules that have extended the
Module class. So when load()
or destroy()
is called on the parent module, the same methods will be executed for all
of the subModules
you've specified, saving you from having to call methods on all of the subModules
directly. Take
a look at the example below.
class MyCustomModule extends Module {
constructor () {
super();
this.subModules.myModuleId = new Module();
this.subModules.myModuleId2 = new Module();
this.subModules.myModuleId3 = new Module();
}
};
let customMod = new MyCustomModule();
customMod.destroy();