dustin
dustin

Reputation: 135

Use Javascript onclick or keydown for event

I'm using JavaScript and CSS to create keys that flips and play a sound. On the front side there is an image then when the key is pressed, it plays a sound and flips to revels the back which displays a different img and flips back over after the key is released. The code works for that purpose, but I want the same functionality for when someone also clicks the key. Can I have both?

function removeTransition(e) {
    if (e.propertyName !== 'transform') return;
    e.target.classList.remove('playing');
  }

  function playSound(e) {
    const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
    const key = document.querySelector(`div[data-key="${e.keyCode}"]`);
    if (!audio) return;

    key.classList.add('playing');
    audio.currentTime = 0;
    audio.play();
  }

  const keys = Array.from(document.querySelectorAll('.key'));
  keys.forEach(key => key.addEventListener('transitionend', removeTransition));
  window.addEventListener('keydown', playSound); 

Upvotes: 1

Views: 4145

Answers (2)

Titus
Titus

Reputation: 22474

Yes, you can have both, you can do something like this:

function removeTransition(e) {
  if (e.propertyName !== 'transform') return;
  e.target.classList.remove('playing');
}

function playSound(e) {
  let keyCode;
  if (e.type === 'click') {
    keyCode = e.currentTarget.dataset.key;
  } else {
    keyCode = e.keyCode;
  }

  const audio = document.querySelector(`audio[data-key="${keyCode}"]`);
  const key = document.querySelector(`div[data-key="${keyCode}"]`);
  if (!audio) return;

  key.classList.add('playing');
  audio.currentTime = 0;
  audio.play();
}

const keys = Array.from(document.querySelectorAll('.key'));
keys.forEach(key => key.addEventListener('transitionend', removeTransition));
window.addEventListener('keydown', playSound);
keys.forEach(key => key.addEventListener('click', playSound))

I've used event.type to determine if the event is a click or a keydown and used element.dataset to retrieve the appropriate key in case of click events (these events don't have the keyCode property).

Also, in case of click events, event.target is actually the clicked key, you can use that instead of looking for the key in the DOM (the querySelector(`div[data-key="${keyCode}"]`) call).

Upvotes: 3

Veggiebob
Veggiebob

Reputation: 11

Yes, as far as I am concerned, you can have as many event listeners per object as you want. Just use the relevant event listeners and attach them to the relevant HTML objects. Remember, in Javascript you need an event listener for each event. For example: (from https://gomakethings.com/listening-to-multiple-events-in-vanilla-js/)

This doesn't work:

document.addEventListener('click mouseover', function (event) {
    // this doesn't work
}, false);

Instead, you'll have to do something like this:

var someFunction = function (event) {
    // Do something...
};

// Add our event listeners
window.addEventListener('click', someFunction, false);
window.addEventListener('mouseover', someFunction, false);

Upvotes: 0

Related Questions