0

Hi i am very new to coding. I am trying to create a contenteditable div that is one line only and prevents the user typing more characters when the [contenteditable] reaches the same width as the parent element (e.g. i don't want it to overflow). The below code works on Desktop but not android or IOS. It seems there are 2 issues; 1) the return false; does not exit on android + IOS. 2) android + IOS do not recognise the "e.which" numbers...on android all keyboard letters are 229. My question is how do I get this code to work on mobile platforms please? Many thanks!

Note: On android all keys are e.which = 229 except Delete = 8 and Enter = 13. The code returns for 8 & 13 but not the rest 229.

<div class="textarea">
    
    <div contenteditable class="global-text-field">Lorum Ipsum</div>
</div>


<style>
.global-text-field{position:absolute;  white-space: nowrap;}
.textarea {position:relative; width:200px; height:50px; background:yellow;}
</style>


<script src="https://code.jquery.com/jquery-3.5.0.js"></script>
<script>

        $('.global-text-field').on('keydown', function(e){
        return OverflowOneLine(e);   
        });    
            
        function OverflowOneLine(e){
           
            var left = parseFloat($(event.target).css('left'));
            var right = parseFloat($(event.target).css('right'));
<!--e.which 8 = Delete, 46 = Backspace, 37 = ArrowLeft, 39 = ArrowRight-->
            if(right <= 6 && e.which !=46 && e.which !=37 && e.which !=39 & e.which !=8){
                return false;
            }
            
            return e.which != 13;
        }  
        
</script>
  • Can you share what keys correspond to the codes `46`, `37`, `39` and `8`? – emi Jan 24 '21 at 11:20
  • Thank you for reading my question: 8 = Delete, 46 = Backspace, 37 = ArrowLeft, 39 = ArrowRight – Andrew Chauve Jan 24 '21 at 11:31
  • Does this answer your question? [keyCode on android is always 229](https://stackoverflow.com/questions/36753548/keycode-on-android-is-always-229) – emi Jan 24 '21 at 15:55

1 Answers1

0

Use e.preventDefault() to prevent default key behavior. Also, wrap all the JS code into an onLoad event listener to ensure the DOM is mounted when the event listener is attached to the DOM (other tips in comments):

<div class="textarea">
    <div contenteditable class="global-text-field">Lorum Ipsum</div>
</div>

<style>
.global-text-field{position:absolute;  white-space: nowrap;}
.textarea {position:relative; width:200px; height:50px; background:yellow;}
</style>

<script src="https://code.jquery.com/jquery-3.5.0.js"></script>
<script>

// Use 2 spaces for JS indenting

// Wrap all code into an onload event listener
$(function() {

  // If you transpile your code or don't need compatibility
  // with old browsers, you'd better use `const` instead of `var`

  // KeyCodes: 8 = Delete, 46 = Backspace, 37 = ArrowLeft, 39 = ArrowRight
  var allowedKeys = [46, 37, 39, 8];

  function OverflowOneLine(e) {

    // Better use const if possible
    var left = parseFloat($(event.target).css('left'));
    var right = parseFloat($(event.target).css('right'));

    // Only use one condition (I've almost missed the one in the return)
    if(e.which === 13 ||
        (
          right <= 6 &&
          // Use an array to mark all the allowed keys
          // `includes` is not supported by any IE.
          // Polyfill it (conditionally) or use another solution
          // if you need to support IE.
          !allowedKeys.includes(e.which)
        )) {
      // Use preventDefault besides returning false
      e.preventDefault();
      return false;
    }

    return true;
  }

  // Directly bind the function callback without creating
  // an extra unneeded intermediate function
  $('.global-text-field').on('keypress', OverflowOneLine); 

});
        
</script>

Edit

As stated in another SO question, you should use keypress or textinput events instead of keydown event, or allow 229 special code.

Edit 2

jQuery says keypress will not be fired on some keys, like Shift, Esc, and delete. But those control keys are the ones into the allowedKeys, so perhaps this is ok for you.

emi
  • 2,786
  • 1
  • 16
  • 24
  • Edited with extra important tip for `onLoad` event listener. – emi Jan 24 '21 at 12:08
  • Thank you for taking the time to respond. Unfortunately I couldn't get this code to work, i'm probably doing something wrong but in anycase after further reading it seems there is a bug with Android resulting in the keydown listener not being able to detect which key was pressed, unless it was enter or delete. – Andrew Chauve Jan 24 '21 at 15:21
  • Fixed missing `)` in `if` condition – emi Jan 24 '21 at 15:26
  • Transformed into snippet. – emi Jan 24 '21 at 15:29
  • Found an extra bug on some Android virtual devices. Added explanation and fixed code (not tested on Android). – emi Jan 24 '21 at 15:52
  • There is another problem you are not managing: pasting text. Perhaps you prefer to listen to `onchange` event, rolling back a change if it produces an overflow (despite the pressed keys). – emi Jan 24 '21 at 16:10
  • Hi Emi, again thank you for your help! Unfortunately the code snippet provided works on desktop but not android. From my reading, keypress is deprecated on mobile browsers and the text input event does not recognise all characters (i did not test to confirm). I also read that this may only affect Samsung Android browers (which I have). The keydown & keyup are fired as it will "alert(e.which)" and detect 229 for all characters except 8 for delete and 13 for space. "return false;" works to prevent 8 & 13 from being pressed, but does not work for 229. – Andrew Chauve Jan 26 '21 at 11:07
  • PS i have used e.preventDefault for preventing pasting. I believe this problem is simply not possible to resolve on android/IOS. I am going to do a "hack" and try to hide the text that overflows, and trim it back character by character in a loop until the parent div is no longer overflowed. Also another spanner in the works is the swipe function on mobiles which I didn't account for. Thanks again, resolving this as I'd hoped is way out of my knowledge (even with your assistance as I'm such a rookie). Thanks again! – Andrew Chauve Jan 26 '21 at 11:13
  • Have you tried to add `229` to the allowed keys? – emi Jan 27 '21 at 09:14