diff --git a/js/blocks/WidgetBlocks.js b/js/blocks/WidgetBlocks.js index a1673ba059..3b0db17dbc 100644 --- a/js/blocks/WidgetBlocks.js +++ b/js/blocks/WidgetBlocks.js @@ -1,3 +1,54 @@ +/* + global FlowBlock, _, last, DEFAULTFILTERTYPE, FILTERTYPES, instrumentsFilters, StackClampBlock, + DEFAULTMODE, TemperamentWidget, TimbreWidget, DEFAULTVOICE, NOINPUTERRORMSG, instrumentsEffects, + MeterWidget, Oscilloscope, turtles, ModeWidget, Tempo, PitchDrumMatrix, PitchSlider, + beginnerMode, MusicKeyboard, PitchStaircase, RhythmRuler, PhraseMaker, StatusMatrix + */ + +/* + Global locations + js/protoblocks.js + FlowBlock, StackClampBlock + js/utils/utils.js + _, last + js/utils/musicutils.js + DEFAULTFILTERTYPE, FILTERTYPES, DEFAULTMODE, DEFAULTVOICE + js/utils/synthutils.js + instrumentsFilters, instrumentsEffects + js/logo.js + NOINPUTERRORMSG + js/activity.js + turtles, beginnerMode + js/widgets/temperament.js + TemperamentWidget + js/widgets/timbre.js + TimbreWidget + js/widgets/meterwidget.js + MeterWidget + js/widgets/oscilloscope.js + Oscilloscope + js/widgets/modewidget.js + ModeWidget + js/widgets/tempo.js + Tempo + js/widgets/pitchdrummatrix.js + PitchDrumMatrix + js/widgets/pitchslider.js + PitchSlider + js/widgets/musickeyboard.js + MusicKeyboard + js/widgets/pitchstaircase.js + PitchStairCase + js/widgets/rhythmruler.js + RhythmRuler + js/widgets/phrasemaker.js + PhraseMaker + js/widgets/status.js + StatusMatrix + */ + +/* exported setupWidgetBlocks */ + function setupWidgetBlocks() { class EnvelopeBlock extends FlowBlock { constructor() { @@ -209,7 +260,7 @@ function setupWidgetBlocks() { const listenerName = "_temperament_" + turtle; logo.setDispatchBlock(blk, turtle, listenerName); - const __listener = function(event) { + const __listener = () => { logo.temperament.init(); }; @@ -325,7 +376,7 @@ function setupWidgetBlocks() { const listenerName = "_timbre_" + turtle; logo.setDispatchBlock(blk, turtle, listenerName); - const __listener = function(event) { + const __listener = () => { logo.timbre.init(); }; @@ -366,7 +417,7 @@ function setupWidgetBlocks() { const listenerName = "_meterwidget_" + turtle; logo.setDispatchBlock(blk, turtle, listenerName); - const __listener = function(event) { + const __listener = () => { logo.meterWidget = new MeterWidget(blk); logo.insideMeterWidget = false; @@ -419,7 +470,7 @@ function setupWidgetBlocks() { const listenerName = "_oscilloscope_" + turtle; logo.setDispatchBlock(blk, turtle, listenerName); - const __listener = function(event) { + const __listener = () => { logo.Oscilloscope = new Oscilloscope(logo); logo.inOscilloscope = false; }; @@ -461,7 +512,7 @@ function setupWidgetBlocks() { const listenerName = "_modewidget_" + turtle; logo.setDispatchBlock(blk, turtle, listenerName); - const __listener = function(event) { + const __listener = () => { logo.modeWidget = new ModeWidget(); logo.insideModeWidget = false; }; @@ -499,7 +550,7 @@ function setupWidgetBlocks() { ]); } - flow(args, logo, turtle, blk, receivedArg, actionArgs, isflow) { + flow(args, logo, turtle, blk) { if (logo.tempo === null) { logo.tempo = new Tempo(); } @@ -511,7 +562,7 @@ function setupWidgetBlocks() { const listenerName = "_tempo_" + turtle; logo.setDispatchBlock(blk, turtle, listenerName); - const __listener = function(event) { + const __listener = () => { logo.tempo.init(); }; @@ -569,7 +620,7 @@ function setupWidgetBlocks() { const listenerName = "_pitchdrummatrix_" + turtle; logo.setDispatchBlock(blk, turtle, listenerName); - const __listener = function(event) { + const __listener = () => { if ( logo.pitchDrumMatrix.drums.length === 0 || logo.pitchDrumMatrix.rowLabels.length === 0 @@ -626,7 +677,7 @@ function setupWidgetBlocks() { const listenerName = "_pitchslider_" + turtle; logo.setDispatchBlock(blk, turtle, listenerName); - const __listener = function(event) { + const __listener = () => { logo.pitchSlider.init(logo); logo.inPitchSlider = false; }; @@ -670,7 +721,8 @@ function setupWidgetBlocks() { if (this.lang !== "ja") this.hidden = true; } - flow(args, logo, turtle, blk, receivedArg, actionArgs, isflow) {} + flow() {} + // flow(args, logo, turtle, blk, receivedArg, actionArgs, isflow) {} } class MusicKeyboard2Block extends StackClampBlock { @@ -758,8 +810,8 @@ function setupWidgetBlocks() { const listenerName = "_musickeyboard_" + turtle; logo.setDispatchBlock(blk, turtle, listenerName); - const __listener = function(event) { - logo.musicKeyboard.init(logo); + const __listener = () => { + logo.musicKeyboard.init(); }; logo.setTurtleListener(turtle, listenerName, __listener); @@ -807,7 +859,7 @@ function setupWidgetBlocks() { const listenerName = "_pitchstaircase_" + turtle; logo.setDispatchBlock(blk, turtle, listenerName); - const __listener = function(event) { + const __listener = () => { logo.pitchStaircase.init(logo); logo.inPitchStaircase = false; }; @@ -894,7 +946,7 @@ function setupWidgetBlocks() { const listenerName = "_rhythmruler_" + turtle; logo.setDispatchBlock(blk, turtle, listenerName); - const __listener = function(event) { + const __listener = () => { logo.rhythmRuler.init(); }; @@ -1037,7 +1089,7 @@ function setupWidgetBlocks() { const listenerName = "_matrix_" + turtle; logo.setDispatchBlock(blk, turtle, listenerName); - const __listener = function(event) { + const __listener = () => { if ( logo.tupletRhythms.length === 0 || logo.phraseMaker.rowLabels.length === 0 @@ -1143,7 +1195,7 @@ function setupWidgetBlocks() { const listenerName = "_status_" + turtle; logo.setDispatchBlock(blk, turtle, listenerName); - const __listener = function(event) { + const __listener = () => { logo.statusMatrix.init(logo); logo.inStatusMatrix = false; }; diff --git a/js/widgets/musickeyboard.js b/js/widgets/musickeyboard.js index 66f3011b48..54600b0178 100644 --- a/js/widgets/musickeyboard.js +++ b/js/widgets/musickeyboard.js @@ -1,61 +1,254 @@ -// Copyright (c) 2015 Jefferson Lee -// Copyright (c) 2018 Ritwik Abhishek -// Copyright (c) 2018,20 Walter Bender -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the 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. -// -// You should have received a copy of the GNU Affero General Public -// License along with this library; if not, write to the Free Software -// Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA - -function MusicKeyboard() { - const FAKEBLOCKNUMBER = 100000; - const BUTTONDIVWIDTH = 535; // 5 buttons - const OUTERWINDOWWIDTH = 758; - const INNERWINDOWWIDTH = 50; - const BUTTONSIZE = 53; - const ICONSIZE = 32; +/** + * @file This contains the prototype of the MusicKeyboard Widget. + * + * @copyright 2015 Jefferson Lee + * @copyright 2018 Ritwik Abhishek + * @copyright 2018,20 Walter Bender + * + * @license + * This program is free software; you can redistribute it and/or modify it under the terms of the + * 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. + * + * You should have received a copy of the GNU Affero General Public License along with this + * library; if not, write to the Free Software Foundation, 51 Franklin Street, Suite 500 Boston, + * MA 02110-1335 USA. + */ + +/* + global platformColor, docById, wheelnav, slicePath, logo, Singer, last, _, FIXEDSOLFEGE1 + SHARP, FLAT, noteToFrequency, EIGHTHNOTEWIDTH, MATRIXSOLFEHEIGHT, MATRIXSOLFEWIDTH, + i18nSolfege, toFraction, blocks, getNote, PREVIEWVOLUME, DEFAULTVOICE, PITCHES3, + SOLFEGENAMES, PITCHES2, PITCHES, NOTESSHARP, NOTESFLAT, convertFromSolfege, SOLFEGECONVERSIONTABLE + + + */ + +/* exported MusicKeyboard */ + +/** + * @class + * @classdesc pertains to setting up all features of the musickeyboard widget and its UI features. + * + * Private members' names begin with underscore '_". + */ +class MusicKeyboard { + static FAKEBLOCKNUMBER = 100000; + static BUTTONDIVWIDTH = 535; // 5 buttons + static OUTERWINDOWWIDTH = 758; + static INNERWINDOWWIDTH = 50; + static BUTTONSIZE = 53; + static ICONSIZE = 32; // Mapping between keycodes and virtual keyboard - const BLACKKEYS = [87, 69, 82, 84, 89, 85, 73, 79]; - const WHITEKEYS = [65, 83, 68, 70, 71, 72, 74, 75, 76]; - const SPACE = 32; + static BLACKKEYS = [87, 69, 82, 84, 89, 85, 73, 79]; + static WHITEKEYS = [65, 83, 68, 70, 71, 72, 74, 75, 76]; + static SPACE = 32; - const saveOnKeyDown = document.onkeydown; - const saveOnKeyUp = document.onkeyup; + static saveOnKeyDown = document.onkeydown; + static saveOnKeyUp = document.onkeyup; + static beginnerMode = localStorage.beginnerMode; + static unit = MusicKeyboard.beginnerMode === "true" ? 8 : 16; + static selectedNotes = []; - const w = window.innerWidth; - this._cellScale = w / 1200; + /** + * @constructor + */ + + constructor() { + const w = window.innerWidth; + this._cellScale = w / 1200; + + this._stopOrCloseClicked = false; + this.playingNow = false; + + this.instruments = []; + this.noteNames = []; + this.octaves = []; + this.keyboardShown = true; + this.layout = []; + this.idContainer = []; + this.tick = false; + this.meterArgs = [4, 1 / 4]; + + // Map between keyboard element ids and the note associated with the key. + this.noteMapper = {}; + this.blockNumberMapper = {}; + this.instrumentMapper = {}; + + this._rowBlocks = []; + + // Each element in the array is [start time, note, id, duration, voice]. + this._notesPlayed = []; + } + + /** + * Initialises the MusicKeyboard widget. + * @returns {void} + */ + + init() { + this.tick = false; + this.playingNow = false; + let w = window.innerWidth; + this._cellScale = w / 1200; + + const widgetWindow = window.widgetWindows.windowFor(this, "music keyboard"); + this.widgetWindow = widgetWindow; + widgetWindow.clear(); + widgetWindow.show(); + this._keysLayout(); + const tur = logo.turtles.ithTurtle(0); + this.bpm = tur.singer.bpm.length > 0 ? last(tur.singer.bpm) : Singer.masterBPM; + + widgetWindow.onclose = () => { + let myNode; + document.onkeydown = MusicKeyboard.saveOnKeyDown; + document.onkeyup = MusicKeyboard.saveOnKeyUp; + + if (document.getElementById("keyboardHolder2")) { + document.getElementById("keyboardHolder2").style.display = "none"; + } + + myNode = document.getElementById("myrow"); + if (myNode != null) { + myNode.innerHTML = ""; + } + + myNode = document.getElementById("myrow2"); + if (myNode != null) { + myNode.innerHTML = ""; + } + + MusicKeyboard.selectedNotes = []; + if (this.loopTick) this.loopTick.stop(); + widgetWindow.destroy(); + }; + + this.playButton = widgetWindow.addButton( + "play-button.svg", + MusicKeyboard.ICONSIZE, + _("Play") + ); + + this.playButton.onclick = () => { + logo.turtleDelay = 0; + this.processSelected(); + this.playAll(); + }; + + widgetWindow.addButton( + "export-chunk.svg", + MusicKeyboard.ICONSIZE, + _("Save") + ).onclick = () => { + this._save(); + }; + + widgetWindow.addButton( + "erase-button.svg", + MusicKeyboard.ICONSIZE, + _("Clear") + ).onclick = () => { + this._notesPlayed = []; + MusicKeyboard.selectedNotes = []; + // if (!that.keyboardShown) { + this._createTable(); + // } + }; + + widgetWindow.addButton("add2.svg", MusicKeyboard.ICONSIZE, _("Add note")).onclick = () => { + this._createAddRowPieSubmenu(); + }; + + this.midiButton = widgetWindow.addButton("midi.svg", MusicKeyboard.ICONSIZE, _("MIDI")); + this.midiButton.onclick = () => { + this.doMIDI(); + }; + + this.tickButton = widgetWindow.addButton( + "metronome.svg", + MusicKeyboard.ICONSIZE, + _("Metronome") + ); + this.tickButton.onclick = () => { + if (this.tick) { + this.tick = false; + this.loopTick.stop(); + } else { + this.tick = true; + logo.synth.loadSynth(0, "cow bell"); + this.loopTick = logo.synth.loop( + 0, + "cow bell", + "C5", + 1 / 64, + 0, + this.bpm || 90, + 0.07 + ); + setTimeout(() => { + logo.synth.start(); + }, 500); + } + }; + + // Append keyboard and div on widget windows + this.keyboardDiv = document.createElement("div"); + const attr = document.createAttribute("id"); + attr.value = "mkbKeyboardDiv"; + this.keyboardDiv.setAttributeNode(attr); + this.keyTable = document.createElement("div"); + widgetWindow.getWidgetBody().append(this.keyboardDiv); + widgetWindow.getWidgetBody().append(this.keyTable); + widgetWindow.getWidgetBody().style.height = "550px"; + widgetWindow.getWidgetBody().style.width = "1000px"; - const beginnerMode = localStorage.beginnerMode; + this._createKeyboard(); - const unit = beginnerMode === "true" ? 8 : 16; - this._stopOrCloseClicked = false; - this.playingNow = false; + this._createTable(); - this.instruments = []; - this.noteNames = []; - this.octaves = []; - this.keyboardShown = true; - this.layout = []; - this.idContainer = []; - this.tick = false; - this.meterArgs = [4, 1 / 4]; + w = Math.max( + Math.min(window.innerWidth, this._cellScale * MusicKeyboard.OUTERWINDOWWIDTH - 20), + MusicKeyboard.BUTTONDIVWIDTH + ); - // Map between keyboard element ids and the note associated with the key. - this.noteMapper = {}; - this.blockNumberMapper = {}; - this.instrumentMapper = {}; - let selectedNotes = []; + //Change widget size on fullscreen mode, else + //revert back to original size on unfullscreen mode + widgetWindow.onmaximize = () => { + if (widgetWindow._maximized) { + widgetWindow.getWidgetBody().style.position = "absolute"; + widgetWindow.getWidgetBody().style.height = "calc(100vh - 64px)"; + widgetWindow.getWidgetBody().style.width = "200vh"; + docById("mkbOuterDiv").style.width = "calc(200vh - 64px)"; + docById("keyboardHolder2").style.width = "calc(200vh - 64px)"; + try { + docById("mkbInnerDiv").style.width = "calc(200vh - 64px)"; + } catch (e) { + // Does this happen? + // console.debug("Error calculating InnerDiv width"); + } + + widgetWindow.getWidgetBody().style.left = "70px"; + } else { + widgetWindow.getWidgetBody().style.position = "relative"; + widgetWindow.getWidgetBody().style.left = "0px"; + widgetWindow.getWidgetBody().style.height = "550px"; + widgetWindow.getWidgetBody().style.width = "1000px"; + docById("mkbOuterDiv").style.width = w + "px"; + } + }; + + widgetWindow.sendToCenter(); + } - this._rowBlocks = []; + /** + * @public + * @param {number} rowBlock + * @returns {void} + */ - // Each element in the array is [start time, note, id, duration, voice]. - this._notesPlayed = []; - this.addRowBlock = (rowBlock) => { + addRowBlock(rowBlock) { // In case there is a repeat block, use a unique block number // for each instance. while (this._rowBlocks.indexOf(rowBlock) !== -1) { @@ -63,11 +256,15 @@ function MusicKeyboard() { } this._rowBlocks.push(rowBlock); - }; + } - this.processSelected = () => { + /** + * @public + * @returns {void} + */ + processSelected() { if (this._notesPlayed.length === 0) { - selectedNotes = []; + MusicKeyboard.selectedNotes = []; return; } @@ -79,7 +276,7 @@ function MusicKeyboard() { // selectedNotes is used for playback. Coincident notes are // grouped together. It is built from notesPlayed. - selectedNotes = [ + MusicKeyboard.selectedNotes = [ { noteOctave: [this._notesPlayed[0].noteOctave], objId: [this._notesPlayed[0].objId], @@ -96,17 +293,17 @@ function MusicKeyboard() { i < this._notesPlayed.length && this._notesPlayed[i].startTime === this._notesPlayed[i - 1].startTime ) { - selectedNotes[j].noteOctave.push(this._notesPlayed[i].noteOctave); - selectedNotes[j].objId.push(this._notesPlayed[i].objId); - selectedNotes[j].duration.push(this._notesPlayed[i].duration); - selectedNotes[j].voice.push(this._notesPlayed[i].voice); - selectedNotes[j].blockNumber.push(this._notesPlayed[i].blockNumber); + MusicKeyboard.selectedNotes[j].noteOctave.push(this._notesPlayed[i].noteOctave); + MusicKeyboard.selectedNotes[j].objId.push(this._notesPlayed[i].objId); + MusicKeyboard.selectedNotes[j].duration.push(this._notesPlayed[i].duration); + MusicKeyboard.selectedNotes[j].voice.push(this._notesPlayed[i].voice); + MusicKeyboard.selectedNotes[j].blockNumber.push(this._notesPlayed[i].blockNumber); i++; } j++; if (i < this._notesPlayed.length) { - selectedNotes.push({ + MusicKeyboard.selectedNotes.push({ noteOctave: [this._notesPlayed[i].noteOctave], objId: [this._notesPlayed[i].objId], duration: [this._notesPlayed[i].duration], @@ -116,10 +313,14 @@ function MusicKeyboard() { }); } } - }; + } + + /** + * @public + * @returns {void} + */ - this.addKeyboardShortcuts = function () { - // ; + addKeyboardShortcuts() { let duration = 0; const startTime = {}; const temp1 = {}; @@ -127,20 +328,20 @@ function MusicKeyboard() { const current = new Set(); const __startNote = (event) => { - let i, id, ele; - if (WHITEKEYS.indexOf(event.keyCode) !== -1) { - i = WHITEKEYS.indexOf(event.keyCode); + let i, id; + if (MusicKeyboard.WHITEKEYS.indexOf(event.keyCode) !== -1) { + i = MusicKeyboard.WHITEKEYS.indexOf(event.keyCode); id = "whiteRow" + i.toString(); - } else if (BLACKKEYS.indexOf(event.keyCode) !== -1) { - i = BLACKKEYS.indexOf(event.keyCode); + } else if (MusicKeyboard.BLACKKEYS.indexOf(event.keyCode) !== -1) { + i = MusicKeyboard.BLACKKEYS.indexOf(event.keyCode); id = "blackRow" + i.toString(); - } else if (SPACE == event.keyCode) { + } else if (MusicKeyboard.SPACE == event.keyCode) { id = "rest"; } - ele = docById(id); + const ele = docById(id); if (!(id in startTime)) { - startDate = new Date(); + const startDate = new Date(); startTime[id] = startDate.getTime(); } @@ -164,16 +365,20 @@ function MusicKeyboard() { return; } - this._logo.synth.trigger(0, temp2[id], 1, this.instrumentMapper[id], null, null); + logo.synth.trigger(0, temp2[id], 1, this.instrumentMapper[id], null, null); if (this.tick) { - restDuration = (startTime[id] - this.endTime) / 1000.0; + let restDuration = (startTime[id] - this.endTime) / 1000.0; restDuration /= 60; // time in minutes restDuration *= this.bpm; restDuration *= this.meterArgs[1]; - restDuration = parseFloat((Math.round(restDuration * unit) / unit).toFixed(4)); + restDuration = parseFloat( + ( + Math.round(restDuration * MusicKeyboard.unit) / MusicKeyboard.unit + ).toFixed(4) + ); if (restDuration === 0) { restDuration = 0; @@ -191,7 +396,7 @@ function MusicKeyboard() { } }; - const __keyboarddown = function (event) { + const __keyboarddown = (event) => { if (current.has(event.keyCode)) return; __startNote(event); @@ -201,19 +406,19 @@ function MusicKeyboard() { }; const __endNote = (event) => { - let i, id, ele, no; - if (WHITEKEYS.indexOf(event.keyCode) !== -1) { - i = WHITEKEYS.indexOf(event.keyCode); + let i, id; + if (MusicKeyboard.WHITEKEYS.indexOf(event.keyCode) !== -1) { + i = MusicKeyboard.WHITEKEYS.indexOf(event.keyCode); id = "whiteRow" + i.toString(); - } else if (BLACKKEYS.indexOf(event.keyCode) !== -1) { - i = BLACKKEYS.indexOf(event.keyCode); + } else if (MusicKeyboard.BLACKKEYS.indexOf(event.keyCode) !== -1) { + i = MusicKeyboard.BLACKKEYS.indexOf(event.keyCode); id = "blackRow" + i.toString(); - } else if (SPACE == event.keyCode) { + } else if (MusicKeyboard.SPACE == event.keyCode) { id = "rest"; } - ele = docById(id); - newDate = new Date(); + const ele = docById(id); + const newDate = new Date(); this.endTime = newDate.getTime(); duration = (this.endTime - startTime[id]) / 1000.0; @@ -224,16 +429,16 @@ function MusicKeyboard() { ele.style.backgroundColor = "white"; } - no = ele.getAttribute("alt").split("__")[2]; - duration /= 60; duration *= this.bpm; duration *= this.meterArgs[1]; - duration = parseFloat((Math.round(duration * unit) / unit).toFixed(4)); + duration = parseFloat( + (Math.round(duration * MusicKeyboard.unit) / MusicKeyboard.unit).toFixed(4) + ); if (duration === 0) { - duration = 1 / unit; + duration = 1 / MusicKeyboard.unit; } else if (duration < 0) { duration = -duration; } @@ -245,7 +450,7 @@ function MusicKeyboard() { duration: parseFloat(duration) }); } else { - this._logo.synth.stopSound(0, this.instrumentMapper[id], temp2[id]); + logo.synth.stopSound(0, this.instrumentMapper[id], temp2[id]); this._notesPlayed.push({ startTime: startTime[id], noteOctave: temp2[id], @@ -263,7 +468,7 @@ function MusicKeyboard() { } }; - const __keyboardup = function (event) { + const __keyboardup = (event) => { current.delete(event.keyCode); __endNote(event); //event.preventDefault(); @@ -271,9 +476,17 @@ function MusicKeyboard() { document.onkeydown = __keyboarddown; document.onkeyup = __keyboardup; - }; + } + + /** + * @public + * @param {HTMLElement} element + * @param {number} i + * @param {number} blockNumber + * @returns {void} + */ - this.loadHandler = function (element, i, blockNumber) { + loadHandler(element, i, blockNumber) { const temp1 = this.layout[i].noteName; let temp2; if (temp1 === "hertz") { @@ -298,7 +511,7 @@ function MusicKeyboard() { startDate = new Date(); startTime = startDate.getTime(); // Milliseconds(); element.style.backgroundColor = platformColor.orange; - this._logo.synth.trigger( + logo.synth.trigger( 0, this.noteMapper[element.id], 1, @@ -308,8 +521,8 @@ function MusicKeyboard() { ); }; - element.onmousedown = function () { - __startNote(this); + element.onmousedown = () => { + __startNote(element); }; const __endNote = (element) => { @@ -323,12 +536,12 @@ function MusicKeyboard() { const now = new Date(); duration = now.getTime() - startTime; duration /= 1000; - this._logo.synth.stopSound( + logo.synth.stopSound( 0, this.instrumentMapper[element.id], this.noteMapper[element.id] ); - if (beginnerMode === "true") { + if (MusicKeyboard.beginnerMode === "true") { duration = parseFloat((Math.round(duration * 8) / 8).toFixed(3)); } else { duration = parseFloat((Math.round(duration * 16) / 16).toFixed(4)); @@ -351,159 +564,22 @@ function MusicKeyboard() { this._createTable(); }; - element.onmouseout = function () { + element.onmouseout = () => { // __endNote(); }; - element.onmouseup = function () { - __endNote(this); - }; - }; - - this.init = function (logo) { - this._logo = logo; - this.tick = false; - this.playingNow = false; - let w = window.innerWidth; - this._cellScale = w / 1200; - const iconSize = ICONSIZE * this._cellScale; - - const widgetWindow = window.widgetWindows.windowFor(this, "music keyboard"); - this.widgetWindow = widgetWindow; - widgetWindow.clear(); - widgetWindow.show(); - this._keysLayout(); - const tur = logo.turtles.ithTurtle(0); - this.bpm = tur.singer.bpm.length > 0 ? last(tur.singer.bpm) : Singer.masterBPM; - - widgetWindow.onclose = () => { - let myNode; - document.onkeydown = saveOnKeyDown; - document.onkeyup = saveOnKeyUp; - - if (document.getElementById("keyboardHolder2")) { - document.getElementById("keyboardHolder2").style.display = "none"; - } - - myNode = document.getElementById("myrow"); - if (myNode != null) { - myNode.innerHTML = ""; - } - - myNode = document.getElementById("myrow2"); - if (myNode != null) { - myNode.innerHTML = ""; - } - - selected = []; - selectedNotes = []; - if (this.loopTick) this.loopTick.stop(); - widgetWindow.destroy(); - }; - - this.playButton = widgetWindow.addButton("play-button.svg", ICONSIZE, _("Play")); - - this.playButton.onclick = () => { - this._logo.turtleDelay = 0; - this.processSelected(); - this.playAll(); - }; - - widgetWindow.addButton("export-chunk.svg", ICONSIZE, _("Save")).onclick = () => { - this._save(); - }; - - widgetWindow.addButton("erase-button.svg", ICONSIZE, _("Clear")).onclick = () => { - this._notesPlayed = []; - selectedNotes = []; - // if (!that.keyboardShown) { - this._createTable(); - // } - }; - - widgetWindow.addButton("add2.svg", ICONSIZE, _("Add note")).onclick = () => { - this._createAddRowPieSubmenu(); - }; - - this.midiButton = widgetWindow.addButton("midi.svg", ICONSIZE, _("MIDI")); - this.midiButton.onclick = () => { - this.doMIDI(); - }; - - this.tickButton = widgetWindow.addButton("metronome.svg", ICONSIZE, _("Metronome")); - this.tickButton.onclick = () => { - if (this.tick) { - this.tick = false; - this.loopTick.stop(); - } else { - this.tick = true; - this._logo.synth.loadSynth(0, "cow bell"); - this.loopTick = this._logo.synth.loop( - 0, - "cow bell", - "C5", - 1 / 64, - 0, - this.bpm || 90, - 0.07 - ); - setTimeout(() => { - this._logo.synth.start(); - }, 500); - } - }; - - // Append keyboard and div on widget windows - this.keyboardDiv = document.createElement("div"); - const attr = document.createAttribute("id"); - attr.value = "mkbKeyboardDiv"; - this.keyboardDiv.setAttributeNode(attr); - this.keyTable = document.createElement("div"); - widgetWindow.getWidgetBody().append(this.keyboardDiv); - widgetWindow.getWidgetBody().append(this.keyTable); - widgetWindow.getWidgetBody().style.height = "550px"; - widgetWindow.getWidgetBody().style.width = "1000px"; - - this._createKeyboard(); - - this._createTable(); - - w = Math.max( - Math.min(window.innerWidth, this._cellScale * OUTERWINDOWWIDTH - 20), - BUTTONDIVWIDTH - ); - - //Change widget size on fullscreen mode, else - //revert back to original size on unfullscreen mode - widgetWindow.onmaximize = function () { - if (widgetWindow._maximized) { - widgetWindow.getWidgetBody().style.position = "absolute"; - widgetWindow.getWidgetBody().style.height = "calc(100vh - 64px)"; - widgetWindow.getWidgetBody().style.width = "200vh"; - docById("mkbOuterDiv").style.width = "calc(200vh - 64px)"; - docById("keyboardHolder2").style.width = "calc(200vh - 64px)"; - try { - docById("mkbInnerDiv").style.width = "calc(200vh - 64px)"; - } catch (e) { - // Does this happen? - console.debug("Error calculating InnerDiv width"); - } - - widgetWindow.getWidgetBody().style.left = "70px"; - } else { - widgetWindow.getWidgetBody().style.position = "relative"; - widgetWindow.getWidgetBody().style.left = "0px"; - widgetWindow.getWidgetBody().style.height = "550px"; - widgetWindow.getWidgetBody().style.width = "1000px"; - docById("mkbOuterDiv").style.width = w + "px"; - } + element.onmouseup = () => { + __endNote(element); }; + } - widgetWindow.sendToCenter(); - }; + /** + * @public + * @returns {void} + */ - this.playAll = function () { - if (selectedNotes.length <= 0) { + playAll() { + if (MusicKeyboard.selectedNotes.length <= 0) { return; } @@ -519,26 +595,26 @@ function MusicKeyboard() { '" alt="' + _("stop") + '" height="' + - ICONSIZE + + MusicKeyboard.ICONSIZE + '" width="' + - ICONSIZE + + MusicKeyboard.ICONSIZE + '" vertical-align="middle" align-content="center">  '; - if (selectedNotes.length < 1) { + if (MusicKeyboard.selectedNotes.length < 1) { return; } const notes = []; - let ele, zx, res, cell, maxWidth; - for (let i = 0; i < selectedNotes[0].noteOctave.length; i++) { - if (this.keyboardShown && selectedNotes[0].objId[0] !== null) { - ele = docById(selectedNotes[0].objId[i]); + let ele, zx, res, cell; + for (let i = 0; i < MusicKeyboard.selectedNotes[0].noteOctave.length; i++) { + if (this.keyboardShown && MusicKeyboard.selectedNotes[0].objId[0] !== null) { + ele = docById(MusicKeyboard.selectedNotes[0].objId[i]); if (ele !== null) { ele.style.backgroundColor = "lightgrey"; } } - zx = selectedNotes[0].noteOctave[i]; + zx = MusicKeyboard.selectedNotes[0].noteOctave[i]; res = zx; if (typeof zx === "string") { res = zx.replace(SHARP, "#").replace(FLAT, "b"); @@ -553,8 +629,12 @@ function MusicKeyboard() { } this._stopOrCloseClicked = false; - this._playChord(notes, selectedNotes[0].duration, selectedNotes[0].voice); - maxWidth = Math.max.apply(Math, selectedNotes[0].duration); + this._playChord( + notes, + MusicKeyboard.selectedNotes[0].duration, + MusicKeyboard.selectedNotes[0].voice + ); + const maxWidth = Math.max.apply(Math, MusicKeyboard.selectedNotes[0].duration); this.playOne(1, maxWidth, playButtonCell); } else { if (!this.keyboardShown) { @@ -572,17 +652,24 @@ function MusicKeyboard() { '" alt="' + _("Play") + '" height="' + - ICONSIZE + + MusicKeyboard.ICONSIZE + '" width="' + - ICONSIZE + + MusicKeyboard.ICONSIZE + '" vertical-align="middle" align-content="center">  '; } - }; + } - this.playOne = function (counter, time, playButtonCell) { + /** + * @public + * @param {number} counter + * @param {string} time + * @param {HTMLElement} playButtonCell + * @returns {void} + */ + playOne(counter, time, playButtonCell) { setTimeout(() => { - let cell, eleid, ele, notes, id, zx, res, maxWidth; - if (counter < selectedNotes.length) { + let cell, eleid, ele, notes, zx, res, maxWidth; + if (counter < MusicKeyboard.selectedNotes.length) { if (this._stopOrCloseClicked) { return; } @@ -592,9 +679,16 @@ function MusicKeyboard() { cell.style.backgroundColor = platformColor.selectorBackground; } - if (this.keyboardShown && selectedNotes[counter - 1].objId[0] !== null) { - for (let i = 0; i < selectedNotes[counter - 1].noteOctave.length; i++) { - eleid = selectedNotes[counter - 1].objId[i]; + if ( + this.keyboardShown && + MusicKeyboard.selectedNotes[counter - 1].objId[0] !== null + ) { + for ( + let i = 0; + i < MusicKeyboard.selectedNotes[counter - 1].noteOctave.length; + i++ + ) { + eleid = MusicKeyboard.selectedNotes[counter - 1].objId[i]; ele = docById(eleid); if (eleid.includes("blackRow")) { ele.style.backgroundColor = "black"; @@ -605,19 +699,18 @@ function MusicKeyboard() { } notes = []; - for (let i = 0; i < selectedNotes[counter].noteOctave.length; i++) { - if (this.keyboardShown && selectedNotes[counter].objId[0] !== null) { - id = this.idContainer.findIndex((ele) => { - return ele[1] === selectedNotes[counter].objId[i]; - }); - - ele = docById(selectedNotes[counter].objId[i]); + for (let i = 0; i < MusicKeyboard.selectedNotes[counter].noteOctave.length; i++) { + if ( + this.keyboardShown && + MusicKeyboard.selectedNotes[counter].objId[0] !== null + ) { + ele = docById(MusicKeyboard.selectedNotes[counter].objId[i]); if (ele !== null) { ele.style.backgroundColor = "lightgrey"; } } - zx = selectedNotes[counter].noteOctave[i]; + zx = MusicKeyboard.selectedNotes[counter].noteOctave[i]; res = zx; if (typeof zx === "string") { res = zx.replace(SHARP, "#").replace(FLAT, "b"); @@ -628,12 +721,12 @@ function MusicKeyboard() { if (this.playingNow) { this._playChord( notes, - selectedNotes[counter].duration, - selectedNotes[counter].voice + MusicKeyboard.selectedNotes[counter].duration, + MusicKeyboard.selectedNotes[counter].voice ); } - maxWidth = Math.max.apply(Math, selectedNotes[counter].duration); + maxWidth = Math.max.apply(Math, MusicKeyboard.selectedNotes[counter].duration); this.playOne(counter + 1, maxWidth, playButtonCell); } else { playButtonCell.innerHTML = @@ -644,9 +737,9 @@ function MusicKeyboard() { '" alt="' + _("Play") + '" height="' + - ICONSIZE + + MusicKeyboard.ICONSIZE + '" width="' + - ICONSIZE + + MusicKeyboard.ICONSIZE + '" vertical-align="middle" align-content="center">  '; this.playingNow = false; if (!this.keyboardShown) { @@ -656,37 +749,50 @@ function MusicKeyboard() { } } }, time * 1000 + 125); - }; + } - this._playChord = (notes, noteValue, instruments) => { + /** + * @private + * @param {Array} notes + * @param {Array} noteValue + * @param {Array} instruments + * @returns {void} + */ + + _playChord(notes, noteValue, instruments) { if (notes[0] === "R") { return; } setTimeout(() => { - this._logo.synth.trigger(0, notes[0], noteValue[0], instruments[0], null, null); + logo.synth.trigger(0, notes[0], noteValue[0], instruments[0], null, null); }, 1); if (notes.length > 1) { setTimeout(() => { - this._logo.synth.trigger(0, notes[1], noteValue[0], instruments[1], null, null); + logo.synth.trigger(0, notes[1], noteValue[0], instruments[1], null, null); }, 1); } if (notes.length > 2) { setTimeout(() => { - this._logo.synth.trigger(0, notes[2], noteValue[0], instruments[2], null, null); + logo.synth.trigger(0, notes[2], noteValue[0], instruments[2], null, null); }, 1); } if (notes.length > 3) { setTimeout(() => { - this._logo.synth.trigger(0, notes[3], noteValue[0], instruments[3], null, null); + logo.synth.trigger(0, notes[3], noteValue[0], instruments[3], null, null); }, 1); } - }; + } - this._keysLayout = function () { + /** + * @private + * @returns {void} + */ + + _keysLayout() { this.layout = []; const sortableList = []; for (let i = 0; i < this.noteNames.length; i++) { @@ -710,7 +816,7 @@ function MusicKeyboard() { sortableList.push({ frequency: noteToFrequency( this.noteNames[i] + this.octaves[i], - this._logo.turtles.ithTurtle(0).singer.keySignature + logo.turtles.ithTurtle(0).singer.keySignature ), noteName: this.noteNames[i], noteOctave: this.octaves[i], @@ -720,7 +826,7 @@ function MusicKeyboard() { } } - let sortedList = sortableList.sort(function (a, b) { + let sortedList = sortableList.sort((a, b) => { return a.frequency - b.frequency; }); @@ -747,7 +853,7 @@ function MusicKeyboard() { removeBlock(i); } - const newList = fillChromaticGaps(sortedList); + const newList = this.fillChromaticGaps(sortedList); for (let i = 0; i < newList.length; i++) { this.layout.push({ @@ -757,17 +863,24 @@ function MusicKeyboard() { voice: newList[i].voice }); } - }; + } + + /** + * @private + * @param {number} colIndex + * @param {boolean} playNote + * @returns {void} + */ - this._setNotes = function (colIndex, playNote) { + _setNotes(colIndex, playNote) { const start = docById("cells-" + colIndex).getAttribute("start"); - this._notesPlayed = this._notesPlayed.filter(function (ele) { + this._notesPlayed = this._notesPlayed.filter((ele) => { return ele.startTime != parseInt(start); }); // Look for each cell that is marked in this column. - silence = true; + let silence = true; let row, cell, ele, dur; for (let j = 0; j < this.layout.length; j++) { row = docById("mkb" + j); @@ -787,16 +900,25 @@ function MusicKeyboard() { objId: null, duration: parseFloat(dur) }); - this._notesPlayed.sort(function (a, b) { + this._notesPlayed.sort((a, b) => { return a.startTime - b.startTime; }); } - }; + } - this._setNoteCell = function (j, colIndex, start, playNote) { + /** + * @private + * @param {number} j + * @param {number} colIndex + * @param {string} start + * @param {boolean} playNote + * @returns {void} + */ + + _setNoteCell(j, colIndex, start, playNote) { const n = this.layout.length; const temp1 = this.layout[n - j - 1].noteName; - let temp2, ele; + let temp2; if (temp1 === "hertz") { temp2 = this.layout[n - j - 1].noteOctave; } else if (temp1 in FIXEDSOLFEGE1) { @@ -808,7 +930,7 @@ function MusicKeyboard() { temp1.replace(SHARP, "#").replace(FLAT, "b") + this.layout[n - j - 1].noteOctave; } - ele = docById(j + ":" + colIndex); + const ele = docById(j + ":" + colIndex); this._notesPlayed.push({ startTime: parseInt(start), noteOctave: temp2, @@ -818,12 +940,12 @@ function MusicKeyboard() { voice: this.layout[n - j - 1].voice }); - this._notesPlayed.sort(function (a, b) { + this._notesPlayed.sort((a, b) => { return a.startTime - b.startTime; }); if (playNote) { - this._logo.synth.trigger( + logo.synth.trigger( 0, temp2, ele.getAttribute("alt"), @@ -832,13 +954,18 @@ function MusicKeyboard() { null ); } - }; + } - this.makeClickable = function () { + /** + * @public + * @returns {void} + */ + + makeClickable() { const rowNote = docById("mkbNoteDurationRow"); let cell; - for (let i = 0; i < selectedNotes.length; i++) { + for (let i = 0; i < MusicKeyboard.selectedNotes.length; i++) { cell = rowNote.cells[i]; cell.onclick = (event) => { @@ -864,11 +991,10 @@ function MusicKeyboard() { cell.onmousedown = (e) => { cell = e.target; - let obj, i, j; isMouseDown = true; - obj = cell.id.split(":"); - i = Number(obj[0]); - j = Number(obj[1]); + const obj = cell.id.split(":"); + // const i = Number(obj[0]); + const j = Number(obj[1]); if (cell.style.backgroundColor === "black") { cell.style.backgroundColor = cell.getAttribute("cellColor"); this._setNotes(j, false); @@ -879,10 +1005,9 @@ function MusicKeyboard() { }; cell.onmouseover = () => { - let obj, i, j; - obj = cell.id.split(":"); - i = Number(obj[0]); - j = Number(obj[1]); + const obj = cell.id.split(":"); + // const i = Number(obj[0]); + const j = Number(obj[1]); if (isMouseDown) { if (cell.style.backgroundColor === "black") { cell.style.backgroundColor = cell.getAttribute("cellColor"); @@ -894,18 +1019,29 @@ function MusicKeyboard() { } }; - cell.onmouseup = function () { + cell.onmouseup = () => { isMouseDown = false; }; } } - }; + } + + /** + * @private + * @param {number} noteValue + * @returns {number} + */ - this._noteWidth = function (noteValue) { + _noteWidth(noteValue) { return Math.max(Math.floor(EIGHTHNOTEWIDTH * (8 * noteValue) * this._cellScale), 15); - }; + } + + /** + * @private + * @returns {void} + */ - this._createTable = function () { + _createTable() { this.processSelected(); const mkbTableDiv = this.keyTable; mkbTableDiv.style.display = "inline"; @@ -934,7 +1070,7 @@ function MusicKeyboard() { docById("mkbInnerDiv").style.marginLeft = 0; const mkbTable = docById("mkbTable"); - if (selectedNotes.length < 1) { + if (MusicKeyboard.selectedNotes.length < 1) { outerDiv.innerHTML = ""; return; } @@ -1010,10 +1146,11 @@ function MusicKeyboard() { '
'; const cellColor = "lightgrey"; let maxWidth, noteMaxWidth, row, ind, dur; - for (let j = 0; j < selectedNotes.length; j++) { - maxWidth = Math.max.apply(Math, selectedNotes[j].duration); + for (let j = 0; j < MusicKeyboard.selectedNotes.length; j++) { + maxWidth = Math.max.apply(Math, MusicKeyboard.selectedNotes[j].duration); noteMaxWidth = - this._noteWidth(Math.max.apply(Math, selectedNotes[j].duration)) * 2 + "px"; + this._noteWidth(Math.max.apply(Math, MusicKeyboard.selectedNotes[j].duration)) * 2 + + "px"; n = this.layout.length; for (let i = 0; i < this.layout.length; i++) { row = docById("mkb" + i); @@ -1024,10 +1161,14 @@ function MusicKeyboard() { cell.style.maxWidth = cell.style.width; if ( - selectedNotes[j].blockNumber.indexOf(this.layout[n - i - 1].blockNumber) !== -1 + MusicKeyboard.selectedNotes[j].blockNumber.indexOf( + this.layout[n - i - 1].blockNumber + ) !== -1 ) { - ind = selectedNotes[j].blockNumber.indexOf(this.layout[n - i - 1].blockNumber); - cell.setAttribute("alt", selectedNotes[j].duration[ind]); + ind = MusicKeyboard.selectedNotes[j].blockNumber.indexOf( + this.layout[n - i - 1].blockNumber + ); + cell.setAttribute("alt", MusicKeyboard.selectedNotes[j].duration[ind]); cell.style.backgroundColor = "black"; cell.style.border = "2px solid white"; cell.style.borderRadius = "10px"; @@ -1041,7 +1182,7 @@ function MusicKeyboard() { cell.setAttribute("cellColor", cellColor); } - dur = toFraction(Math.max.apply(Math, selectedNotes[j].duration)); + dur = toFraction(Math.max.apply(Math, MusicKeyboard.selectedNotes[j].duration)); row = docById("mkbNoteDurationRow"); cell = row.insertCell(); cell.style.height = Math.floor(MATRIXSOLFEHEIGHT * this._cellScale) + 1 + "px"; @@ -1052,7 +1193,7 @@ function MusicKeyboard() { cell.style.textAlign = "center"; cell.innerHTML = dur[0].toString() + "/" + dur[1].toString(); cell.setAttribute("id", "cells-" + j); - cell.setAttribute("start", selectedNotes[j].startTime); + cell.setAttribute("start", MusicKeyboard.selectedNotes[j].startTime); cell.setAttribute("dur", maxWidth); cell.style.backgroundColor = platformColor.rhythmcellcolor; } @@ -1060,9 +1201,16 @@ function MusicKeyboard() { const innerDiv = docById("mkbInnerDiv"); innerDiv.scrollLeft = innerDiv.scrollWidth; // Force to the right. this.makeClickable(); - }; + } + + /** + * @private + * @param {string} cellId + * @param {string} start + * @returns {void} + */ - this._createpiesubmenu = function (cellId, start) { + _createpiesubmenu(cellId, start) { docById("wheelDivptm").style.display = ""; this._menuWheel = new wheelnav("wheelDivptm", null, 600, 600); @@ -1158,13 +1306,13 @@ function MusicKeyboard() { docById("wheelDivptm").style.left = Math.min( - this._logo.blocks.turtles._canvas.width - 200, - Math.max(0, x * this._logo.blocks.getStageScale()) + logo.blocks.turtles._canvas.width - 200, + Math.max(0, x * logo.blocks.getStageScale()) ) + "px"; docById("wheelDivptm").style.top = Math.min( - this._logo.blocks.turtles._canvas.height - 250, - Math.max(0, y * this._logo.blocks.getStageScale()) + logo.blocks.turtles._canvas.height - 250, + Math.max(0, y * logo.blocks.getStageScale()) ) + "px"; this._exitWheel.navItems[0].navigateFunction = () => { @@ -1226,13 +1374,20 @@ function MusicKeyboard() { docById("wheelnav-wheelDivptm-title-3").children[0].textContent = tabsLabels[j]; }; } - }; + } + + /** + * @private + * @param {string} start + * @param {number} duration + * @returns {void} + */ - this._updateDuration = function (start, duration) { + _updateDuration(start, duration) { start = parseInt(start); duration = parseInt(duration[0]) / parseInt(duration[1]); const newduration = parseFloat((Math.round(duration * 8) / 8).toFixed(3)); - this._notesPlayed = this._notesPlayed.map(function (item) { + this._notesPlayed = this._notesPlayed.map((item) => { if (item.startTime === start) { item.duration = newduration; } @@ -1240,14 +1395,22 @@ function MusicKeyboard() { return item; }); this._createTable(); - }; + } - this._addNotes = function (cellId, start, divideNoteBy) { + + /** + * @private + * @param {string} cellId + * @param {string} start + * @param {number} divideNoteBy + * @returns {void} + */ + _addNotes(cellId, start, divideNoteBy) { start = parseInt(start); const cell = docById(cellId); const dur = cell.getAttribute("dur"); - this._notesPlayed = this._notesPlayed.reduce(function (prevValue, curValue) { + this._notesPlayed = this._notesPlayed.reduce((prevValue, curValue) => { let oldcurValue, newcurValue; if (parseInt(curValue.startTime) === start) { prevValue = prevValue.concat([curValue]); @@ -1269,25 +1432,37 @@ function MusicKeyboard() { }, []); this._createTable(); - }; + } + + /** + * @private + * @param {string} start + * @returns {void} + */ - this._deleteNotes = function (start) { + _deleteNotes(start) { start = parseInt(start); - this._notesPlayed = this._notesPlayed.filter(function (ele) { + this._notesPlayed = this._notesPlayed.filter((ele) => { return parseInt(ele.startTime) !== start; }); this._createTable(); - }; + } + + /** + * @private + * @param {string} start + * @param {number} divideNoteBy + * @returns {void} + */ - this._divideNotes = function (start, divideNoteBy) { + _divideNotes(start, divideNoteBy) { start = parseInt(start); - this._notesPlayed = this._notesPlayed.reduce(function (prevValue, curValue) { - let newcurValue, newcurValue2, oldcrValue; + this._notesPlayed = this._notesPlayed.reduce((prevValue, curValue) => { if (parseInt(curValue.startTime) === start) { - if (beginnerMode === "true") { + if (MusicKeyboard.beginnerMode === "true") { if (curValue.duration / divideNoteBy < 0.125) { return prevValue.concat([curValue]); } @@ -1297,12 +1472,12 @@ function MusicKeyboard() { } } - newcurValue = JSON.parse(JSON.stringify(curValue)); + const newcurValue = JSON.parse(JSON.stringify(curValue)); newcurValue.duration = curValue.duration / divideNoteBy; prevValue = prevValue.concat([newcurValue]); - oldcurValue = newcurValue; + let oldcurValue = newcurValue; for (let i = 0; i < divideNoteBy - 1; i++) { - newcurValue2 = JSON.parse(JSON.stringify(oldcurValue)); + const newcurValue2 = JSON.parse(JSON.stringify(oldcurValue)); newcurValue2.startTime = parseInt( newcurValue2.startTime + newcurValue2.duration * 1000 ); @@ -1317,9 +1492,14 @@ function MusicKeyboard() { }, []); this._createTable(); - }; + } + + /** + * @private + * @returns {void} + */ - this._createAddRowPieSubmenu = function () { + _createAddRowPieSubmenu() { docById("wheelDivptm").style.display = ""; docById("wheelDivptm").style.zIndex = "300"; const pitchLabels = ["do", "re", "mi", "fa", "sol", "la", "ti"]; @@ -1376,13 +1556,13 @@ function MusicKeyboard() { docById("wheelDivptm").style.width = "300px"; docById("wheelDivptm").style.left = Math.min( - this._logo.blocks.turtles._canvas.width - 200, - Math.max(0, x * this._logo.blocks.getStageScale()) + logo.blocks.turtles._canvas.width - 200, + Math.max(0, x * logo.blocks.getStageScale()) ) + "px"; docById("wheelDivptm").style.top = Math.min( - this._logo.blocks.turtles._canvas.height - 250, - Math.max(0, y * this._logo.blocks.getStageScale()) + logo.blocks.turtles._canvas.height - 250, + Math.max(0, y * logo.blocks.getStageScale()) ) + "px"; this._exitWheel.navItems[0].navigateFunction = () => { @@ -1400,10 +1580,11 @@ function MusicKeyboard() { return; } const label = VALUESLABEL[this._menuWheel.selectedNavItemIndex]; - const newBlock = this._logo.blocks.blockList.length; + const newBlock = logo.blocks.blockList.length; if (label === "pitch") { - for (let i = 0; i < pitchLabels.length; i++) { + let i; + for (i = 0; i < pitchLabels.length; i++) { if ( pitchLabels[i].indexOf(last(this.layout).noteName) !== -1 || last(this.layout).noteName.indexOf(pitchLabels[i]) !== -1 @@ -1451,25 +1632,25 @@ function MusicKeyboard() { switch (label) { case "pitch": - this._logo.blocks.loadNewBlocks([ + logo.blocks.loadNewBlocks([ [0, ["pitch", {}], 0, 0, [null, 1, 2, null]], [1, ["solfege", { value: rLabel }], 0, 0, [0]], [2, ["number", { value: rArg }], 0, 0, [0]] ]); break; case "hertz": - this._logo.blocks.loadNewBlocks([ + logo.blocks.loadNewBlocks([ [0, ["hertz", {}], 0, 0, [null, 1, null]], [1, ["number", { value: rArg }], 0, 0, [0]] ]); break; default: - console.log("Nothing to do for " + label); + // console.log("Nothing to do for " + label); } let aboveBlock = -1; for (let i = this.layout.length; i > 0; i--) { - if (this.layout[i - 1].blockNumber < FAKEBLOCKNUMBER) { + if (this.layout[i - 1].blockNumber < MusicKeyboard.FAKEBLOCKNUMBER) { aboveBlock = this.layout[i - 1].blockNumber; break; } @@ -1489,37 +1670,49 @@ function MusicKeyboard() { this._createTable(); }, 500); } else { - console.log("Could not find anywhere to insert new block."); + // console.log("Could not find anywhere to insert new block."); } }; for (let i = 0; i < valueLabel.length; i++) { this._menuWheel.navItems[i].navigateFunction = __selectionChanged; } - }; + } + + /** + * @private + * @param {number} aboveBlock + * @param {number} block + * @returns {void} + */ - this._addNotesBlockBetween = function (aboveBlock, block) { - const belowBlock = last(this._logo.blocks.blockList[aboveBlock].connections); - this._logo.blocks.blockList[aboveBlock].connections[ - this._logo.blocks.blockList[aboveBlock].connections.length - 1 + _addNotesBlockBetween(aboveBlock, block) { + const belowBlock = last(logo.blocks.blockList[aboveBlock].connections); + logo.blocks.blockList[aboveBlock].connections[ + logo.blocks.blockList[aboveBlock].connections.length - 1 ] = block; if (belowBlock !== null) { - this._logo.blocks.blockList[belowBlock].connections[0] = block; + logo.blocks.blockList[belowBlock].connections[0] = block; } - this._logo.blocks.blockList[block].connections[0] = aboveBlock; + logo.blocks.blockList[block].connections[0] = aboveBlock; - this._logo.blocks.blockList[block].connections[ - this._logo.blocks.blockList[block].connections.length - 1 + logo.blocks.blockList[block].connections[ + logo.blocks.blockList[block].connections.length - 1 ] = belowBlock; - this._logo.blocks.adjustDocks(this.blockNo, true); - this._logo.blocks.clampBlocksToCheck.push([this.blockNo, 0]); - this._logo.blocks.refreshCanvas(); - }; + logo.blocks.adjustDocks(this.blockNo, true); + logo.blocks.clampBlocksToCheck.push([this.blockNo, 0]); + logo.blocks.refreshCanvas(); + } + + /** + * @private + * @returns {void} + */ - this._sortLayout = function () { + _sortLayout() { this.layout.sort((a, b) => { let aValue, bValue; if (a.noteName == "hertz") { @@ -1527,7 +1720,7 @@ function MusicKeyboard() { } else { aValue = noteToFrequency( a.noteName + a.noteOctave, - this._logo.turtles.ithTurtle(0).singer.keySignature + logo.turtles.ithTurtle(0).singer.keySignature ); } if (b.noteName == "hertz") { @@ -1535,7 +1728,7 @@ function MusicKeyboard() { } else { bValue = noteToFrequency( b.noteName + b.noteOctave, - this._logo.turtles.ithTurtle(0).singer.keySignature + logo.turtles.ithTurtle(0).singer.keySignature ); } @@ -1571,33 +1764,46 @@ function MusicKeyboard() { } else { this._createTable(); } - }; + } + + /** + * @private + * @param {number} blockNo + * @returns {void} + */ - this._removePitchBlock = function (blockNo) { - const c0 = this._logo.blocks.blockList[blockNo].connections[0]; - const c1 = last(this._logo.blocks.blockList[blockNo].connections); - if (this._logo.blocks.blockList[c0].name === "musickeyboard") { - this._logo.blocks.blockList[c0].connections[1] = c1; + _removePitchBlock(blockNo) { + const c0 = logo.blocks.blockList[blockNo].connections[0]; + const c1 = last(logo.blocks.blockList[blockNo].connections); + if (logo.blocks.blockList[c0].name === "musickeyboard") { + logo.blocks.blockList[c0].connections[1] = c1; } else { - this._logo.blocks.blockList[c0].connections[ - this._logo.blocks.blockList[c0].connections.length - 1 + logo.blocks.blockList[c0].connections[ + logo.blocks.blockList[c0].connections.length - 1 ] = c1; } if (c1) { - this._logo.blocks.blockList[c1].connections[0] = c0; + logo.blocks.blockList[c1].connections[0] = c0; } - this._logo.blocks.blockList[blockNo].connections[ - this._logo.blocks.blockList[blockNo].connections.length - 1 + logo.blocks.blockList[blockNo].connections[ + logo.blocks.blockList[blockNo].connections.length - 1 ] = null; - this._logo.blocks.sendStackToTrash(this._logo.blocks.blockList[blockNo]); - this._logo.blocks.adjustDocks(this.blockNo, true); - this._logo.blocks.clampBlocksToCheck.push([this.blockNo, 0]); - this._logo.blocks.refreshCanvas(); - }; + logo.blocks.sendStackToTrash(logo.blocks.blockList[blockNo]); + logo.blocks.adjustDocks(this.blockNo, true); + logo.blocks.clampBlocksToCheck.push([this.blockNo, 0]); + logo.blocks.refreshCanvas(); + } + + /** + * @private + * @param {string} index + * @param {string} condition + * @returns {void} + */ - this._createColumnPieSubmenu = function (index, condition) { + _createColumnPieSubmenu(index, condition) { index = parseInt(index); if ( blocks.blockList[this.layout[this.layout.length - index - 1].blockNumber] === undefined @@ -1730,25 +1936,25 @@ function MusicKeyboard() { docById("wheelDivptm").style.width = "300px"; docById("wheelDivptm").style.left = Math.min( - this._logo.blocks.turtles._canvas.width - 200, - Math.max(0, x * this._logo.blocks.getStageScale()) + logo.blocks.turtles._canvas.width - 200, + Math.max(0, x * logo.blocks.getStageScale()) ) + "px"; docById("wheelDivptm").style.top = Math.min( - this._logo.blocks.turtles._canvas.height - 250, - Math.max(0, y * this._logo.blocks.getStageScale()) + logo.blocks.turtles._canvas.height - 250, + Math.max(0, y * logo.blocks.getStageScale()) ) + "px"; index = this.layout.length - index - 1; const block = this.layout[index].blockNumber; - let noteValue = this._logo.blocks.blockList[ - this._logo.blocks.blockList[block].connections[1] + let noteValue = logo.blocks.blockList[ + logo.blocks.blockList[block].connections[1] ].value; if (condition === "pitchblocks") { - const octaveValue = this._logo.blocks.blockList[ - this._logo.blocks.blockList[block].connections[2] + const octaveValue = logo.blocks.blockList[ + logo.blocks.blockList[block].connections[2] ].value; let accidentalsValue = 2; @@ -1779,22 +1985,23 @@ function MusicKeyboard() { }; const __hertzSelectionChanged = () => { - blockValue = this._pitchWheel.navItems[this._pitchWheel.selectedNavItemIndex].title; - const argBlock = this._logo.blocks.blockList[block].connections[1]; - this._logo.blocks.blockList[argBlock].text.text = blockValue; - this._logo.blocks.blockList[argBlock].value = parseInt(blockValue); - - const z = this._logo.blocks.blockList[argBlock].container.children.length - 1; - this._logo.blocks.blockList[argBlock].container.setChildIndex( - this._logo.blocks.blockList[argBlock].text, + const blockValue = this._pitchWheel.navItems[this._pitchWheel.selectedNavItemIndex] + .title; + const argBlock = logo.blocks.blockList[block].connections[1]; + logo.blocks.blockList[argBlock].text.text = blockValue; + logo.blocks.blockList[argBlock].value = parseInt(blockValue); + + const z = logo.blocks.blockList[argBlock].container.children.length - 1; + logo.blocks.blockList[argBlock].container.setChildIndex( + logo.blocks.blockList[argBlock].text, z ); - this._logo.blocks.blockList[argBlock].updateCache(); + logo.blocks.blockList[argBlock].updateCache(); const cell = docById("labelcol" + (this.layout.length - index - 1)); this.layout[index].noteOctave = parseInt(blockValue); cell.innerHTML = this.layout[index].noteName + this.layout[index].noteOctave.toString(); - this._notesPlayed.map(function (item) { + this._notesPlayed.map((item) => { if (item.objId == this.layout[index].blockNumber) { item.noteOctave = parseInt(blockValue); } @@ -1810,40 +2017,38 @@ function MusicKeyboard() { const __selectionChanged = () => { let label = this._pitchWheel.navItems[this._pitchWheel.selectedNavItemIndex].title; - let labelValue, i, attr, flag; + let labelValue, i, attr; if (condition === "pitchblocks") { i = noteLabelsI18n.indexOf(label); labelValue = noteLabels[i]; attr = this._accidentalsWheel.navItems[this._accidentalsWheel.selectedNavItemIndex] .title; - flag = false; if (attr !== "♮") { label += attr; - flag = true; } } else { i = noteLabels.indexOf(label); labelValue = label; } - const noteLabelBlock = this._logo.blocks.blockList[block].connections[1]; - this._logo.blocks.blockList[noteLabelBlock].text.text = label; - this._logo.blocks.blockList[noteLabelBlock].value = labelValue; + const noteLabelBlock = logo.blocks.blockList[block].connections[1]; + logo.blocks.blockList[noteLabelBlock].text.text = label; + logo.blocks.blockList[noteLabelBlock].value = labelValue; - const z = this._logo.blocks.blockList[noteLabelBlock].container.children.length - 1; - this._logo.blocks.blockList[noteLabelBlock].container.setChildIndex( - this._logo.blocks.blockList[noteLabelBlock].text, + const z = logo.blocks.blockList[noteLabelBlock].container.children.length - 1; + logo.blocks.blockList[noteLabelBlock].container.setChildIndex( + logo.blocks.blockList[noteLabelBlock].text, z ); - this._logo.blocks.blockList[noteLabelBlock].updateCache(); + logo.blocks.blockList[noteLabelBlock].updateCache(); let octave; if (condition === "pitchblocks") { octave = Number( this._octavesWheel.navItems[this._octavesWheel.selectedNavItemIndex].title ); - this._logo.blocks.blockList[noteLabelBlock].blocks.setPitchOctave( - this._logo.blocks.blockList[noteLabelBlock].connections[0], + logo.blocks.blockList[noteLabelBlock].blocks.setPitchOctave( + logo.blocks.blockList[noteLabelBlock].connections[0], octave ); } @@ -1853,7 +2058,7 @@ function MusicKeyboard() { this.layout[index].noteOctave = octave; cell.innerHTML = this.layout[index].noteName + this.layout[index].noteOctave.toString(); const temp1 = label; - let temp3; + let temp2; if (temp1 in FIXEDSOLFEGE1) { temp2 = FIXEDSOLFEGE1[temp1].replace(SHARP, "#").replace(FLAT, "b") + octave; } else { @@ -1873,8 +2078,9 @@ function MusicKeyboard() { const i = noteLabelsI18n.indexOf(label); let labelValue = noteLabels[i]; - const attr = this._accidentalsWheel.navItems[this._accidentalsWheel.selectedNavItemIndex] - .title; + const attr = this._accidentalsWheel.navItems[ + this._accidentalsWheel.selectedNavItemIndex + ].title; if (attr !== "♮") { labelValue += attr; } @@ -1886,15 +2092,15 @@ function MusicKeyboard() { labelValue, octave, 0, - this._logo.turtles.ithTurtle(0).singer.keySignature, + logo.turtles.ithTurtle(0).singer.keySignature, false, null, - this._logo.errorMsg, - this._logo.synth.inTemperament + logo.errorMsg, + logo.synth.inTemperament ); - this._logo.synth.setMasterVolume(PREVIEWVOLUME); - Singer.setSynthVolume(this._logo, 0, DEFAULTVOICE, PREVIEWVOLUME); - this._logo.synth.trigger(0, [obj[0] + obj[1]], 1 / 8, DEFAULTVOICE, null, null); + logo.synth.setMasterVolume(PREVIEWVOLUME); + Singer.setSynthVolume(logo, 0, DEFAULTVOICE, PREVIEWVOLUME); + logo.synth.trigger(0, [obj[0] + obj[1]], 1 / 8, DEFAULTVOICE, null, null); __selectionChanged(); }; @@ -1912,9 +2118,14 @@ function MusicKeyboard() { this._octavesWheel.navItems[i].navigateFunction = __pitchPreview; } } - }; + } + + /** + * @private + * @returns {void} + */ - this._createKeyboard = function () { + _createKeyboard() { document.onkeydown = null; const mkbKeyboardDiv = this.keyboardDiv; mkbKeyboardDiv.style.display = "flex"; @@ -1932,6 +2143,7 @@ function MusicKeyboard() { keyboardHolder2.style.left = "0px"; keyboardHolder2.style.height = "145px"; keyboardHolder2.style.backgroundColor = "white"; + keyboardHolder2.style.cursor = "pointer"; const blackRow = document.getElementsByClassName("black"); blackRow[0].style.top = "1px"; blackRow[0].style.borderSpacing = "0px 0px 20px"; @@ -1962,10 +2174,10 @@ function MusicKeyboard() { let myrowId = 0; let myrow2Id = 0; - let parentbl, parentbl2, el, newel, newel2, nname, elementid, elementid2; + let parenttbl, parenttbl2, el, newel, newel2, nname; for (let p = 0; p < this.layout.length; p++) { // If the blockNumber is null, don't add a label. - if (this.layout[p].noteName > FAKEBLOCKNUMBER) { + if (this.layout[p].noteName > MusicKeyboard.FAKEBLOCKNUMBER) { parenttbl2 = document.getElementById("myrow2"); newel2 = document.createElement("td"); newel2.setAttribute("id", "blackRow" + myrow2Id.toString()); @@ -1984,10 +2196,10 @@ function MusicKeyboard() { newel2.setAttribute( "alt", this.layout[p].noteName + - "__" + - this.layout[p].noteOctave + - "__" + - this.layout[p].blockNumber + "__" + + this.layout[p].noteOctave + + "__" + + this.layout[p].blockNumber ); this.idContainer.push([ "blackRow" + myrow2Id.toString(), @@ -2008,10 +2220,10 @@ function MusicKeyboard() { newel.setAttribute( "alt", this.layout[p].noteName + - "__" + - this.layout[p].voice + - "__" + - this.layout[p].blockNumber + "__" + + this.layout[p].voice + + "__" + + this.layout[p].blockNumber ); this.idContainer.push([ "whiteRow" + myrowId.toString(), @@ -2019,7 +2231,7 @@ function MusicKeyboard() { ]); newel.innerHTML = "(" + - String.fromCharCode(WHITEKEYS[myrowId]) + + String.fromCharCode(MusicKeyboard.WHITEKEYS[myrowId]) + ")
" + this.layout[p].voice; @@ -2037,10 +2249,10 @@ function MusicKeyboard() { newel.setAttribute( "alt", this.layout[p].noteName + - "__" + - this.layout[p].noteOctave + - "__" + - this.layout[p].blockNumber + "__" + + this.layout[p].noteOctave + + "__" + + this.layout[p].blockNumber ); this.idContainer.push([ "whiteRow" + myrowId.toString(), @@ -2048,7 +2260,7 @@ function MusicKeyboard() { ]); newel.innerHTML = "(" + - String.fromCharCode(WHITEKEYS[myrowId]) + + String.fromCharCode(MusicKeyboard.WHITEKEYS[myrowId]) + ")
" + this.layout[p].noteOctave; @@ -2081,10 +2293,10 @@ function MusicKeyboard() { newel2.setAttribute( "alt", this.layout[p].noteName + - "__" + - this.layout[p].noteOctave + - "__" + - this.layout[p].blockNumber + "__" + + this.layout[p].noteOctave + + "__" + + this.layout[p].blockNumber ); this.idContainer.push([ "blackRow" + myrow2Id.toString(), @@ -2092,11 +2304,12 @@ function MusicKeyboard() { ]); nname = this.layout[p].noteName.replace(SHARP, "").replace("#", ""); - if (this.layout[p].blockNumber > FAKEBLOCKNUMBER) { + if (this.layout[p].blockNumber > MusicKeyboard.FAKEBLOCKNUMBER) { + // } else if (SOLFEGENAMES.indexOf(nname) !== -1) { newel2.innerHTML = "(" + - String.fromCharCode(BLACKKEYS[myrow2Id]) + + String.fromCharCode(MusicKeyboard.BLACKKEYS[myrow2Id]) + ")
" + i18nSolfege(nname) + SHARP + @@ -2104,7 +2317,7 @@ function MusicKeyboard() { } else { newel2.innerHTML = "(" + - String.fromCharCode(BLACKKEYS[myrow2Id]) + + String.fromCharCode(MusicKeyboard.BLACKKEYS[myrow2Id]) + ")
" + this.layout[p].noteName + this.layout[p].noteOctave; @@ -2122,7 +2335,6 @@ function MusicKeyboard() { ) { parenttbl2 = document.getElementById("myrow2"); newel2 = document.createElement("td"); - elementid2 = document.getElementsByTagName("td").length; newel2.setAttribute("id", "blackRow" + myrow2Id.toString()); newel2.style.textAlign = "center"; if ([2, 6, 9, 13, 16, 20].indexOf(myrow2Id) !== -1) { @@ -2140,21 +2352,22 @@ function MusicKeyboard() { newel2.setAttribute( "alt", this.layout[p].noteName + - "__" + - this.layout[p].noteOctave + - "__" + - this.layout[p].blockNumber + "__" + + this.layout[p].noteOctave + + "__" + + this.layout[p].blockNumber ); this.idContainer.push([ "blackRow" + myrow2Id.toString(), this.layout[p].blockNumber ]); nname = this.layout[p].noteName.replace(FLAT, "").replace("b", ""); - if (this.layout[p].blockNumber > FAKEBLOCKNUMBER) { + if (this.layout[p].blockNumber > MusicKeyboard.FAKEBLOCKNUMBER) { + // } else if (SOLFEGENAMES.indexOf(nname) !== -1) { newel2.innerHTML = "(" + - String.fromCharCode(BLACKKEYS[myrow2Id]) + + String.fromCharCode(MusicKeyboard.BLACKKEYS[myrow2Id]) + ")
" + i18nSolfege(nname) + FLAT + @@ -2162,7 +2375,7 @@ function MusicKeyboard() { } else { newel2.innerHTML = "(" + - String.fromCharCode(BLACKKEYS[myrow2Id]) + + String.fromCharCode(MusicKeyboard.BLACKKEYS[myrow2Id]) + ")
" + this.layout[p].noteName + this.layout[p].noteOctave; @@ -2177,35 +2390,35 @@ function MusicKeyboard() { } else { parenttbl = document.getElementById("myrow"); newel = document.createElement("td"); - elementid = document.getElementsByTagName("td").length; newel.setAttribute("id", "whiteRow" + myrowId.toString()); newel.style.textAlign = "center"; newel.setAttribute( "alt", this.layout[p].noteName + - "__" + - this.layout[p].noteOctave + - "__" + - this.layout[p].blockNumber + "__" + + this.layout[p].noteOctave + + "__" + + this.layout[p].blockNumber ); this.idContainer.push([ "whiteRow" + myrowId.toString(), this.layout[p].blockNumber ]); - if (this.layout[p].blockNumber > FAKEBLOCKNUMBER) { + if (this.layout[p].blockNumber > MusicKeyboard.FAKEBLOCKNUMBER) { + // } else if (SOLFEGENAMES.indexOf(this.layout[p].noteName) !== -1) { newel.innerHTML = "(" + - String.fromCharCode(WHITEKEYS[myrowId]) + + String.fromCharCode(MusicKeyboard.WHITEKEYS[myrowId]) + ")
" + i18nSolfege(this.layout[p].noteName) + this.layout[p].noteOctave; } else { newel.innerHTML = "(" + - String.fromCharCode(WHITEKEYS[myrowId]) + + String.fromCharCode(MusicKeyboard.WHITEKEYS[myrowId]) + ")
" + this.layout[p].noteName + this.layout[p].noteOctave; @@ -2236,7 +2449,7 @@ function MusicKeyboard() { for (let i = 0; i < this.idContainer.length; i++) { // If the blockNumber is null, don't make the key clickable. if (this.layout[i].blockNumber === null) { - console.log("skipping " + i); + // console.log("skipping " + i); continue; } this.loadHandler( @@ -2247,16 +2460,21 @@ function MusicKeyboard() { } this.addKeyboardShortcuts(); - }; + } + + /** + * @private + * @returns {void} + */ - this._save = function () { + _save() { this.processSelected(); - console.debug("Generating action stack for: "); - console.debug(selectedNotes); + // console.debug("Generating action stack for: "); + // console.debug(MusicKeyboard.selectedNotes); const newStack = [ [0, ["action", { collapsed: false }], 100, 100, [null, 1, 2, null]], [1, ["text", { value: _("action") }], 0, 0, [0]], - [2, "hidden", 0, 0, [0, selectedNotes.length == 0 ? null : 3]] + [2, "hidden", 0, 0, [0, MusicKeyboard.selectedNotes.length == 0 ? null : 3]] ]; // This function organizes notes into groups with same voices. @@ -2293,7 +2511,7 @@ function MusicKeyboard() { this.findLen = (selectedNotesGrp, selectedNotes) => { let ans = 0; for (let i = 0; i < selectedNotesGrp.length; i++) { - note = selectedNotes[selectedNotesGrp[i]]; + const note = selectedNotes[selectedNotesGrp[i]]; if (note.noteOctave[0] === "R") { ans += 6; // rest note uses 6 } else if (note.noteOctave[0] === null) { @@ -2305,7 +2523,7 @@ function MusicKeyboard() { return ans; }; - newNotes = this._clusterNotes(selectedNotes); + const newNotes = this._clusterNotes(MusicKeyboard.selectedNotes); let prevId = 2; let endOfStackIdx, id; @@ -2314,8 +2532,10 @@ function MusicKeyboard() { const selectedNotesGrp = newNotes[noteGrp]; const isLast = noteGrp == newNotes.length - 1; id = newStack.length; - const voice = selectedNotes[selectedNotesGrp[0]].voice[0] || DEFAULTVOICE; - const next = isLast ? null : id + 3 + this.findLen(selectedNotesGrp, selectedNotes); + const voice = MusicKeyboard.selectedNotes[selectedNotesGrp[0]].voice[0] || DEFAULTVOICE; + const next = isLast + ? null + : id + 3 + this.findLen(selectedNotesGrp, MusicKeyboard.selectedNotes); newStack.push( [id, "settimbre", 0, 0, [prevId, id + 1, id + 3, id + 2]], @@ -2327,7 +2547,7 @@ function MusicKeyboard() { endOfStackIdx = id; for (let i = 0; i < selectedNotesGrp.length; i++) { - note = selectedNotes[selectedNotesGrp[i]]; + const note = MusicKeyboard.selectedNotes[selectedNotesGrp[i]]; // Add the Note block and its value const idx = newStack.length; @@ -2480,19 +2700,24 @@ function MusicKeyboard() { } } - this._logo.blocks.loadNewBlocks(newStack); - this._logo.textMsg(_("New action block generated!")); - }; + logo.blocks.loadNewBlocks(newStack); + logo.textMsg(_("New action block generated!")); + } + + /** + * @private + * @returns {void} + */ - this.clearBlocks = function () { + clearBlocks() { this.noteNames = []; this.octaves = []; - }; + } /** * @deprecated */ - this._addButton = function (row, icon, iconSize, label) { + _addButton(row, icon, iconSize, label) { const cell = row.insertCell(-1); cell.innerHTML = '    '; - cell.style.width = BUTTONSIZE + "px"; + cell.style.width = MusicKeyboard.BUTTONSIZE + "px"; cell.style.minWidth = cell.style.width; cell.style.maxWidth = cell.style.width; cell.style.height = cell.style.width; @@ -2514,25 +2739,32 @@ function MusicKeyboard() { cell.style.maxHeight = cell.style.height; cell.style.backgroundColor = platformColor.selectorBackground; - cell.onmouseover = function () { + cell.onmouseover = () => { this.style.backgroundColor = platformColor.selectorBackgroundHOVER; }; - cell.onmouseout = function () { + cell.onmouseout = () => { this.style.backgroundColor = platformColor.selectorBackground; }; return cell; - }; + } + + /** + * @private + * @param {string} index + * @param {string} condition + * @returns {void} + */ - this.doMIDI = () => { + doMIDI() { let duration = 0; let startTime = 0; this.getElement = {}; for (let idx = 0; idx < this.layout.length; idx++) { - key = this.layout[idx]; + const key = this.layout[idx]; this.getElement[key.noteName.toString() + key.noteOctave.toString()] = key.objId; this.getElement[FIXEDSOLFEGE1[key.noteName.toString()] + "" + key.noteOctave] = key.objId; //convet solfege to alphabetic. @@ -2542,7 +2774,7 @@ function MusicKeyboard() { if (!element) return; startTime = event.timeStamp; // Milliseconds(); element.style.backgroundColor = platformColor.orange; - this._logo.synth.trigger( + logo.synth.trigger( 0, this.noteMapper[element.id], 1, @@ -2565,12 +2797,12 @@ function MusicKeyboard() { const now = event.timeStamp; duration = now - startTime; duration /= 1000; - this._logo.synth.stopSound( + logo.synth.stopSound( 0, this.instrumentMapper[element.id], this.noteMapper[element.id] ); - if (beginnerMode === "true") { + if (MusicKeyboard.beginnerMode === "true") { duration = parseFloat((Math.round(duration * 8) / 8).toFixed(3)); } else { duration = parseFloat((Math.round(duration * 16) / 16).toFixed(4)); @@ -2645,13 +2877,17 @@ function MusicKeyboard() { }; if (navigator.requestMIDIAccess) - navigator.requestMIDIAccess({ sysex: true }) - .then(onMIDISuccess, onMIDIFailure); - else - logo.errorMsg(_("Failed to get MIDI access in browser.")); - }; + navigator.requestMIDIAccess({ sysex: true }).then(onMIDISuccess, onMIDIFailure); + else logo.errorMsg(_("Failed to get MIDI access in browser.")); + } + + /** + * @private + * @param {Array} noteList + * @returns {Array} + */ - function fillChromaticGaps(noteList) { + fillChromaticGaps(noteList) { // Assuming list of either solfege or letter class of the form // sol4 or G4. Each entry is a dictionary with noteName and // noteOctave. @@ -2661,7 +2897,7 @@ function MusicKeyboard() { const hertzList = []; const drumList = []; let obj = null; - let fakeBlockNumber = FAKEBLOCKNUMBER + 1; + let fakeBlockNumber = MusicKeyboard.FAKEBLOCKNUMBER + 1; // Find the first non-Hertz note. for (let i = 0; i < noteList.length; i++) { @@ -2790,4 +3026,4 @@ function MusicKeyboard() { return newList; } -} +} \ No newline at end of file