user15202517
user15202517

Reputation:

JavaScript addEventListener click and keycode


I want keycode and mouse click to work all the time. Independently of each other, it will click on the button when I press the "space" button and when I click the mouse, it will click on the button.

let testKey = document.querySelector(".switch-btn");

["click", "keypress"].forEach(ev => {
    testKey.addEventListener(ev, function(e) {
        if(ev == "click") {
            console.log("click");
            if(!testKey.classList.contains("slide")) {
                testKey.classList.add("slide");

            } else {

            }

        }
        if(e.keyCode === 32) {
            console.log("click, space");
        }
    });
});
    <button class="switch-btn">
      <span>
        Play
      </span>
      <span>
        pause
      </span>
      <span class="switch"></span>
    </button> 

Upvotes: 0

Views: 2430

Answers (2)

Dan Nagle
Dan Nagle

Reputation: 5425

The keypress event is deprecated and no longer recommended (See Document: keypress event documentation). Instead you can use the keydown event.

If your intention is to handle the click and keydown events separately then you should check the detail property for the click event handler. If the button is clicked the property will have a value of 1. (See UIEvent.detail documentation)

Unless the user focuses on the button using the tab key, the keydown event is not going to fire your handler. Adding a handler at the container or document level can overcome this. In the code below I have added such a handler and called the stopPropagation method within the handler on the button to prevent the event bubbling up to the document level.

let testKey = document.querySelector(".switch-btn");

document.addEventListener('keydown', function(e) {
    if(e.keyCode === 32) {
        console.log("document: space pressed");
        doTheClassListThing();
    }
});

["click", "keydown"].forEach(ev => {
    testKey.addEventListener(ev, function(e) {
        if(ev == "click" & e.detail == 1) {
            console.log("click");
            doTheClassListThing();
        }
        if(e.keyCode === 32) {
            e.stopPropagation();
            console.log("Button: space keydown");
            doTheClassListThing();
        }
    });
});

function doTheClassListThing() {
    console.log('doTheClassListThing() executed');
    if(!testKey.classList.contains("slide")) {
        testKey.classList.add("slide");
    } else {
    }
}
    <button class="switch-btn">
      <span>
        Play
      </span>
      <span>
        pause
      </span>
      <span class="switch"></span>
    </button> 

Upvotes: 1

ray
ray

Reputation: 27245

I'm not sure I understand the question, but the reason the key doesn't register initially is because the button isn't focused. You could try calling testKey.focus() to ensure it's initially focused.

I do not recommend this approach--forcing focus on the button could create accessibility issues and interfere with other element interactions, but here's a snippet just to demonstrate how focusing the button resolves the issue.

I agree with Terry's comment below, that attaching event handlers on body would be less fraught.

let testKey = document.querySelector(".switch-btn");

testKey.focus();

["click", "keypress"].forEach(ev => {
    testKey.addEventListener(ev, function(e) {
        if(ev == "click") {
            console.log("click");
            if(!testKey.classList.contains("slide")) {
                testKey.classList.add("slide");

            } else {

            }

        }
        if(e.keyCode === 32) {
            console.log("click, space");
        }
        testKey.focus();
    });
});
<button class="switch-btn">
      <span>
        Play
      </span>
      <span>
        pause
      </span>
      <span class="switch"></span>
    </button>

Upvotes: 0

Related Questions