/**
* This file is part of HARMONICARIUM, a web app which allows users to play
* the Harmonic Series dynamically by changing its fundamental tone in real-time.
* It is available in its latest version from:
* https://github.com/IndustrieCreative/Harmonicarium
*
* @license
* Copyright (C) 2017-2020 by Walter Mantovani (http://armonici.it).
* Written by Walter Mantovani.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* globals HUM */
"use strict";
/**
* The BackendUtils class<br>
* A toolset to manage the backend UI.
*/
HUM.BackendUtils = class {
/**
* @param {HUM} harmonicarium - The HUM instance to which this DHC must refer
*/
constructor(harmonicarium) {
/**
* The HUM instance
*
* @member {HUM}
*/
this.harmonicarium = harmonicarium;
/**
* UI HTML elements
*
* @member {Object}
*
* @property {Object.<string, HTMLElement>} fn - Functional UI elements
* @property {Object.<string, HTMLElement>} out - Output UI elements
*/
this.uiElements = {
fn: {
logBtn: document.getElementById("HTMLf_openLogBtn"+harmonicarium.id),
logPanel: document.getElementById("HTMLf_logPanel"+harmonicarium.id),
logTest: document.getElementById("HTMLf_logTest"+harmonicarium.id),
sidePanel: document.getElementById("HTMLf_sidePanel"+harmonicarium.id),
sidePanel_content: document.getElementById("HTMLf_sidePanel_content"+harmonicarium.id),
helpObj: document.getElementById("HTMLf_helpObj"+harmonicarium.id),
creditsObj: document.getElementById("HTMLf_creditsObj"+harmonicarium.id),
settings: document.getElementById("HTMLf_settingsObj"+harmonicarium.id),
openHelp: document.getElementById("HTMLf_openHelp"+harmonicarium.id),
openCredits: document.getElementById("HTMLf_openCredits"+harmonicarium.id),
closeSidePanel: document.getElementById("HTMLf_closeSidePanel"+harmonicarium.id),
closeBtn: false,
backBtn: false,
},
out: {
/**
* The global HTML Log element (common to all dhc instances)
*
* @type {HTMLElement}
*/
logText: document.getElementById("HTMLo_logText"+harmonicarium.id),
},
};
this._initUI();
// =======================
} // end class Constructor
// ===========================
/**
* Initialize the UI controllers
*/
_initUI() {
// LogText listeners
this.uiElements.out.logText.innerHTML = "<p>>>>>>>>> > Welcome to the Harmonicarium!</p><p>...</p><p>..</p><p>.</p>";
this.uiElements.fn.logBtn.addEventListener("click", () => this.toggleLogPanel() );
this.uiElements.fn.logTest.addEventListener("click", () => this.tester() );
// Menu Help & Credits listeners
this.uiElements.fn.openHelp.addEventListener("click", () => this.showSidebarContent("help") );
this.uiElements.fn.openCredits.addEventListener("click", () => this.showSidebarContent("credits") );
this.uiElements.fn.closeBtn = HUM.tmpl.useIcon('closeCross', this.harmonicarium.id, this.uiElements.fn.closeSidePanel, -20, 0);
this.uiElements.fn.backBtn = HUM.tmpl.useIcon('leftArrow', this.harmonicarium.id, this.uiElements.fn.closeSidePanel, 8, 0);
this.uiElements.fn.closeBtn.addEventListener("click", () => this.showSidebar() );
this.uiElements.fn.backBtn.addEventListener("click", () => this.showSidebarContent("settings") );
this.uiElements.fn.closeBtn.setAttributeNS(null, 'preserveAspectRatio', 'xMinYMin meet');
this.uiElements.fn.closeBtn.setAttributeNS(null, 'pointer-events', 'bounding-box');
this.uiElements.fn.closeBtn.setAttributeNS(null, 'width', '100%');
this.uiElements.fn.closeBtn.setAttributeNS(null, 'height', '100%');
this.uiElements.fn.backBtn.setAttributeNS(null, 'preserveAspectRatio', 'xMinYMin meet');
this.uiElements.fn.backBtn.setAttributeNS(null, 'pointer-events', 'bounding-box');
this.uiElements.fn.backBtn.setAttributeNS(null, 'width', '100%');
this.uiElements.fn.backBtn.setAttributeNS(null, 'height', '100%');
// Log PC keyboard keypress events
// Useful to avoid unwanted user inputs...
document.addEventListener('keydown', function(event) {
console.log(event.keyCode);
console.log(event.code);
});
}
/*==============================================================================*
* UI EVENTS LOG
*==============================================================================*/
/**
* Log into the HTML Log element the infos passed via the argument
*
* @param {string} str - Text string describing the event to log
*/
eventLog(str) {
let time = new Date();
let s = time.getSeconds();
let m = time.getMinutes();
let h = time.getHours();
if (h < 10) {h = "0" + h;}
if (m < 10) {m = "0" + m;}
if (s < 10) {s = "0" + s;}
this.uiElements.out.logText.innerHTML = "<p>" + h + ":" + m + ":" + s + " > " + str + "</p>" + this.uiElements.out.logText.innerHTML;
this.uiElements.out.logText.scrollTop = this.uiElements.out.logText.scrollHeight;
}
/**
* Open the Event Log panel from the bottom and toggle the open/close button
*
* @param {Object} element - HTML element of the Event Log open/close button
*/
toggleLogPanel() {
// onclick="icTESTER()"
if (this.uiElements.fn.logBtn.classList.contains("panelShown")) {
// Closed %
this.uiElements.fn.logPanel.style.height = "0%";
} else {
// Open %
this.uiElements.fn.logPanel.style.height = "35%";
}
this.uiElements.fn.logBtn.classList.toggle("panelShown");
}
/*==============================================================================*
* UI HELP/CREDITS
*==============================================================================*/
/**
* Display the desired content in the side panel
*
* @param {('settings'|'help'|'credits')} type - The content to display
*/
showSidebarContent(type) {
let help = this.uiElements.fn.helpObj,
credits = this.uiElements.fn.creditsObj,
settings = this.uiElements.fn.settings;
switch (type) {
case "help":
help.setAttribute("style", "display: block;");
credits.setAttribute("style", "display: none;");
settings.setAttribute("style", "display: none;");
this.uiElements.fn.backBtn.style.display = 'block';
this.uiElements.fn.sidePanel_content.scrollTo(0,0);
break;
case "credits":
help.setAttribute("style", "display: none;");
credits.setAttribute("style", "display: block;");
settings.setAttribute("style", "display: none;");
this.uiElements.fn.backBtn.style.display = 'block';
this.uiElements.fn.sidePanel_content.scrollTo(0,0);
break;
case "settings":
help.setAttribute("style", "display: none;");
credits.setAttribute("style", "display: none;");
settings.setAttribute("style", "display: block;");
this.uiElements.fn.backBtn.style.display = 'none';
this.uiElements.fn.sidePanel_content.scrollTo(0,0);
break;
//default:
}
}
/**
* Open the side panel
*/
// @old icHelp
showSidebar() {
let sidePanel = this.uiElements.fn.sidePanel,
dpPadPage = this.harmonicarium.html.dpPadPage;
this.showSidebarContent("settings");
if (sidePanel.classList.contains("panelShown")) {
// Close %
sidePanel.style.width = "0%";
dpPadPage.style.width = "100%";
// this.animateSidebar('close', 50, 50);
} else {
// Open %
sidePanel.style.width = "50%";
dpPadPage.style.width = '50%';
// this.animateSidebar('open', 0, 100);
}
// this.harmonicarium.windowResize();
this.harmonicarium.components.dpPad.windowResize();
sidePanel.classList.toggle("panelShown");
}
// animateSidebar(action, counter, decounter) {
// if (action === 'open') {
// if(counter < 50){
// setTimeout( () => {
// counter += 4;
// decounter -= 4;
// this.uiElements.fn.sidePanel.style.width = counter+'%';
// this.harmonicarium.html.dpPadPage.style.width = decounter+'%';
// // this.harmonicarium.components.dpPad.windowResize();
// this.harmonicarium.windowResize();
// this.animateSidebar(action, counter, decounter);
// }, 18);
// } else {
// this.uiElements.fn.sidePanel.style.width = '50%';
// this.harmonicarium.html.dpPadPage.style.width = '50%';
// // this.harmonicarium.components.dpPad.windowResize();
// this.harmonicarium.windowResize();
// }
// } else {
// if(counter < 100){
// setTimeout( () => {
// counter += 4;
// decounter -= 4;
// this.uiElements.fn.sidePanel.style.width = decounter+'%';
// this.harmonicarium.html.dpPadPage.style.width = counter+'%';
// this.harmonicarium.components.dpPad.windowResize();
// // this.harmonicarium.windowResize();
// this.animateSidebar(action, counter, decounter);
// }, 18);
// } else {
// this.uiElements.fn.sidePanel.style.width = '0%';
// this.harmonicarium.html.dpPadPage.style.width = '100%';
// this.harmonicarium.components.dpPad.windowResize();
// // this.harmonicarium.windowResize();
// }
// }
// }
/*==============================================================================*
* UI FILE READ ERROR HANDLING
*==============================================================================*/
/**
* Handle errors generated by `FileReader` when loading a file.<br>
* It is meant to be assigned to `FileReader.onerror` handler.
*
* @param {Event} errorEvent - The error event
*/
fileErrorHandler(errorEvent) {
switch (errorEvent.target.error.code) {
case errorEvent.target.error.NOT_FOUND_ERR:
alert('File Not Found!');
break;
case errorEvent.target.error.NOT_READABLE_ERR:
alert('File is not readable.');
break;
case errorEvent.target.error.ABORT_ERR:
break; // void
default:
alert('An error occurred reading this file.');
}
}
/*==============================================================================*
* TEST/DEBUG SECTION
*==============================================================================*/
/**
* Print the DHC tone tables in the console for test/debug purposes
*/
tester() {
this.eventLog("TEST: Full tables printed out. Look at the console of your browser.");
for (const [id, dhc] of Object.entries(this.harmonicarium.components.availableDHCs)) {
// this.eventLog(JSON.stringify(dhc.tables.ft, null, 2).replace(/}|{|"|,/g, ''));
console.log(`DHC ${id} 'ctrl_map' table:`, dhc.tables.ctrl);
console.log(`DHC ${id} 'ft' table:`, dhc.tables.ft);
console.log(`DHC ${id} 'ht' table:`, dhc.tables.ht);
console.log(`DHC ${id} 'reverse ft' table:`, dhc.tables.reverse.ft);
console.log(`DHC ${id} 'reverse ht' table:`, dhc.tables.reverse.ht);
}
}
};