diff --git a/.jshintrc b/.jshintrc index 8ab3485..d22fe13 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,3 +1,6 @@ { - "esversion": 6 + "esversion": 6, + // Allow array["access"]. We use this with localStorage to avoid any + // aggressive minification doing variable name optimisation + "sub": true } \ No newline at end of file diff --git a/src/js/HuesCanvas.js b/src/js/HuesCanvas.js index a01b45d..0836692 100644 --- a/src/js/HuesCanvas.js +++ b/src/js/HuesCanvas.js @@ -104,7 +104,7 @@ HuesCanvas.prototype.settingsUpdated = function() { this.setBlurDecay(localStorage["blurDecay"]); this.setBlurQuality(localStorage["blurQuality"]); this.trippyOn = localStorage["trippyMode"] == "on"; -} +}; HuesCanvas.prototype.resize = function() { // height is constant 720px, we expand width to suit @@ -167,7 +167,7 @@ HuesCanvas.prototype.redraw = function() { this.context.drawImage(bitmap, Math.floor(offset - this.blurDistance/2), 0, bitmap.width + this.blurDistance, bitmap.height); } else { - for(var i=-1; i<=1; i+= this.blurDelta) { + for(let i=-1; i<=1; i+= this.blurDelta) { this.context.drawImage(bitmap, Math.floor(this.blurDistance * i) + offset, 0); } } @@ -177,7 +177,7 @@ HuesCanvas.prototype.redraw = function() { this.context.drawImage(bitmap, offset, Math.floor(-this.blurDistance/2), bitmap.width, bitmap.height + this.blurDistance); } else { - for(var i=-1; i<=1; i+= this.blurDelta) { + for(let i=-1; i<=1; i+= this.blurDelta) { this.context.drawImage(bitmap, offset, Math.floor(this.blurDistance * i)); } } @@ -203,8 +203,8 @@ HuesCanvas.prototype.redraw = function() { }); var invert = !baseInvert; - for(var i = 0; i < 2; i++) { - if(this.trippyRadii[i] == 0) { + for(let i = 0; i < 2; i++) { + if(this.trippyRadii[i] === 0) { continue; } // Invert for each subsequent draw @@ -241,7 +241,7 @@ HuesCanvas.prototype.intToHex = function(num) { HuesCanvas.prototype.animationLoop = function() { if (this.colourFade) { - var delta = this.audio.currentTime - this.colourFadeStart; + let delta = this.audio.currentTime - this.colourFadeStart; var fadeVal = delta / this.colourFadeLength; if (fadeVal >= 1) { this.stopFade(); @@ -273,7 +273,7 @@ HuesCanvas.prototype.animationLoop = function() { } if(this.blurStart) { // flash offsets blur gen by a frame - var delta = this.audio.currentTime - this.blurStart + (1/30); + let delta = this.audio.currentTime - this.blurStart + (1/30); this.blurDistance = this.blurAmount * Math.exp(-this.blurDecay * delta); // Update UI @@ -284,7 +284,7 @@ HuesCanvas.prototype.animationLoop = function() { this.core.blurUpdated(0, dist); } if(this.trippyOn && (this.trippyStart[0] || this.trippyStart[1])) { - for(var i = 0; i < 2; i++) { + for(let i = 0; i < 2; i++) { this.trippyRadii[i] = Math.floor((this.audio.currentTime - this.trippyStart[i]) * this.trippyRadius) * 2; if(this.trippyRadii[i] > this.trippyRadius) { this.trippyStart[i] = 0; @@ -292,7 +292,7 @@ HuesCanvas.prototype.animationLoop = function() { continue; } // x comes from outside the window - if(i % 2 == 0) { + if(i % 2 === 0) { this.trippyRadii[i] = this.trippyRadius - this.trippyRadii[i]; } } @@ -490,7 +490,7 @@ HuesCanvas.prototype.startSnow = function() { var width = this.canvas.width; this.snowAngle = 0; this.snowflakes = []; - for(var i = 0; i < this.maxSnow; i++) { + for(let i = 0; i < this.maxSnow; i++) { this.snowflakes.push({ x: Math.random()*width, //x-coordinate y: Math.random()*height, //y-coordinate @@ -514,16 +514,16 @@ HuesCanvas.prototype.drawSnow = function() { this.snowContext.fillStyle = "rgba(255, 255, 255, 0.8)"; this.snowContext.beginPath(); - for(var i = 0; i < this.maxSnow; i++) { - var flake = this.snowflakes[i]; + for(let i = 0; i < this.maxSnow; i++) { + let flake = this.snowflakes[i]; this.snowContext.moveTo(flake.x, flake.y); this.snowContext.arc(flake.x, flake.y, flake.r, 0, Math.PI * 2, true); } this.snowContext.fill(); this.snowAngle += delta / 6; - for(var i = 0; i < this.maxSnow; i++) { - var flake = this.snowflakes[i]; + for(let i = 0; i < this.maxSnow; i++) { + let flake = this.snowflakes[i]; //Updating X and Y coordinates //We will add 1 to the cos function to prevent negative values which will lead flakes to move upwards //Every particle has its own density which can be used to make the downward movement different for each flake diff --git a/src/js/HuesCore.js b/src/js/HuesCore.js index dd4bd50..67fec10 100644 --- a/src/js/HuesCore.js +++ b/src/js/HuesCore.js @@ -194,8 +194,8 @@ function HuesCore(defaults) { return true; } // If we've focused a text input, let the input go through! - if((e.target.tagName.toLowerCase() == "input" && e.target.type == "text") - || e.target.contentEditable === "true") { + if((e.target.tagName.toLowerCase() == "input" && e.target.type == "text") || + e.target.contentEditable === "true") { return true; } var key = e.keyCode || e.which; @@ -208,7 +208,7 @@ HuesCore.prototype.callEventListeners = function(ev) { this.eventListeners[ev].forEach(function(callback) { callback.apply(null, args); }); -} +}; HuesCore.prototype.addEventListener = function(ev, callback) { ev = ev.toLowerCase(); @@ -232,7 +232,7 @@ HuesCore.prototype.removeEventListener = function(ev, callback) { HuesCore.prototype.resizeVisualiser = function() { this.soundManager.initVisualiser(this.visualiser.width/2); -} +}; HuesCore.prototype.updateVisualiser = function() { if(localStorage["visualiser"] != "on") { @@ -258,7 +258,7 @@ HuesCore.prototype.updateVisualiser = function() { var vals = logArrays[a]; for(var i = 0; i < vals.length; i++) { var index = 0; - if(logArrays.length == 2 && a == 0) { + if(logArrays.length == 2 && a === 0) { index = vals.length - i - 1; } else { index = i; @@ -270,7 +270,7 @@ HuesCore.prototype.updateVisualiser = function() { x += barWidth; } } -} +}; HuesCore.prototype.animationLoop = function() { requestAnimationFrame(this.animationLoop.bind(this)); @@ -314,7 +314,7 @@ HuesCore.prototype.recalcBeatIndex = function() { mapSoFar = build + rhythm.slice(0, this.beatIndex); } // If there's an odd amount of inverts thus far, invert our display - var invertCount = (mapSoFar.match(/i|I/g)||[]).length + var invertCount = (mapSoFar.match(/i|I/g)||[]).length; this.setInvert(invertCount % 2); }; @@ -370,7 +370,7 @@ HuesCore.prototype.setSongOject = function(song) { return this.setSong(i); } } -} +}; HuesCore.prototype.setSong = function(index) { if(this.currentSong == this.resourceManager.enabledSongs[index]) { @@ -419,7 +419,7 @@ HuesCore.prototype.updateBeatLength = function() { } else { this.buildLength = -1; } -} +}; HuesCore.prototype.getBeatLength = function() { if(this.beatIndex < 0) { @@ -427,7 +427,7 @@ HuesCore.prototype.getBeatLength = function() { } else { return this.loopLength; } -} +}; HuesCore.prototype.fillBuildup = function() { // update loop length for flash style filling @@ -445,8 +445,8 @@ HuesCore.prototype.fillBuildup = function() { while (this.currentSong.buildupRhythm.length < buildBeats) { this.currentSong.buildupRhythm = this.currentSong.buildupRhythm + "."; } + console.log("Buildup length:", buildBeats); } - console.log("Buildup length:", buildBeats); } // update with a buildup of possibly different length this.updateBeatLength(); @@ -477,7 +477,7 @@ HuesCore.prototype.loopCheck = function() { if(Math.floor(this.soundManager.currentTime() / this.soundManager.loopLength) > this.loopCount) { this.onLoop(); } -} +}; HuesCore.prototype.onLoop = function() { this.loopCount++; @@ -495,7 +495,7 @@ HuesCore.prototype.onLoop = function() { } break; } -} +}; HuesCore.prototype.doAutoSong = function() { var func = null; @@ -511,7 +511,7 @@ HuesCore.prototype.doAutoSong = function() { } else { func.call(this); } -} +}; HuesCore.prototype.songDataUpdated = function() { if (this.currentSong) { @@ -632,7 +632,7 @@ HuesCore.prototype.beater = function(beat) { this.renderer.doXBlur(); this.renderer.doBlackout(); break; - case '¤': + case '¤': this.renderer.doXBlur(); this.renderer.doBlackout(true); break; @@ -677,7 +677,7 @@ HuesCore.prototype.beater = function(beat) { this.toggleInvert(); break; } - if ([".", "+", "|", "¤"].indexOf(beat) == -1) { + if ([".", "+", "|", "¤"].indexOf(beat) == -1) { this.renderer.clearBlackout(); } if([".", "+", ":", "*", "X", "O", "~", "=", "i", "I"].indexOf(beat) == -1) { @@ -729,11 +729,11 @@ HuesCore.prototype.setInvert = function(invert) { document.documentElement.style.webkitFilter = ""; } this.callEventListeners("invert", invert); -} +}; HuesCore.prototype.toggleInvert = function() { this.setInvert(!this.invert); -} +}; HuesCore.prototype.respackLoaded = function() { this.init(); diff --git a/src/js/HuesEditor.js b/src/js/HuesEditor.js index 6fd8e6d..ad8bf51 100644 --- a/src/js/HuesEditor.js +++ b/src/js/HuesEditor.js @@ -133,7 +133,7 @@ HuesEditor.prototype.resize = function(noHilightCalc) { this.waveCanvas.width = this.waveCanvas.clientWidth; } -} +}; HuesEditor.prototype.createTextInput = function(label, id, subtitle, parent) { var div = document.createElement("div"); @@ -155,7 +155,7 @@ HuesEditor.prototype.createTextInput = function(label, id, subtitle, parent) { parent.appendChild(div); return input; -} +}; HuesEditor.prototype.createButton = function(label, parent, disabled, extraClass) { var button = document.createElement("span"); @@ -169,7 +169,7 @@ HuesEditor.prototype.createButton = function(label, parent, disabled, extraClass button.innerHTML = label.toUpperCase(); parent.appendChild(button); return button; -} +}; HuesEditor.prototype.uiCreateInfo = function() { var info = document.createElement("div"); @@ -185,7 +185,7 @@ HuesEditor.prototype.uiCreateInfo = function() { return; } this.core.callEventListeners("newsong", this.song); - } + }; this.title = this.createTextInput("Title:", "edit-title", "Song name", info); this.title.oninput = songUpdate.bind(this, "title"); @@ -211,7 +211,7 @@ HuesEditor.prototype.onNewSong = function(song) { this.loopWave = null; } } -} +}; HuesEditor.prototype.onBeat = function(map, index) { if(!this.song || this.core.currentSong != this.song) { @@ -234,7 +234,7 @@ HuesEditor.prototype.onBeat = function(map, index) { // Not computing width/height here due to Chrome bug editor._hilight.style.left = (offsetX * this.hilightWidth) + "px"; editor._hilight.style.top = (offsetY * this.hilightHeight) + "px"; -} +}; HuesEditor.prototype.reflow = function(editor, map) { if(!map) { // NOTHING TO SEE HERE @@ -257,7 +257,7 @@ HuesEditor.prototype.reflow = function(editor, map) { var regex = new RegExp("(.{" + charsPerLine + "})", "g"); editor._beatmap.innerHTML = map.replace(regex, "$1
"); editor._breakAt = charsPerLine; -} +}; HuesEditor.prototype.loadAudio = function(editor) { if(editor._fileInput.files.length < 1) { @@ -299,7 +299,7 @@ HuesEditor.prototype.loadAudio = function(editor) { console.log(error); alert("Couldn't load song! Is it a LAME encoded MP3?"); }); -} +}; HuesEditor.prototype.removeAudio = function(editor) { if(!this.song) { @@ -319,7 +319,7 @@ HuesEditor.prototype.removeAudio = function(editor) { this.core.soundManager.stop(); this.updateWaveform(); } -} +}; HuesEditor.prototype.blobToArrayBuffer = function(blob) { return new Promise((resolve, reject) => { @@ -332,7 +332,7 @@ HuesEditor.prototype.blobToArrayBuffer = function(blob) { }; fr.readAsArrayBuffer(blob); }); -} +}; HuesEditor.prototype.newSong = function(song) { if(!song) { @@ -380,7 +380,7 @@ HuesEditor.prototype.newSong = function(song) { this.linked = true; this.updateInfo(); this.updateWaveform(); -} +}; HuesEditor.prototype.updateInfo = function() { if(!this.linked) { @@ -423,7 +423,7 @@ HuesEditor.prototype.updateInfo = function() { } } } -} +}; HuesEditor.prototype.pushUndo = function(name, editor, oldText, newText) { if(oldText == newText) { @@ -436,18 +436,18 @@ HuesEditor.prototype.pushUndo = function(name, editor, oldText, newText) { this.undoBuffer.pop(); } this.updateUndoUI(); -} +}; HuesEditor.prototype.undo = function() { this.undoRedo(this.undoBuffer, this.redoBuffer); -} +}; HuesEditor.prototype.redo = function() { this.undoRedo(this.redoBuffer, this.undoBuffer); -} +}; HuesEditor.prototype.undoRedo = function(from, to) { - if(from.length == 0 || !this.song) { + if(from.length === 0 || !this.song) { return; } // Remove old data @@ -461,13 +461,13 @@ HuesEditor.prototype.undoRedo = function(from, to) { this.updateHalveDoubleButtons(fromData.editor); this.core.updateBeatLength(); this.core.recalcBeatIndex(); -} +}; HuesEditor.prototype.clearUndoRedo = function() { this.undoBuffer = []; this.redoBuffer = []; this.updateUndoUI(); -} +}; HuesEditor.prototype.updateUndoUI = function() { this.undoBtn.className = "hues-button disabled"; @@ -483,7 +483,7 @@ HuesEditor.prototype.updateUndoUI = function() { this.redoBtn.classList.remove("disabled"); this.redoBtn.onclick = this.redo.bind(this); } -} +}; HuesEditor.prototype.halveBeats = function(editor) { if(!this.song || this.getText(editor).length < 2) { @@ -500,16 +500,16 @@ HuesEditor.prototype.halveBeats = function(editor) { this.song.independentBuild = false; } this.setText(editor, this.song[editor._rhythm].replace(/(.)./g, "$1")); -} +}; HuesEditor.prototype.doubleBeats = function(editor) { - if(!this.song || this.getText(editor).length == 0) { + if(!this.song || this.getText(editor).length === 0) { return; } if(!this.song.independentBuild) { // Double them both var other = editor._rhythm == "rhythm" ? this.buildEdit : this.loopEdit; - if(this.getText(other).length == 0) { + if(this.getText(other).length === 0) { return; } this.song.independentBuild = true; @@ -517,7 +517,7 @@ HuesEditor.prototype.doubleBeats = function(editor) { this.song.independentBuild = false; } this.setText(editor, this.song[editor._rhythm].replace(/(.)/g, "$1.")); -} +}; HuesEditor.prototype.uiCreateImport = function() { var imports = document.createElement("div"); @@ -560,7 +560,7 @@ HuesEditor.prototype.uiCreateSongStat = function(name, value, parent) { valueSpan.className = "edit-songstat-value"; container.appendChild(valueSpan); return valueSpan; -} +}; HuesEditor.prototype.uiCreateEditArea = function() { var editArea = document.createElement("div"); @@ -574,7 +574,7 @@ HuesEditor.prototype.uiCreateEditArea = function() { this.timeLock.id = "edit-timelock"; this.timeLock.className = "hues-icon"; // CHAIN, use  for CHAIN-BROKEN - var locker = this.createButton("", this.timeLock) + var locker = this.createButton("", this.timeLock); locker.onclick = () => { if(!this.song) { return; @@ -637,21 +637,21 @@ HuesEditor.prototype.uiCreateEditArea = function() { this.buildEdit._hilight.textContent = "[none]"; this.loopEdit._hilight.innerHTML = - '
\ - Click [LOAD RHYTHM] to load a loop! LAME encoded MP3s work best.
\ - (LAME is important for seamless MP3 loops)
\ -
\ - [DOUBLE] doubles the selected map length by padding it with "."s.
\ - [HALVE] shortens the map length by removing every other character.
\ -
\ - You can also add a buildup with [LOAD BUILDUP], or remove it
\ - with [REMOVE].
\ -
\ - [NEW SONG] adds a completely empty song for you to edit, and
\ - [EDIT CURRENT SONG] takes the current playing song to the editor.
\ -
\ - [COPY/SAVE XML] allow for storing the rhythms and easy
\ - inclusion into a Resource Pack!'; + '
' + + 'Click [LOAD RHYTHM] to load a loop! LAME encoded MP3s work best.
' + + '(LAME is important for seamless MP3 loops)
' + + '
' + + '[DOUBLE] doubles the selected map length by padding it with "."s.
' + + '[HALVE] shortens the map length by removing every other character.
' + + '
' + + 'You can also add a buildup with [LOAD BUILDUP], or remove it
' + + 'with [REMOVE].
' + + '
' + + '[NEW SONG] adds a completely empty song for you to edit, and
' + + '[EDIT CURRENT SONG] takes the current playing song to the editor.
' + + '
' + + '[COPY/SAVE XML] allow for storing the rhythms and easy
' + + 'inclusion into a Resource Pack!'; }; HuesEditor.prototype.uiCreateSingleEditor = function(title, soundName, rhythmName, id, parent) { @@ -690,9 +690,9 @@ HuesEditor.prototype.uiCreateSingleEditor = function(title, soundName, rhythmNam header.appendChild(rightHeader); container._halveBtn = this.createButton("Halve", rightHeader); - container._halveBtn.onclick = this.halveBeats.bind(this, container) + container._halveBtn.onclick = this.halveBeats.bind(this, container); container._doubleBtn = this.createButton("Double", rightHeader); - container._doubleBtn.onclick = this.doubleBeats.bind(this, container) + container._doubleBtn.onclick = this.doubleBeats.bind(this, container); var fileInput = document.createElement("input"); fileInput.type ="file"; @@ -700,7 +700,7 @@ HuesEditor.prototype.uiCreateSingleEditor = function(title, soundName, rhythmNam fileInput.multiple = false; fileInput.onchange = this.loadAudio.bind(this, container); var load = this.createButton("Load " + title.replace(/ /g,""), rightHeader); - load.onclick = () => {fileInput.click()}; + load.onclick = () => {fileInput.click();}; container._removeBtn = this.createButton("Remove", rightHeader, true); container._removeBtn.onclick = this.removeAudio.bind(this, container); @@ -735,7 +735,7 @@ HuesEditor.prototype.uiCreateSingleEditor = function(title, soundName, rhythmNam this.setLocked(container, 0); return container; -} +}; HuesEditor.prototype.rightClick = function(editor, event) { if(!this.linked) { @@ -759,7 +759,7 @@ HuesEditor.prototype.rightClick = function(editor, event) { } else { return true; } -} +}; HuesEditor.prototype.textUpdated = function(editor) { if(!this.song || !this.song[editor._sound]) { @@ -768,11 +768,11 @@ HuesEditor.prototype.textUpdated = function(editor) { } // Space at start of line is nonbreaking, get it with \u00a0 var input = editor._beatmap.textContent.replace(/ |\u00a0/g, ""); - if(input.length == 0) { + if(input.length === 0) { input = "."; } this.setText(editor, input); -} +}; HuesEditor.prototype.getText = function(editor) { if(!this.song || !this.song[editor._rhythm]) { @@ -792,7 +792,7 @@ HuesEditor.prototype.setText = function(editor, text, caretFromEnd) { caret = Math.min(editor._locked, caret); if(text.length > editor._locked) { // Works for pastes too! Removes the different between sizes from the caret position - text = text.slice(0, caret) + text.slice(caret + (text.length - editor._locked), text.length) + text = text.slice(0, caret) + text.slice(caret + (text.length - editor._locked), text.length); } else { while(text.length < editor._locked) { text += "."; @@ -828,7 +828,7 @@ HuesEditor.prototype.setText = function(editor, text, caretFromEnd) { this.updateHalveDoubleButtons(otherMap); } this.pushUndo(editor._rhythm, editor, this.song[editor._rhythm], text); - this.song[editor._rhythm] = text + this.song[editor._rhythm] = text; this.reflow(editor, this.song[editor._rhythm]); this.setCaret(editor._beatmap, caret); this.updateHalveDoubleButtons(editor); @@ -837,7 +837,7 @@ HuesEditor.prototype.setText = function(editor, text, caretFromEnd) { // We may have to go backwards in time this.core.recalcBeatIndex(); this.updateInfo(); -} +}; HuesEditor.prototype.getCaret = function(editable) { var caret = 0; @@ -846,7 +846,7 @@ HuesEditor.prototype.getCaret = function(editable) { var range = sel.getRangeAt(0); //
elements are empty, and pastes do weird things. // So don't go up in multiples of 2 for getCaret - for(var i = 0; i < editable.childNodes.length; i++) { + for(let i = 0; i < editable.childNodes.length; i++) { if (range.commonAncestorContainer == editable.childNodes[i]) { caret += range.endOffset; return caret; @@ -856,13 +856,13 @@ HuesEditor.prototype.getCaret = function(editable) { } } return 0; -} +}; HuesEditor.prototype.setCaret = function(editable, caret) { var range = document.createRange(); var sel = window.getSelection(); //
elements mean children go up in multiples of 2 - for(var i = 0; i < editable.childNodes.length; i+= 2) { + for(let i = 0; i < editable.childNodes.length; i+= 2) { var textLen = editable.childNodes[i].textContent.length; if(caret > textLen) { caret -= textLen; @@ -874,7 +874,7 @@ HuesEditor.prototype.setCaret = function(editable, caret) { break; } } -} +}; HuesEditor.prototype.updateHalveDoubleButtons = function(editor) { editor._halveBtn.className = "hues-button disabled"; @@ -889,7 +889,7 @@ HuesEditor.prototype.updateHalveDoubleButtons = function(editor) { editor._halveBtn.className = "hues-button"; } } -} +}; HuesEditor.prototype.setLocked = function(editor, locked) { editor._locked = locked; @@ -899,7 +899,7 @@ HuesEditor.prototype.setLocked = function(editor, locked) { editor._lockedBtn.innerHTML = ""; // UNLOCKED } this.updateHalveDoubleButtons(editor); -} +}; HuesEditor.prototype.uiCreateControls = function() { var controls = document.createElement("div"); @@ -913,7 +913,7 @@ HuesEditor.prototype.uiCreateControls = function() { // In case it gets clamped, check var newRate = this.core.soundManager.playbackRate; playRateLab.textContent = newRate.toFixed(2) + "x"; - } + }; var speedControl = document.createElement("div"); controls.appendChild(speedControl); @@ -944,7 +944,7 @@ HuesEditor.prototype.uiCreateControls = function() { wrapAt.type = "text"; wrapAt.oninput = () => { wrapAt.value = wrapAt.value.replace(/\D/g,''); - if(wrapAt.value == "" || wrapAt.value < 1) { + if(wrapAt.value === "" || wrapAt.value < 1) { wrapAt.value = ""; return; } @@ -977,7 +977,7 @@ HuesEditor.prototype.updateWaveform = function() { this.loopWaveBuff = this.core.soundManager.loop; this.loopWave = this.renderWave(this.loopWaveBuff, this.core.soundManager.loopLength); } -} +}; HuesEditor.prototype.renderWave = function(buffer, length) { if(!buffer) { @@ -992,14 +992,14 @@ HuesEditor.prototype.renderWave = function(buffer, length) { var samplesPerPixel = Math.floor(buffer.sampleRate / WAVE_PIXELS_PER_SECOND); var waveData = []; - for(var i = 0; i < buffer.numberOfChannels; i++) { + for(let i = 0; i < buffer.numberOfChannels; i++) { waveData.push(buffer.getChannelData(i)); } // Half pixel offset makes things look crisp var pixel = 0.5; waveContext.strokeStyle = "black"; var halfHeight = WAVE_HEIGHT_PIXELS/2; - for(var i = 0; i < buffer.length; i += samplesPerPixel) { + for(let i = 0; i < buffer.length; i += samplesPerPixel) { var min = 0, max = 0; for(var j = 0; j < samplesPerPixel && i + j < buffer.length; j++) { for(var chan = 0; chan < waveData.length; chan++) { @@ -1019,7 +1019,7 @@ HuesEditor.prototype.renderWave = function(buffer, length) { } return wave; -} +}; HuesEditor.prototype.drawWave = function() { var width = this.waveCanvas.width; @@ -1032,20 +1032,20 @@ HuesEditor.prototype.drawWave = function() { if(this.buildWave && minTime < 0) { var bLen = this.core.soundManager.buildLength; - var center = Math.floor((now + bLen) / bLen * this.buildWave.width); + let center = Math.floor((now + bLen) / bLen * this.buildWave.width); this.drawOneWave(this.buildWave, center, width); } if(this.loopWave && maxTime > 0) { var loopLen = this.core.soundManager.loopLength; var clampedNow = (minTime % loopLen) + span; - var center = Math.floor(clampedNow / loopLen * this.loopWave.width); + let center = Math.floor(clampedNow / loopLen * this.loopWave.width); this.drawOneWave(this.loopWave, center, width); var clampedNext = (maxTime % loopLen) - span; // We've looped and need to draw 2 things if(clampedNext < clampedNow) { - var center = Math.floor(clampedNext / loopLen * this.loopWave.width); + let center = Math.floor(clampedNext / loopLen * this.loopWave.width); this.drawOneWave(this.loopWave, center, width); } } @@ -1056,7 +1056,7 @@ HuesEditor.prototype.drawWave = function() { this.waveContext.moveTo(width/2, 0); this.waveContext.lineTo(width/2, WAVE_HEIGHT_PIXELS); this.waveContext.stroke(); -} +}; HuesEditor.prototype.drawOneWave = function(wave, center, width) { this.waveContext.drawImage(wave, @@ -1064,7 +1064,7 @@ HuesEditor.prototype.drawOneWave = function(wave, center, width) { width, WAVE_HEIGHT_PIXELS, // source width/height 0, 0, // dest x/y width, WAVE_HEIGHT_PIXELS); // dest width/height -} +}; HuesEditor.prototype.generateXML = function() { if(!this.song) { @@ -1087,7 +1087,7 @@ HuesEditor.prototype.generateXML = function() { } result += " \n"; return result; -} +}; HuesEditor.prototype.saveXML = function() { var xml = this.generateXML(); @@ -1109,7 +1109,7 @@ HuesEditor.prototype.saveXML = function() { element.click(); document.body.removeChild(element); -} +}; // http://stackoverflow.com/a/30810322 HuesEditor.prototype.copyXML = function() { @@ -1143,7 +1143,7 @@ HuesEditor.prototype.copyXML = function() { } else { alert("Copy failed! Try saving instead"); } -} +}; window.HuesEditor = HuesEditor; diff --git a/src/js/HuesInfo.js b/src/js/HuesInfo.js index 81b69fc..70d61a3 100644 --- a/src/js/HuesInfo.js +++ b/src/js/HuesInfo.js @@ -1,4 +1,4 @@ -/* Copyright (c) 2015 William Toohey +/* Copyright (c) 2015 William Toohey * Portions Copyright (c) 2015 Calvin Walton * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -78,7 +78,7 @@ function populateHuesInfo(version) { addInfo("Beat glossary", beatGlossary); addInfo("Keyboard shortcuts", shortcuts); -}; +} var addInfo = function(titleText, list) { var refElem = document.getElementById(huesInfo.referenceID); diff --git a/src/js/HuesSettings.js b/src/js/HuesSettings.js index a1018d5..a5fa5fa 100644 --- a/src/js/HuesSettings.js +++ b/src/js/HuesSettings.js @@ -172,6 +172,7 @@ HuesSettings.prototype.settingsOptions = { ret = "min"; break; case "off": + /* falls through */ default: return ""; } @@ -238,17 +239,19 @@ function HuesSettings(defaults) { // because we still care about the main window document.getElementById("closeButton").onclick = this.hide.bind(this); + // we also care about tabs looking nice. + var checkListener = function() { + for(let i = 0; i < tabs.length; i++) { + tabs[i].className = "tab-label"; + } + this._label.className = "tab-label checked"; + }; var tabs = document.getElementsByClassName("tab-label"); - for(var i = 0; i < tabs.length; i++) { + for(let i = 0; i < tabs.length; i++) { var check = document.getElementById(tabs[i].htmlFor); check._label = tabs[i]; - check.addEventListener("change", function() { // Uses 'this' of check! - for(var i = 0; i < tabs.length; i++) { - tabs[i].className = "tab-label"; - } - this._label.className = "tab-label checked"; - }); + check.addEventListener("change", checkListener); } if(!this.defaults.noUI) { this.initUI(); @@ -304,6 +307,18 @@ HuesSettings.prototype.showInfo = function() { HuesSettings.prototype.initUI = function() { var doc = this.root.ownerDocument; + + // Don't make in every loop + var intValidator = function(self, variable) { + this.value = this.value.replace(/\D/g,''); + if(this.value === "" || this.value < 1) { + this.value = ""; + return; + } + localStorage[variable] = this.value; + self.updateConditionals(); + self.core.settingsUpdated(); + }; // To order things nicely for(var cat in this.settingsCategories) { @@ -312,7 +327,7 @@ HuesSettings.prototype.initUI = function() { catContainer.textContent = cat; catContainer.className = "settings-category"; var cats = this.settingsCategories[cat]; - for(var i = 0; i < cats.length; i++) { + for(let i = 0; i < cats.length; i++) { var setName = cats[i]; var setContainer = doc.createElement("div"); var setting = this.settingsOptions[setName]; @@ -320,6 +335,7 @@ HuesSettings.prototype.initUI = function() { setContainer.className = "settings-individual"; var buttonContainer = doc.createElement("div"); buttonContainer.className = "settings-buttons"; + for(var j = 0; j < setting.options.length; j++) { var option = setting.options[j]; if(typeof option === "string") { @@ -355,16 +371,7 @@ HuesSettings.prototype.initUI = function() { input.value = localStorage[option.variable]; // TODO: support more than just positive ints when the need arises if(option.inputType == "int") { - input.oninput = (function(self, variable) { - this.value = this.value.replace(/\D/g,''); - if(this.value == "" || this.value < 1) { - this.value = ""; - return; - } - localStorage[variable] = this.value; - self.updateConditionals(); - self.core.settingsUpdated(); - }.bind(input, this, option.variable)); + input.oninput = intValidator.bind(input, this, option.variable); } input.autofocus = false; buttonContainer.appendChild(input); @@ -405,15 +412,15 @@ HuesSettings.prototype.set = function(setting, value) { HuesSettings.prototype.updateConditionals = function() { // update any conditionally formatted settings text - for(var i = 0; i < this.textCallbacks.length; i++) { + for(let i = 0; i < this.textCallbacks.length; i++) { var text = this.textCallbacks[i]; text.element.textContent = text.func(); } - for(var i = 0; i < this.visCallbacks.length; i++) { + for(let i = 0; i < this.visCallbacks.length; i++) { var callback = this.visCallbacks[i]; callback.element.style.visibility = callback.func() ? "visible" : "hidden"; } -} +}; // Note: This is not defaults as per defaultSettings, but those merged with // the defaults given in the initialiser diff --git a/src/js/HuesUI.js b/src/js/HuesUI.js index c7d98f2..40f23d3 100644 --- a/src/js/HuesUI.js +++ b/src/js/HuesUI.js @@ -76,7 +76,7 @@ function HuesUI(parent) { HuesUI.prototype.addCoreCallback = function(name, func) { this.callbacks.push({name : name, func : func}); -} +}; HuesUI.prototype.initUI = function() { // Major info, image, song names @@ -1029,7 +1029,7 @@ HalloweenUI.prototype.initUI = function() { this.root.appendChild(this.vignette); this.addCoreCallback("invert", this.invert.bind(this)); -} +}; HalloweenUI.prototype.beat = function(beats, index) { ModernUI.prototype.beat.call(this, beats, index); @@ -1039,7 +1039,7 @@ HalloweenUI.prototype.beat = function(beats, index) { eyes.className = "hues-m-beatcenter hues-h-eyes"; this.beatCenter.appendChild(eyes); } -} +}; HalloweenUI.prototype.invert = function(invert) { if(invert) { @@ -1055,7 +1055,7 @@ HalloweenUI.prototype.connectCore = function(core) { ModernUI.prototype.connectCore.call(this, core); document.getElementById("preloadHelper").classList.add("hues-h-text"); -} +}; HalloweenUI.prototype.disconnect = function() { ModernUI.prototype.disconnect.call(this, core); diff --git a/src/js/ResourceManager.js b/src/js/ResourceManager.js index bcec5bb..3d0e585 100644 --- a/src/js/ResourceManager.js +++ b/src/js/ResourceManager.js @@ -83,17 +83,17 @@ Resources.prototype.addAll = function(urls, progressCallback) { this.progressCallback = progressCallback; this.progressState = Array.apply(null, Array(urls.length)).map(Number.prototype.valueOf,0); } - var r; - var respackPromises = [] - for(var i = 0; i < urls.length; i++) { - r = new Respack(); - ((r) => { - respackPromises.push(r.loadFromURL(urls[i], function(index, progress, pack) { - this.progressState[index] = progress; - this.updateProgress(pack); - }.bind(this, i))); - })(r); + var respackPromises = []; + + var progressFunc = function(index, progress, pack) { + this.progressState[index] = progress; + this.updateProgress(pack); + }; + + for(let i = 0; i < urls.length; i++) { + let r = new Respack(); + respackPromises.push(r.loadFromURL(urls[i], progressFunc.bind(this, i))); } // Start all the promises at once, but add in sequence return respackPromises.reduce((sequence, packPromise) => { @@ -107,7 +107,7 @@ Resources.prototype.addAll = function(urls, progressCallback) { Resources.prototype.updateProgress = function(pack) { var total = 0; - for(var i = 0; i < this.progressState.length; i++) { + for(let i = 0; i < this.progressState.length; i++) { total += this.progressState[i]; } total /= this.progressState.length; @@ -143,7 +143,7 @@ Resources.prototype.rebuildArrays = function() { this.allImages = []; this.allAnimations = []; - for(var i = 0; i < this.resourcePacks.length; i++) { + for(let i = 0; i < this.resourcePacks.length; i++) { this.addResourcesToArrays(this.resourcePacks[i]); } }; @@ -152,19 +152,19 @@ Resources.prototype.rebuildEnabled = function() { this.enabledSongs = []; this.enabledImages = []; - for(var i = 0; i < this.resourcePacks.length; i++) { + for(let i = 0; i < this.resourcePacks.length; i++) { var pack = this.resourcePacks[i]; if (pack.enabled !== true) { continue; } - for(var j = 0; j < pack.songs.length; j++) { - var song = pack.songs[j]; + for(let j = 0; j < pack.songs.length; j++) { + let song = pack.songs[j]; if (song.enabled && this.enabledSongs.indexOf(song) == -1) { this.enabledSongs.push(song); } } - for(var j = 0; j < pack.images.length; j++) { - var image = pack.images[j]; + for(let j = 0; j < pack.images.length; j++) { + let image = pack.images[j]; if (image.enabled && this.enabledImages.indexOf(image) == -1) { this.enabledImages.push(image); } @@ -179,14 +179,14 @@ Resources.prototype.rebuildEnabled = function() { while(imageList.firstElementChild) { imageList.removeChild(imageList.firstElementChild); } - for(var i = 0; i < this.enabledSongs.length; i++) { - var song = this.enabledSongs[i]; + for(let i = 0; i < this.enabledSongs.length; i++) { + let song = this.enabledSongs[i]; this.appendSimpleListItem(song.title, songList, function(index) { this.core.setSong(index); }.bind(this, i)); } - for(var i = 0; i < this.enabledImages.length; i++) { - var image = this.enabledImages[i]; + for(let i = 0; i < this.enabledImages.length; i++) { + let image = this.enabledImages[i]; this.appendSimpleListItem(image.name, imageList, function(index) { this.core.setImage(index); this.core.setIsFullAuto(false); @@ -211,7 +211,7 @@ Resources.prototype.removeAllPacks = function() { Resources.prototype.getSongNames = function() { var names = []; - for(var i = 0; i < this.allSongs.length; i++) { + for(let i = 0; i < this.allSongs.length; i++) { names.push(this.allSongs[i]); } return names; @@ -220,22 +220,19 @@ Resources.prototype.getSongNames = function() { Resources.prototype.loadLocal = function() { console.log("Loading local zip(s)"); - var r; var files = this.fileInput.files; var p = Promise.resolve(); - for(var i = 0; i < files.length; i++) { - r = new Respack(); - // closure required - ((file, r) => { - p = p.then(() => { - return r.loadFromBlob(file, (progress, respack) => { - this.localProgress(progress, respack); - }); - }).then(pack => { - this.addPack(pack); - this.localComplete(); + for(let i = 0; i < files.length; i++) { + let r = new Respack(); + /*jshint -W083 */ + p = p.then(() => { + return r.loadFromBlob(files[i], (progress, respack) => { + this.localProgress(progress, respack); }); - })(files[i], r); + }).then(pack => { + this.addPack(pack); + this.localComplete(); + }); } return p.then(() => { console.log("Local respack parsing complete"); @@ -303,7 +300,7 @@ Resources.prototype.initUI = function() { var loadLocal = document.createElement("div"); loadLocal.className = "hues-button"; loadLocal.textContent = "LOAD ZIPS"; - loadLocal.onclick = () => {this.fileInput.click()}; + loadLocal.onclick = () => {this.fileInput.click();}; buttons.appendChild(loadLocal); buttons.appendChild(loadRemote); this.packsView.loadRemote = loadRemote; @@ -556,7 +553,7 @@ Resources.prototype.selectPack = function(id) { imageList.removeChild(imageList.firstElementChild); } - for(var i = 0; i < pack.songs.length; i++) { + for(let i = 0; i < pack.songs.length; i++) { var song = pack.songs[i]; this.appendListItem("songs", song.title, "song" + i, songList, this.selectResourceCallback(song), @@ -564,7 +561,7 @@ Resources.prototype.selectPack = function(id) { song.enabled); } - for(var i = 0; i < pack.images.length; i++) { + for(let i = 0; i < pack.images.length; i++) { var image = pack.images[i]; this.appendListItem("images", image.name, "image" + i, imageList, this.selectResourceCallback(image), @@ -614,7 +611,7 @@ Resources.prototype.enableAll = function() { var tab = this.getEnabledTabContents(); if(!tab) return; - for(var i = 0; i < tab.arr.length; i++) { + for(let i = 0; i < tab.arr.length; i++) { tab.arr[i].enabled = true; document.getElementById(tab.elName + i).checked = true; } @@ -625,7 +622,7 @@ Resources.prototype.disableAll = function() { var tab = this.getEnabledTabContents(); if(!tab) return; - for(var i = 0; i < tab.arr.length; i++) { + for(let i = 0; i < tab.arr.length; i++) { tab.arr[i].enabled = false; document.getElementById(tab.elName + i).checked = false; } @@ -636,7 +633,7 @@ Resources.prototype.invert = function() { var tab = this.getEnabledTabContents(); if(!tab) return; - for(var i = 0; i < tab.arr.length; i++) { + for(let i = 0; i < tab.arr.length; i++) { tab.arr[i].enabled = !tab.arr[i].enabled; document.getElementById(tab.elName + i).checked = tab.arr[i].enabled; } @@ -697,7 +694,7 @@ Resources.prototype.populateRemotes = function() { while(remoteList.firstElementChild) { remoteList.removeChild(remoteList.firstElementChild); } - for(var i = 0; i < this.remotes.length; i++) { + for(let i = 0; i < this.remotes.length; i++) { this.remotes[i].loaded = false; this.appendSimpleListItem(this.remotes[i].name, remoteList, function(index) { @@ -741,29 +738,29 @@ Resources.prototype.selectRemotePack = function(id) { imageList.removeChild(imageList.firstElementChild); } - for(var i = 0; i < pack.songs.length; i++) { + for(let i = 0; i < pack.songs.length; i++) { var song = pack.songs[i]; this.appendSimpleListItem(song, songList); } var moreSongs = pack.songcount - pack.songs.length; if(moreSongs > 0) { - var text = "... and " + moreSongs + " more song"; + let text = "... and " + moreSongs + " more song"; if(moreSongs > 1) { - text += "s" + text += "s"; } this.appendSimpleListItem(text + ".", songList); this.appendSimpleListItem("Load the respack to show the rest!", songList); } - for(var i = 0; i < pack.images.length; i++) { + for(let i = 0; i < pack.images.length; i++) { var image = pack.images[i]; this.appendSimpleListItem(image, imageList); } var moreImages = pack.imagecount - pack.images.length; if(moreImages > 0) { - var text = "... and " + moreImages + " more image"; + let text = "... and " + moreImages + " more image"; if(moreImages > 1) { - text += "s" + text += "s"; } this.appendSimpleListItem(text + ".", imageList); this.appendSimpleListItem("Load the respack to show the rest!", imageList); diff --git a/src/js/ResourcePack.js b/src/js/ResourcePack.js index 5da7400..798109a 100644 --- a/src/js/ResourcePack.js +++ b/src/js/ResourcePack.js @@ -120,7 +120,7 @@ Respack.prototype.getBlob = function(url, progress) { throw error; } }); -} +}; Respack.prototype.loadFromBlob = function(blob, progress) { if(progress) { @@ -141,7 +141,7 @@ Respack.prototype.loadFromBlob = function(blob, progress) { return this.parseZip(zip); }).then(() => { return this; - });; + }); }; Respack.prototype.parseZip = function(zip) { @@ -257,7 +257,7 @@ Respack.prototype.parseSongQueue = function() { return songPromise; }); }, Promise.resolve()); -} +}; Respack.prototype.parseImage = function(file) { var match; @@ -266,7 +266,7 @@ Respack.prototype.parseImage = function(file) { // Animation if((match = name.match(new RegExp("^(.*)_(\\d+)$")))) { - var img = this.getImage(match[1]); + img = this.getImage(match[1]); if(!img) { // make a fresh one img = {"name":match[1], "fullname":match[1], @@ -282,7 +282,7 @@ Respack.prototype.parseImage = function(file) { } // Normal image } else if (!this.containsImage(name)) { - var img = {"name":name, + img = {"name":name, "fullname":name, "bitmap":null, "align":"center", @@ -342,7 +342,7 @@ Respack.prototype.parseImageQueue = function() { } }); }, Promise.resolve()); -} +}; Respack.prototype.loadXML = function(file) { return new Promise((resolve, reject) => { @@ -353,7 +353,7 @@ Respack.prototype.loadXML = function(file) { resolve(text); }); }); -} +}; Respack.prototype.parseXML = function() { var p = Promise.resolve(); @@ -496,7 +496,7 @@ Respack.prototype.parseImageFile = function(text) { // var imagesXML = oDOM.documentElement.children; var el = oDOM.documentElement.firstElementChild; for(; el; el = el.nextElementSibling) { - var image = this.getImage(el.attributes[0].value); + let image = this.getImage(el.attributes[0].value); if(image) { image.fullname = el.getTag("fullname"); if(!image.fullname) { @@ -532,7 +532,7 @@ Respack.prototype.parseImageFile = function(text) { } } for(var i = 0; i < this.images.length; i++) { - var image = this.images[i]; + let image = this.images[i]; // Add all images with no info if(newImages.indexOf(image) == -1) { newImages.push(image); diff --git a/src/js/SoundManager.js b/src/js/SoundManager.js index b35d7bc..51e765e 100644 --- a/src/js/SoundManager.js +++ b/src/js/SoundManager.js @@ -97,7 +97,7 @@ SoundManager.prototype.init = function() { reject(Error("MP3 Worker cannot be started - correct path set in defaults?")); }, false); mp3Worker.postMessage({ping:true}); - }) + }); }).then(response => { return new Promise((resolve, reject) => { // iOS and other some mobile browsers - unlock the context as @@ -126,11 +126,11 @@ SoundManager.prototype.init = function() { } else { resolve(); } - }) + }); }); } return this.initPromise; -} +}; SoundManager.prototype.playSong = function(song, playBuild, forcePlay) { var p = Promise.resolve(); @@ -167,7 +167,7 @@ SoundManager.prototype.playSong = function(song, playBuild, forcePlay) { this.loopLength = this.loop.duration; // This fixes sync issues on Firefox and slow machines. - return this.context.suspend() + return this.context.suspend(); }).then(() => { if(playBuild) { this.seek(-this.buildLength, true); @@ -212,7 +212,7 @@ SoundManager.prototype.setRate = function(rate) { var time = this.clampedTime(); this.playbackRate = rate; this.seek(time); -} +}; SoundManager.prototype.seek = function(time, noPlayingUpdate) { if(!this.song) { @@ -249,7 +249,7 @@ SoundManager.prototype.seek = function(time, noPlayingUpdate) { } this.initVisualiser(); this.core.recalcBeatIndex(); -} +}; // In seconds, relative to the loop start SoundManager.prototype.currentTime = function() { @@ -266,7 +266,7 @@ SoundManager.prototype.clampedTime = function() { time %= this.loopLength; } return time; -} +}; SoundManager.prototype.displayableTime = function() { var time = this.clampedTime(); @@ -326,17 +326,17 @@ SoundManager.prototype.loadBuffer = function(song, soundName) { // transfer the buffer to save time mp3Worker.postMessage(song[soundName], [song[soundName]]); }); -} +}; // Converts continuous PCM array to Web Audio API friendly format SoundManager.prototype.audioBufFromRaw = function(raw) { - var buffer = raw.array + var buffer = raw.array; var channels = raw.channels; var samples = buffer.length/channels; var audioBuf = this.context.createBuffer(channels, samples, raw.sampleRate); //var audioBuf = this.context.createBuffer(1, buffer.length, raw.sampleRate); //audioBuf.copyToChannel(buffer, 0, 0); - for(var i = 0; i < channels; i++) { + for(let i = 0; i < channels; i++) { //console.log("Making buffer at offset",i*samples,"and length",samples,".Original buffer is",channels,"channels and",buffer.length,"elements"); // Offset is in bytes, length is in elements var channel = new Float32Array(buffer.buffer , i * samples * 4, samples); @@ -357,7 +357,7 @@ SoundManager.prototype.initVisualiser = function(bars) { } this.vReady = false; this.vTotalBars = bars; - for(var i = 0; i < this.analysers.length; i++) { + for(let i = 0; i < this.analysers.length; i++) { this.analysers[i].disconnect(); } if(this.splitter) { @@ -374,7 +374,7 @@ SoundManager.prototype.initVisualiser = function(bars) { this.maxBinLin = 0; this.attachVisualiser(); -} +}; SoundManager.prototype.attachVisualiser = function() { if(!this.playing || this.vReady) { @@ -393,7 +393,7 @@ SoundManager.prototype.attachVisualiser = function() { // Split display up into each channel this.vBars = Math.floor(this.vTotalBars/channels); - for(var i = 0; i < channels; i++) { + for(let i = 0; i < channels; i++) { var analyser = this.context.createAnalyser(); // big fft buffers are new-ish try { @@ -423,22 +423,22 @@ SoundManager.prototype.attachVisualiser = function() { var logLow = Math.log2(2000); var logDiff = Math.log2(22000) - logLow; - for(var i = 0; i < logBins; i++) { + for(let i = 0; i < logBins; i++) { var cutoff = i * (logDiff/logBins) + logLow; var freqCutoff = Math.pow(2, cutoff); var binCutoff = Math.floor(freqCutoff / binWidth); this.binCutoffs.push(binCutoff); } this.vReady = true; -} +}; SoundManager.prototype.sumArray = function(array, low, high) { var total = 0; - for(var i = low; i <= high; i++) { + for(let i = low; i <= high; i++) { total += array[i]; } return total/(high-low+1); -} +}; SoundManager.prototype.getVisualiserData = function() { if(!this.vReady) { @@ -449,19 +449,19 @@ SoundManager.prototype.getVisualiserData = function() { var result = this.logArrays[a]; this.analysers[a].getByteFrequencyData(data); - for(var i = 0; i < this.linBins; i++) { + for(let i = 0; i < this.linBins; i++) { var scaled = Math.round(i * this.maxBinLin / this.linBins); result[i] = data[scaled]; } result[this.linBins] = data[this.binCutoffs[0]]; - for(var i = this.linBins+1; i < this.vBars; i++) { + for(let i = this.linBins+1; i < this.vBars; i++) { var cutoff = i - this.linBins; result[i] = this.sumArray(data, this.binCutoffs[cutoff-1], this.binCutoffs[cutoff]); } } return this.logArrays; -} +}; SoundManager.prototype.setMute = function(mute) { if(!this.mute && mute) { // muting @@ -506,7 +506,7 @@ SoundManager.prototype.fadeOut = function(callback) { this.gainNode.gain.exponentialRampToValueAtTime(0.01, this.context.currentTime + 2); } setTimeout(callback, 2000); -} +}; window.SoundManager = SoundManager;