Simple JavaScript micro-framework written over jQuery with event-based communication as a key feature, as well as the ability to manipulate HTML elements without overusing the $ shortcut.
Through the use of the "view" and "controller" concepts, we try to separate responsibilities, implementing strong modularity along the way, and we try to break up HTML design and JavaScript into separate and independent files. Whenever you need to code a new module, you will have to write one HTML file for the view and one JavaScript file for its corresponding controller, which from now on will be known as a Plugster.
Every Plugster can have "outlets" that will act as a link between the controller and the view, allowing us to access the DOM elements in a more elegant and clear way than to use direct jQuery selector sentences.
The following section is a little demonstration of what can be done using the library. It shows how we establish event listeners directly on the HTML view through the "data-on-" attribute, and it also shows how easily we can declare outlets to avoid using the $ shortcut on the controller.
<div class="has-text-centered"
data-controller-name="ControlCenterPlugster"
data-on-timerplugster-timerpaused="handlePauseCommand"
data-on-timerplugster-timerresumed="handleResumeCommand">
<div class="subtitle">Timer Control Center</div>
<div data-outlet-id="buttonsList" class="buttons is-centered">
<button data-outlet-id="playButton" class="button is-success">Start</button>
<button data-outlet-id="restartButton" class="button is-danger is-hidden">Stop</button>
</div>
</div>
import {Plugster}
from "https://cdn.jsdelivr.net/gh/paranoid-software/plugster@1.0.12/dist/plugster.min.js";
class ControlCenterPlugster extends Plugster {
constructor(outlets) {
super(outlets);
}
afterInit() {
let self = this;
self.currentState = 'STOPPED';
self._.playButton.on('click', {}, function() {
if (self.currentState === 'STOPPED') {
self.currentState = 'RUNNING';
self._.buttonsList.addClass('has-addons');
self._.restartButton.removeClass('is-hidden');
self._.playButton.text('Pause');
self.notifyTimerStart();
return;
}
if (self.currentState === 'PAUSED') {
self.currentState = 'RUNNING';
self._.playButton.text('Pause');
self.notifyTimerResume();
return;
}
self.currentState = 'PAUSED';
self._.playButton.text('Resume');
self.notifyTimerPause();
});
self._.restartButton.on('click', {}, function() {
self.currentState = 'STOPPED';
self._.buttonsList.removeClass('has-addons');
self._.restartButton.addClass('is-hidden');
self._.playButton.text('Start');
self.notifyTimerRestart();
});
}
handlePauseCommand() {
this.currentState = 'PAUSED';
this._.playButton.text('Resume');
}
handleResumeCommand() {
this.currentState = 'RUNNING';
this._.playButton.text('Pause');
}
notifyTimerStart() {
this.dispatchEvent(this.timerStarted.name, {})
}
timerStarted(data, callback) {
this.registerEventSignature(this.timerStarted.name, data, callback);
}
notifyTimerPause() {
this.dispatchEvent(this.timerPaused.name, {})
}
timerPaused(data, callback) {
this.registerEventSignature(this.timerPaused.name, data, callback);
}
notifyTimerResume() {
this.dispatchEvent(this.timerResumed.name, {})
}
timerResumed(data, callback) {
this.registerEventSignature(this.timerResumed.name, data, callback);
}
notifyTimerRestart() {
this.dispatchEvent(this.timerRestarted.name, {})
}
timerRestarted(data, callback) {
this.registerEventSignature(this.timerRestarted.name, data, callback);
}
}
let controlCenterPlugster = await new ControlCenterPlugster({
buttonsList: {},
playButton: {},
restartButton: {}
}).init();
Plugster.plug(controlCenterPlugster);
"Control center" widget (Plugster) to start and pause the clock timer placed just below.
<div class="has-text-centered"
data-controller-name="TimerPlugster"
data-on-controlcenterplugster-timerstarted="handleStartCommand"
data-on-controlcenterplugster-timerpaused="handlePauseCommand"
data-on-controlcenterplugster-timerresumed="handleResumeCommand"
data-on-controlcenterplugster-timerrestarted="handleRestartCommand">
<div data-outlet-id="timerLabel" class="subtitle is-clickable">0s</div>
</div>
import {Plugster}
from "https://cdn.jsdelivr.net/gh/paranoid-software/plugster@1.0.12/dist/plugster.min.js";
class TimerPlugster extends Plugster {
constructor(outlets) {
super(outlets);
}
afterInit() {
let self = this;
self.elapsedTime = 0;
self.currentState = 'STOPPED';
self._.timerLabel.on('click', {}, function() {
clearInterval(self.timer);
if (self.currentState === 'RUNNING') {
self.currentState = 'PAUSED';
self.notifyTimerPause();
return;
}
if (self.currentState === 'PAUSED') {
self.currentState = 'RUNNING';
self.resumeTimer();
self.notifyTimerResume();
return;
}
console.log('Currently stopped.');
});
}
handleStartCommand() {
this.currentState = 'RUNNING';
clearInterval(this.timer);
this.resumeTimer(true);
}
handlePauseCommand() {
this.currentState = 'PAUSED';
clearInterval(this.timer);
}
handleResumeCommand() {
this.currentState = 'RUNNING';
this.resumeTimer();
}
handleRestartCommand() {
clearInterval(this.timer);
this.currentState = 'STOPPED';
this.elapsedTime = 0;
this._.timerLabel.text(`${this.elapsedTime}s`);
}
resumeTimer(restart = false) {
let self = this;
if (restart) self.elapsedTime = 0;
self.timer = setInterval(function() {
self.elapsedTime += 1;
self._.timerLabel.text(`${self.elapsedTime}s`);
}, 1000);
}
notifyTimerPause() {
this.dispatchEvent(this.timerPaused.name, {})
}
timerPaused(data, callback) {
this.registerEventSignature(this.timerPaused.name, data, callback);
}
notifyTimerResume() {
this.dispatchEvent(this.timerResumed.name, {})
}
timerResumed(data, callback) {
this.registerEventSignature(this.timerResumed.name, data, callback);
}
}
let timerPlugster = await new TimerPlugster({
timerLabel: {}
}).init();
Plugster.plug(timerPlugster);
Timer widget controlled by the timer control center displayed above, and also by itself.