Drum Machine

Meow meow

by Admiral Potato

HTML

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/css/bulma.min.css">
<script src="https://unpkg.com/bulma-prefers-dark"></script>
<div class="calculator-grid">
        <div class="container">
            <div class="card is-primary">
                <div class="card-content">
                    <div class="field">
                        <div class="control">
                            <h2>World's Greatest</h2>
                            <h1>Drum Machine</h1>                        
                        </div>
                    </div>
                    
                    <div class="columns" id="column-holder">
                        <div class="column" id="column-template">
                            <div class="key">
                                <button class="button">$</button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

CSS

body {
  font-family: 'Karla';
  font-size: 22px;
}

.button,
.input,
.textarea {
  margin-bottom: 1em;
}

.button.is-dark {
  background: linear-gradient(to top, rgba(12, 12, 12, 10), rgba(27, 27, 27, 10), rgba(12, 12, 12, 10));
}

body,
h1,
h2,
button {
  font-family: "Karla", sans-serif;
}

h1 {
  text-align: center;
  font-weight: bold;
  font-size: 2rem;
}

h2 {
  text-align: center;
  font-weight: bold;
}

.card {
  background: linear-gradient(to right, rgb(21, 45, 23), rgb(11, 73, 83), rgb(21, 45, 23));
}

.input,
.textarea {
  background-color: #dbdbdb;
  border-color: #363636;
  color: #0a0a0a;
  box-shadow: inset 0 1px 2px rgb(255 255 255 / 10%);
  max-width: 100%;
  width: 100%;
}

.input,
.select select,
.textarea {
  border-radius: 4px;
}

*,
*::before,
*::after {
  box-sizing: border-box;
  font-family: "Montserrat", sans-serif;
  font-weight: normal;
}

body {
  margin: 0;
  padding: 0;
  background: linear-gradient(to right, rgb(16, 16, 16), rgb(23, 8, 0));
}

.calculator-grid {
  display: grid;
  justify-content: center;
  align-content: center;
  min-height: 100vh;
  grid-template-columns: repeat(4, 100px);
  grid-template-rows: minmax(120px, auto) repeat(5, 100px);
}

.calculator-grid>button {
  cursor: pointer;
  font-size: 2rem;
  border: 1px, solid #FFFFFF;
  outline: none;
  background-color: rbga(255, 255, 255, 0.75);
}

.calculator-grid>button:hover {
  background-color: #a9a9a9;
}

.span-two {
  grid-column: span 2;
  color: #adf802;
  background-color: rgba(139, 0, 139, 0.8);
}

.output {
  grid-column: 1 / -1;
  background-color: rgba(0, 0, 0, 0.75);
  display: flex;
  align-items: flex-end;
  justify-content: space-around;
  flex-direction: column;
  padding: 10px;
  word-wrap: break-word;
  word-break: break-all;
}

.output .previous-operand {
  color: rgba(255, 255, 255, 0.75);
  font-size: 1.5rem;
}

.output .current-operand {
  color: white;
  font-size: 2.5rem;
}

JavaScript

const audioKeyMap = {
  a: new Audio("https://www.fesliyanstudios.com/soundeffects/2019-06-26Farm/Goat-Baby-Bah-A-www.fesliyanstudios.com.mp3"),
  s: new Audio("https://orangefreesounds.com/wp-content/uploads/2022/08/Short-meow-sound-effect.mp3"),
  d: new Audio("https://www.orangefreesounds.com/wp-content/uploads/2022/04/Duckling-sound-effect.mp3")
};

const columnTemplate = document.getElementById('column-template')
const columnHolder = document.getElementById('column-holder')

// remove template ID so none of the spawned instances have ID by default
columnTemplate.id = undefined;

columnHolder.removeChild(columnTemplate);
const myCauldron = document.createElement('div');

const buttonKeyMap = {};

const buildColumnForKey = function (keyString) {
  myCauldron.innerHTML = columnTemplate.outerHTML;
  const column = myCauldron.children[0];
  const button = column.children[0].children[0];
  button.innerText = keyString;
  button.dataset.key = keyString;
  columnHolder.appendChild(column);
  buttonKeyMap[keyString] = button;
  return button;
}

const buttonKeys = Object.keys(audioKeyMap);
buttonKeys.forEach(buildColumnForKey);

const activateSoundByKey = function(key) {
  const audioObject = audioKeyMap[key];
  if (audioObject) {
    const button = buttonKeyMap[key];
    button.classList.add('is-primary'); 
    audioObject.play();
  }
  else {
    console.log('No sound for u.')
  }
}

const deactivateSoundByKey = function(key) {
  const button = buttonKeyMap[key];
  if (button) {
    button.classList.remove('is-primary');
  }
}

document.addEventListener('keydown', function (event) {
  const key = event.key;
  // console.log('What is key?', key);
  activateSoundByKey(key); 
});

document.addEventListener('keyup', function (event) {
  const key = event.key;
  deactivateSoundByKey(key);
});

const mouseDownHandler = function (mouseDownEvent) {
  // console.log('What is the MouseDownEvent?', mouseDownEvent);
  const targetElement = mouseDownEvent.target;
  const key =...