Turn your checkbox into an on off switch. The focus of this demonstration is not css so you will largely be tackling that yourself as an exercise for the reader.
It changes in state from on to off and from off to on. Underlaying the visual is an optional checkbox input which responds with it.
class OnOffSwitch
{
private _isActive: boolean = false;
onActive: Function;
onInactive: Function;
element: HTMLElement;
parts: {
handle: HTMLElement,
checkbox: HTMLInputElement
};
}
Lets take a look at our class. We are storing a boolean called _isActive
we will always trust it is the current state of the switch. There are available onActive
and onInactive
functions for times that we want our switch to trigger a callback.
Our primary element is defined, a handle within it, and a checkbox. We will populate all of these things when we get to our constructor. But at this point we should take a look at what the HTML looks like.
<div class="on-off-switch">
<div class="handle"></div>
<input type="checkbox" checked>
</div>
In this case we are including the optional checkbox input, which is placed within the on-off-switch
parent and we are providing it with a checked attribute. You will probably include a name on the input and a value as well. When your form is submitted it will register just like a normal checkbox.
Importantly in your css the input should be set display: none;
. The rest of the element can look like whatever you like.
We will be setting and unsetting an is-active
classname on the primary element.
constructor (element: HTMLElement, onActive?: Function, onInactive?: Function)
{
this.element = element;
this.parts = {
handle: <HTMLElement>element.querySelector(".handle"),
checkbox: <HTMLInputElement>element.querySelector("input[type=checkbox]")
};
this.onActive = onActive;
this.onInactive = onInactive;
this.element.addEventListener("click", this._onClick.bind(this));
let isActive = !!this.element.dataset["checked"];
if (this.parts.checkbox)
isActive = this.parts.checkbox.checked;
this.toggle(isActive);
}
private _onClick ()
{
this.toggle();
}
isActive (): boolean
{
return this._isActive;
}
Here we store references to important elements. Our callbacks are registered, and we set an event listener to monitor click events.
During instantiation we try to figure out the intended initial state of the control. We check for a data-checked
attribute on element
, then override it with the value of the underlaying checkbox if one exists. By default using this scheme the checkbox would be off.
At the end of initialisation to ensure everything is appropriately set up we run the toggle
method on our class.
toggle (force: boolean = !this._isActive): boolean
{
if (this.parts.checkbox)
this.parts.checkbox.checked = force;
this._isActive = force;
this.element.classList.toggle("is-active", force);
if (force && this.onActive)
this.onActive();
if (!force && this.onInactive)
this.onInactive();
return force;
}
Our toggle
method takes an optional parameter named force
which indicates whether the switch is changing from on to off or off to on. This parameter defaults to the opposite of what it is currently. Toggle the checkbox's checked attribute based on this value.
Toggle the is-active
class on element
to update the visual aspect of the event. Check whether callbacks are defined and if so run them.
We are finished with our class! Beneath we should run some code on page loaded to instantiate our switch objects.
document.addEventListener('DOMContentLoaded', () => {
let elements = document.querySelectorAll(".on-off-switch");
for (let i = 0; i < elements.length; i++) {
new OnOffSwitch(<HTMLElement>elements.item(i));
}
});
All elements given the class name on-off-switch
will be imbued with masterful toggle switch prettiness.