-1

So i am using a <span> with contenteditable="true". onkeydown generates new elements with the key pressed as text. I use preventDefault() to not show the pressed character in the input field. If "backspace" is pressed, the last new element ist deleted.

It works really well on desktop browsers, but it has an issue on mobile. When testing firefox for android, if I type some letters and then press backspace, none of the events are triggered in js. The virtual keyboard (default and swiftkey tested) somehow keep the last letters and only remove them within the keyboard - only after these are all gone the events get passed to js again.

It is not easy to describe - the scribble shows it. The problem only exists on mobile!!

Resetting the "contenteditable" attribute prevents this behaviour but it also flashes the keyboard, which is not ideal.

//EDIT: fiddle is updated: catching 229, reset caret position, reset input content to " "

let editableSpan = document.querySelector('#inp');

editableSpan.onkeydown = function(e){
    console.log('key pressed', e.which, e.key);
    if(e.key === 'Backspace' || e.key === 'Process'){
    var keyEls = document.querySelectorAll('#out .kbd');
    keyEls.length > 0 && keyEls[keyEls.length - 1].remove();
  }else if(e.key.length === 1){
    var keyEl = document.createElement('span');
    keyEl.classList.add('kbd');
    keyEl.textContent = e.key;
    document.querySelector('#out').append(keyEl);
  }
  e.preventDefault();
}

editableSpan.onkeyup = function(e){
  var letterInp = document.querySelector('#inp');
  var selection = window.getSelection();
  var range     = document.createRange();
  letterInp.innerHTML = '&nbsp;';
  range.setStart(letterInp, letterInp.childNodes.length);
  range.collapse(true);
  selection.removeAllRanges();
  selection.addRange(range);
}
#inp {
  background-color: goldenrod;
  border: solid 3px black;
}
.kbd {
  display:inline-block;
  background-color:darkgrey;
  font-size: 2em;
  padding: .5em;
  margin-right: .3em;
  margin-top: .3em;
  border-radius:.3em;
  font-style:monospace;
}
<span id="out"></span>
<span class="kbd" id="inp" contenteditable="true">&nbsp;</span>


7
  • Use e.key and not e.which, as it was deprecated... oh, long time ago. Some browsers may still support it, but you cannot rely on it. Please use e.key and tell us if it solves the problem. The e.key value should be "Backspace". Commented Feb 4 at 22:59
  • @Yogi the issue is not related - I am not getting any event trigger on mobile after typing some letters. The answer you suggested gets triggers but expects a different keycode. Commented Feb 5 at 7:30
  • @SergeyAKryukov I edited the snippet but it is not related to the problem Commented Feb 5 at 7:30
  • Since resetting the contenteditable attribute works, you should alert what key was pressed on mobile, cause it is not 'Backspace'. Commented Feb 5 at 7:39
  • @skobaljic every input event is logged - and when pressing backspace after typeing some letters in this situation the events are not triggered Commented Feb 5 at 8:32

1 Answer 1

0

With some pointers from @Yogi I got a working solution.

issue 1: no events fired in js - only happens when caret is placed before "space" -> always set caret position to end of element

issue 2: key=229 is returned in keydown -> handle it the same as backspace and reset the inputs content to " " in onkeyup

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.