Search code examples
javascripttwitter-bootstrap-3modal-dialogkeypresscontenteditable

Returning focus, contenteditable misses keypress event


Story

In a custom content editor component (contenteditable div), in which I need to prevent certain character inputs. If the user tries to input a restricted character, a bootstrap modal dialog is shown explaining the restriciton ("You are not allowed to use 'x') and the event is prevented (preventDefault). After dismissing the dialog, the focus goes back to the contenteditable and input can resume.

Issue/Bug?

After dismissing the dialog, the focus is indeed returned to the contenteditable. However, the first key event doesn't trigger keypress on the contenteditable bypassing the keypress event listener.

I tried setting manually the focus and setting the document selection explicitly on the contenteditable, with no luck. I've tried both with jquery and pure js.

Any ideas why is the first event bypassing the keypress listener?

Illustration

JSFiddle here, example restricting "." input:

<div id="testMe" contenteditable="true" class="form-control"></div>

<div id="myModal" class="modal fade">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-body">
          <p> You are not allowed to use this character.</p>
          <p> Press OK to dismiss.</p>
      </div>
      <div class="modal-footer">
        <button id="closeAlert" type="button" class="btn btn-danger">OK</button>
      </div>
    </div>
  </div>
</div>


$("#testMe").keypress(function(event) {
    console.log("key pressed");
    if (String.fromCharCode(event.which) == ".") {
        event.preventDefault();
        $('#myModal').modal('show');
    }
});


$("#closeAlert").click(function() {
    $('#myModal').modal('hide');
});
  1. Click inside the contenteditable
  2. Press "." character (no input appears and a "keypress" message is printed to the console).
  3. Dismiss the dialog
  4. Press "." character again (the input appears and no keypresssmessage appears in the console log).

Solution

  • It turns out that the problem was in setting back the focus of the element. Adding

    $("#testMe").focus();
    

    after hiding the modal fixes it.

    I had originally used the bootbox library for showing modals. For unclear reasons, setting focus immediately after the dialog close callback doesn't work with it.