This repository has been archived on 2022-09-16. You can view files and clone it, but cannot push or open issues/pull-requests.
tlaternet-templates/src/music/player/controls.js

196 lines
4.8 KiB
JavaScript

import $ from "jquery";
/**
* _Text()
*
* A helper class to control the text area for audio controls.
*
* @private
* @param {HTMLElement} div - The div of the text area.
*/
class _Text {
constructor(div) {
this._element = div;
this._text = "";
this._flashing = false;
this._flash_timeout = null;
}
flashText(text) {
let element = this._element;
let flash_timeout = this._flash_timeout;
element.html(text);
this._flashing = true;
clearTimeout(flash_timeout);
this._flash_timeout = setTimeout(() => {
this._flashing = false;
}, 1000);
}
setText(text) {
let element = this._element;
let flashing = this._flashing;
if (!flashing) {
element.html(text);
}
this._text = text;
}
}
/**
* _Button()
*
* A helper class to control the indicator button for audio controls.
*
* @private
* @param {HTMLElement} button - The div of the button.
*/
class _Button {
constructor(button) {
this._element = button;
this._classes = "";
this._flash_classes = "";
this._flashing = false;
this._flash_timeout = null;
}
click(callback) {
this._element.click(callback);
}
flashIcon(icon) {
let classes = this._classes;
let element = this._element;
let flash_classes = this._flash_classes;
let flash_timeout = this._flash_timeout;
// We remove any potentially current classes, and add the
// requested icon class.
element.removeClass(flash_classes);
element.removeClass(classes);
element.addClass(icon);
// We keep track of the classes we are flashing and the fact
// that we are flashing, so that we can remove the correct
// classes later.
this._flash_classes = icon;
this._flashing = true;
// If we previously started a timeout, we'll want to cancel it
// now, since otherwise *it* will clear out our classes.
clearTimeout(flash_timeout);
// We start a timeout to reset to the original classes.
this._flash_timeout = setTimeout(() => {
element.removeClass(this._flash_classes);
element.addClass(this._classes);
this._flash_classes = "";
this._flashing = false;
}, 1000);
}
setIcon(icon) {
let classes = this._classes;
let element = this._element;
let flashing = this._flashing;
// If we are currently flashing an icon, we'll hold off on
// changing the icon.
if (!flashing) {
element.removeClass(classes);
element.addClass(icon);
}
this._classes = icon;
}
}
/**
* Controls()
*
* A class to manage music player controls.
*
* @param {AudioManager} audioManager - The audio manager to interact with.
*/
class Controls {
constructor(audioManager) {
this._element = $("#playerControls");
this._button = new _Button($("#playerControls #playerButton"));
this._text = new _Text($("#playerControls #playerText"));
this._audioManager = audioManager;
this._setAudioEvents({
canplay: () => this._audioManager.audio.play(),
error: () => this.setError(this._audioManager.audio.error.message),
loadstart: () => this.setLoading(),
playing: () => this.setPlaying(),
stalled: () => this.setLoading("Stalling")
});
this._button.click(() => this.mute());
}
setPlaying() {
let button = this._button;
let text = this._text;
button.setIcon("fa-play");
text.setText("");
}
setLoading(reason = "Loading") {
let button = this._button;
let text = this._text;
button.setIcon("fa-spin fa-spinner");
text.setText(reason);
}
setError(reason = "") {
let button = this._button;
let text = this._text;
if (reason == "") {
reason = "Error";
} else {
reason = `Error: ${reason}`;
}
button.setIcon("fa-stop-circle");
text.setText(reason);
}
mute() {
let audioManager = this._audioManager;
let button = this._button;
let text = this._text;
audioManager.mute();
if (audioManager.muted) {
button.flashIcon("fa-volume-off");
text.flashText("Muted");
} else {
button.flashIcon("fa-volume-up");
text.flashText("Unmuted");
}
}
_setAudioEvents(events) {
for (let [event, handler] of Object.entries(events)) {
this._audioManager.addEventListener(event, handler);
}
}
}
export default Controls;