Purpose:
I wanted a way to improve event clarity and event code organization. I observed that every single event flow went through the following steps:
- Trigger -> UI Change -> (Async) Action -> UI Change
Here is a JSFiddle.
Notes & Concerns
- Something about the name of the class seems bad, but I can't come up with something better.
- Are there ways to make the usage more clear to someone who didn't write the class?
- Is there a way to make it where the user doesn't have to call the
callback
function inpreAction
andaction
and not have them fire before the user's function has completed?
Class Definition: UIEvent
// PURPOSE:
// I wanted a way to improve event clarity and event code organization.
// I observed that every single event flow went through the following steps:
// Trigger -> UI Change -> (Async) Action -> UI Change
// EXAMPLES:
// Add button Click -> Disable add button -> Add new row -> Enable add button
// Save button click -> Disable save button -> Save row -> Replace row
// Edit button click -> Change button visibility -> Enable Controls -> Do Nothing.
// PARAMETERS:
// This function takes an object of settings with the following fields.
// 'eventElement':
// A function for selecting the element that will trigger the event from the container element provided to the Initialize() function.
// e.g. (container) => container.querySelector(".some-class")
// 'eventType':
// The event triggered by the element above.
// e.g. "click", "change", etc.
// 'preAction':
// A function that is fired when the event in triggered.
// Has the parameters (e, callback) where e is the eventArgs from the original event and callback is the function to be called when this function has completed.
// Remember to call the 'callback' when done or the 'action' and 'postAction' won't be called.
// 'action':
// A function that is fired after the preAction has completed.
// Has the parameters (e, callback) where e is the eventArgs from the original event and callback is the function to be called when this function has completed.
// Remember to call the 'callback' when done or the 'postAction' won't be called.
// 'postAction':
// A function that is fired after the action has completed.
// Has the parameter (e) which is the eventArgs of the original event.
// INITIALIZTION:
// The Initialize(container) function sets up the event listener on the 'eventElement' given a container.
// If no container is provided, it will default to document.
function UIEvent(settings) {
var thisUIEvent = this;
this.GetElement = (container) => settings.eventElement(container);
this.EventType = settings.eventType;
// Executed before the 'Action'.
// If you provide your own event handler you must call the 'callback' function when done.
this.PreAction = function (e) {
if (settings.preAction) {
settings.preAction(e, thisUIEvent.Action)
} else {
thisUIEvent.Action(e);
}
};
// Executed after the 'PreAction'.
// If you provide your own event handler you must call the 'callback' function when done.
this.Action = function (e) {
if (settings.action) {
settings.action(e, thisUIEvent.PostAction);
} else {
thisUIEvent.PostAction(e);
}
};
// Executed after the 'Action'.
this.PostAction = function (e) {
if (settings.postAction) {
settings.postAction(e);
}
};
// Must be called to create the event listener.
this.Initialize = (container) => {
var element = thisUIEvent.GetElement(container || document);
if (element === null) { return; }
element.addEventListener(thisUIEvent.EventType, function (e) {
thisUIEvent.PreAction(e);
});
};
}
Example Usage: Add Row Button
var AddRowEvent = new UIEvent({
eventType: "click",
eventElement: (container) => container.querySelector(".add-new-row"),
preAction: (e, callback) => {
document.querySelector(".add-new-row").setAttribute("disabled", "disabled");
if (callback) {
callback(e);
}
},
action: (e, callback) => {
var defaultOrder = { Messages: [{ Text: "This is a new row", Color: "green" }, { Text: "This is a new row", Color: "green" }], DeliveryDate: new Date().toLocaleDateString() };
var newRowHtml = Render.Once("row-template", defaultOrder);
var row = Grid.InsertRowBeforeIndex(advanceOrdersTableSelector, newRowHtml);
initializeRow(row);
toggleCanEditRow(row, true);
if (callback) {
callback(e);
}
},
postAction: (e) => {
document.querySelector(".add-new-row").removeAttribute("disabled")
}
});
AddRowEvent.Initialize(); // Same as AddRowEvent.Initialize(document) thanks to defaults.