Last active
April 2, 2017 21:06
-
-
Save jbrains/4dbb425486fc4dcb14285d00c4d65016 to your computer and use it in GitHub Desktop.
Finding functional/reusable bits in a small amount of Javascript. Especially trying to push details up the call stack.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>JS Drum Kit</title> | |
<link rel="stylesheet" href="style.css"> | |
</head> | |
<body> | |
<div class="keys"> | |
<div data-key="65" class="key"> | |
<kbd>A</kbd> | |
<span class="sound">clap</span> | |
</div> | |
<div data-key="83" class="key"> | |
<kbd>S</kbd> | |
<span class="sound">hihat</span> | |
</div> | |
<div data-key="68" class="key"> | |
<kbd>D</kbd> | |
<span class="sound">kick</span> | |
</div> | |
<div data-key="70" class="key"> | |
<kbd>F</kbd> | |
<span class="sound">openhat</span> | |
</div> | |
<div data-key="71" class="key"> | |
<kbd>G</kbd> | |
<span class="sound">boom</span> | |
</div> | |
<div data-key="72" class="key"> | |
<kbd>H</kbd> | |
<span class="sound">ride</span> | |
</div> | |
<div data-key="74" class="key"> | |
<kbd>J</kbd> | |
<span class="sound">snare</span> | |
</div> | |
<div data-key="75" class="key"> | |
<kbd>K</kbd> | |
<span class="sound">tom</span> | |
</div> | |
<div data-key="76" class="key"> | |
<kbd>L</kbd> | |
<span class="sound">tink</span> | |
</div> | |
</div> | |
<section id="drum-sounds"> | |
<audio data-key="65" src="sounds/clap.wav"></audio> | |
<audio data-key="83" src="sounds/hihat.wav"></audio> | |
<audio data-key="68" src="sounds/kick.wav"></audio> | |
<audio data-key="70" src="sounds/openhat.wav"></audio> | |
<audio data-key="71" src="sounds/boom.wav"></audio> | |
<audio data-key="72" src="sounds/ride.wav"></audio> | |
<audio data-key="74" src="sounds/snare.wav"></audio> | |
<audio data-key="75" src="sounds/tom.wav"></audio> | |
<audio data-key="76" src="sounds/tink.wav"></audio> | |
</section> | |
<script> | |
// Generic Javascript | |
function applySafely(f, x) { | |
return (x ? f.call(null, x) : null); | |
} | |
// Generic DOM manipulation | |
// CONTRACT: turnElementOn and turnElementOff are functions of a DOM element | |
// ASSUMES that domElement generates a transition event when it is turned on | |
function pulseUiElement(domElement, turnElementOn, turnElementOff) { | |
// ASSUMES that the DOM event's target is the receiver of addEventListener() | |
domElement.addEventListener('transitionend', event => turnElementOff.call(null, event.target)); | |
turnElementOn.call(null, domElement); | |
} | |
// Generic HTML element behavior | |
// "rewind" means "prepare the audio element to play again" | |
// CONTRACT: audioElement is an <audio> element, so it can be rewound and played | |
function rewindThenPlay(audioElement) { | |
audioElement.currentTime = 0; | |
audioElement.play(); | |
} | |
// Specific to this document | |
// CONTRACT: I can change the CSS class on domElement | |
function markUiElementPlaying(domElement) { | |
domElement.classList.add("playing"); | |
} | |
function markUiElementNotPlaying(domElement) { | |
domElement.classList.remove("playing"); | |
} | |
function pulseUiElementPlaying(domElement) { | |
pulseUiElement(domElement, markUiElementPlaying, markUiElementNotPlaying); | |
} | |
function playSoundAndPulseUi(domElement, soundKeyCode) { | |
const audioElement = domElement.querySelector(`audio[data-key="${soundKeyCode}"]`); | |
applySafely(rewindThenPlay, audioElement); | |
const keyUiElement = domElement.querySelector(`.key[data-key="${soundKeyCode}"]`); | |
applySafely(pulseUiElementPlaying, keyUiElement); | |
} | |
window.addEventListener('keydown', event => playSoundAndPulseUi(document, event.keyCode)); | |
</script> | |
</body> | |
</html> |
$ gloga
* 43da0e7 (HEAD -> jbrains) We now declare functions with a syntax that @hughrawlinson told me provides better stack traces.
[...]
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks, @hughrawlinson! I'm just throwing everything into global scope for now, because I'm (re)learning more basic language constructs and gradually (re)discovering the DOM API. I don't think I'll get to multiple modules for a while. When it becomes "too easy", then I'll add that constraint.
I didn't know about the difference in declaring functions. Thanks.
As for the transition events, I worry a little about spreading around the assumption of which things fire transition events, but I'll live with it for the moment. I'll let myself stumble upon that as I go. :)