Skip to content

Handlers

To create a new handler, you can make use of the sample handler in our _handlerFolder.

If you look at the new handlers, you will see that every handler extends our new CoreHandler, which holds all of the logic that interacts with the manager and is explained further in our Core Handler page.

Aside from that, the structure is:

We store in our constructor the configuration for our library.

Here we will store all the configuration that needs to be common for all of the instances of that library.

This configuration can be a plain object:

constructor(payload) {
super(payload);
this.init();
this.events();
this.config = {
activeClass: "--is-active",
isAnimation: true,
animationSpeed: 300,
cssEasing: "ease-in-out",
};
}

Or a callback:

constructor(payload) {
super(payload);
this.init();
this.events();
this.config = (marquee) => ({
speed: parseFloat(marquee.getAttribute("data-speed")),
controlsOnHover: marquee.getAttribute("data-controls-on-hover") === "true",
reversed: marquee.getAttribute("data-reversed"),
});
}

We use the callback when we need to access a concrete element (for instance, in the marquee example we need to access some attributes for the concrete field we are using), and a plain object when we don’t.

We can also store both common and distinct configurations, as we would need to do for sliders:

onstructor(payload) {
super(payload);
this.init();
this.events();
this.commonConfig = {
// ... common configuration
};
this.configSlider1 = (slider) => ({
config: {
...this.commonConfig,
container: slider.querySelector(".js--slider-a-primary-container"),
controlsContainer: slider.querySelector(".js--slider-a-primary-controls"),
slideBy: "1",
},
onComplete: () => {},
});
this.configSlider2 = (slider) => ({
config: {
...this.commonConfig,
container: slider.querySelector(".js--slider-a-secondary-container"),
controlsContainer: slider.querySelector(".js--slider-a-secondary-controls"),
slideBy: "3",
},
onComplete: () => {},
});
}

Here we see how we store both the configuration we need for both our sliders and then concrete configurations for each slider, where we use our callbacks again!

We will have an example handler for each of our libraries in our examples page for you to reference.

get updateTheDOM() {
return {
marqueeElements: document.querySelectorAll(`.js--marquee`),
};
}

This is a getter method to check the DOM searching for the item we need to apply the library configuration to. We can have one or several examples for this.

init() {
super.getLibraryName("InfiniteMarquee");
}

Here we need to pass our library name to our CoreHandler.js so it can import the necessary files for it to work.

It is important that this name is the same we used in our allocateInstances method in our Project.js

events() {
super.events();
this.emitter.on("MitterContentReplaced", async () => {
this.DOM = this.updateTheDOM;
this.Manager.instances["InfiniteMarquee"] = [];
super.assignInstances({
elementGroups: [
{
elements: this.DOM.marqueeElements,
config: this.config,
},
],
});
});
this.emitter.on("MitterWillReplaceContent", () => {
if (this.DOM.marqueeElements.length) {
super.destroyInstances({ libraryName: "InfiniteMarquee" });
}
});
}

In our events() method, we will be performing actions on our entry and exit from the page, using our mitt events.

The first thing we do when we enter a new page is to search for our DOM elements with our updateTheDOM method.

We also need to create an array to store our instances of the library in the Manager, and then we can call the assignInstances() method from our CoreHandler.js file to create the necessary instances.

To this method we need to pass an object with our element groups, which will be objects with our DOM elements and the configuration we stored in the constructor.

Then, when going out of the page, and this will be familiar by now, we destroy all of our instances. To do this, we first check that we have elements that have created instances and, if that is true, we can invoke our destroyInstances() method from the CoreHandler and pass it the library name that it needs to know which instances it needs to destroy and clean up.

Here, if we needed to pass an extra argument to our destroy() method, we could pass it like this:

this.emitter.on("MitterWillReplaceContent", () => {
if (this.DOM.marqueeElements.length) {
super.destroyInstances({ libraryName: "InfiniteMarquee", destroyArgs: arguments });
}
});

And that is it!

The configuration is fairly simple, and the instantiation and clean-up processes will be the same in every handler. The only thing that changes is the concrete library configuration for each one of them, which you will be able to find in the docs for each of them. You can check our internal and external pages.