Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent the html details element from toggling when the summary has an embedded text input and user presses space bar

I have a text input within the summary tag of a details element which is in the open state. The intention is to capture user input which will eventually be displayed as a details element (see below). However the details element toggles when the user presses the space bar while entering text. I want to prevent this. I expected that this could be done using stopPropagation in the keypress event but it does not seem to be working. How do I prevent the element from toggling?

window.onload = function() {
  var summary = document.getElementById("x");
  var fn = function(e) {
    e.stopPropagation();
    /*if(e.keyCode == 32){
      e.preventDefault();
      e.target.value += " "
    } */
  };
  summary.onkeypress = fn;
  //summary.onkeydown = fn;
};
<details open>
  <summary><input id="x" type="text" /></summary>
  Some content
</details>

I need to do this within a React component but I'm posting a js/html example here for simplicity.

One alternative is to use preventDefault onkeypress when space is entered and manually concatenate the space char but this seems inelegant

like image 933
vivekraman Avatar asked Apr 23 '18 05:04

vivekraman


2 Answers

You can catch the event on summary object and then preventDefault() will not toggle details element state but also will not block space addition.

window.onload = function() {
  var summary = document.getElementById("x");
  var fn = function(e) {      
    if(e.keyCode == 32){
      e.preventDefault();
    }
  };
  summary.onkeyup = fn;
};
<details open>
  <summary id="x"><input  type="text" /></summary>
  Some content
</details>

Pay attention i moved id="x" to summary instead of input

like image 157
Moti Korets Avatar answered Nov 24 '22 01:11

Moti Korets


Having seen the other answer, unfortunately it appeared it didn't work for me. Instead I used the following (you'll need jQuery for this one):

$("details").on("keyup", function(event) {
    if ($(document.activeElement).is("input") && $(document.activeElement).parent().is("summary") && event.keyCode == 32) {
        if ($(this).attr("open")) {
            $(this).removeAttr("open");
        } else {
            $(this).attr("open", "");
        }
    }
});

When the space key is pressed, the code will detect if you're in an input, and if you are, the open attribute will be toggled (as it was firstly toggled before the event was run, so this creates an effect similar to event.preventDefault(); which doesn't work here) before the screen has a chance to redraw. The space character will of course still show in the input, and the space action will of course be working again when the input is not focused but the summary element is, as to not break accessibility.

The code may need altering (specifically the if on line 2) if you've got an input nested inside something else rather than the summary element, but it shouldn't be too hard to modify.

Also, I have tested the script for accessibility ─ it works well with keyboard-only navigation, and of course with ChromeVox too (the readouts make sense, as well as with the keyboard).

like image 25
James Livesey Avatar answered Nov 23 '22 23:11

James Livesey