18

I have got this code

<div id="IIYBAGWNBC" contenteditable="true"></div>

And this in jquery

$("#IIYBAGWNBC").text(function(index, currentText) {
  return currentText.substr(0, 100);
});

How do I prevent the user to enter more than 100 characters in contenteditable div

Mr. Alien
  • 153,751
  • 34
  • 298
  • 278
J.doe
  • 205
  • 1
  • 2
  • 9

7 Answers7

16

It's pretty simple, on keydown, count the length of element's string and prevent user if he tries to feed more than 100 chars

$('div').on('keydown paste', function(event) { //Prevent on paste as well

  //Just for info, you can remove this line
  $('span').text('Total chars:' + $(this).text().length); 

  //You can add delete key event code as well over here for windows users.
  if($(this).text().length === 100 && event.keyCode != 8) { 
    event.preventDefault();
  }
});

Demo

Explanation:

On keydown or paste event on the contenteditable div we check if the length of the div reached 100 and if user is not clicking backspace key than prevent user to feed in more characters by clicking any key or even pasting with right click.

Mr. Alien
  • 153,751
  • 34
  • 298
  • 278
8

I did something like this by using the above mentioned answer to generalize the code, so that you can set the max length for any contenteditable div

$("div[contenteditable='true'][maxlength]").on('keydown paste', function (event) {
     var cntMaxLength = parseInt($(this).attr('maxlength'));

     if ($(this).text().length === cntMaxLength && event.keyCode != 8) {
         event.preventDefault();
     }
});

HTML will be as bewlow

<div id="IIYBAGWNBC" contenteditable="true" maxlength="500"></div>

this way you can mention the maxlenght to any of the contenteditable Div elemen. Hope this is helpful.

Community
  • 1
  • 1
Roshith
  • 81
  • 1
  • 4
  • You should use ">=" instead of "===" in case the user paste a long text and you should trim the extra characters that are more than "max length". – Mohamad Hamouday Mar 28 '22 at 22:01
3

This code does the job, note the "keyup" instead of "keydown" for correct processing of ctrl-v event, in addition, this code excludes arrow keys, finally please note the code that cut the text if you reach the limit:

$("div[contenteditable='true'][maxlength]").on('keyup paste', function (event) {
     var cntMaxLength = parseInt($(this).attr('maxlength'));

     if ($(this).text().length >= cntMaxLength && event.keyCode != 8 && 
         event.keyCode != 37 && event.keyCode != 38 && event.keyCode != 39 && 
         event.keyCode != 40) {
         
         event.preventDefault();

         $(this).html(function(i, currentHtml) {
             return currentHtml.substring(0, cntMaxLength-1);
         });
     }
});

Then, in your html:

<div contenteditable="true" maxlength="1024"></div>
Julian Rios
  • 2,431
  • 2
  • 7
  • 9
0

Simply you can do in html without javascript.

<div contenteditable="true" onkeypress="return (this.innerText.length <= 26)"> </div>

Gurung
  • 159
  • 1
  • 4
0
<div id="your-id" contenteditable="true" maxlength="10" onkeydown="onKeyDown(event)"></div>
function onKeyDown(event) {

  /* Any Shortcut except Ctrl + V */
  const isValidShortcut = (event.ctrlKey && event.keyCode != 86 );

  /* Backspace - Delete - Arrow Keys - Ctrl - Shift */
  const isValidKeyCode = [8, 16, 17, 37, 38, 39, 40, 46].includes(event.keyCode);

  const maxLength = parseInt(event.srcElement.getAttribute("maxlength"));

  const text = event.srcElement.innerText;

  if ( text.length >= maxLength && !isValidKeyCode && !isValidShortcut ) {
    event.preventDefault();
  }
}
0

The following code restricts input using regexp pattern, works on input type='text', content editable divs and textareas, prevents pasting and drag/dropping of non-matching text. Just add pattern='^.{0,10}$' property to restrict maxlength (or ^[\s\S]{0,10}$ to support new lines). You can copy this code into test.html file and open it in your browser for a quick test. I would like to know in which use cases it wouldn't work, please give a feedback in the comments.

<html>
<script language='javascript'>
function patternify() {
    //Restricts input using regexp pattern
    for (const el of document.querySelectorAll("[pattern]")) {
        el.dataset.beforeinputvalue = el.innerText.replaceAll("\n", "&n;")
        format = function(evt) {
            const pattern = el.getAttribute("pattern")
            const accept = new RegExp(pattern, "g")

            var input_match
            var el_div_value
            if (el.tagName == "DIV") {
                el_div_value = el.innerText
                input_match = el_div_value.match(accept)
            } else {
                input_match = el.value.match(accept)
            }

            if (input_match == null) {

                if (el.tagName == "DIV") {
                    var sel = document.getSelection();
                    //var bo = sel.baseOffset
                    var eo = sel.extentOffset
                    var cp = getCaretPosition(el)[0];
                    el.innerHTML = el.dataset.beforeinputvalue.replaceAll("&n;","<br>")
                    var antienter=0

                    if (window.fix_pattern_key === "Enter") antienter=1
                    setCurrentCursorPosition(el, cp-1+antienter)
                    
                } else {
                    var ss = el.selectionStart
                    var se = el.selectionEnd
                    el.value = el.dataset.beforeinputvalue
                    el.selectionStart = ss - 1
                    el.selectionEnd = se - 1
                }

            } else {
                if (el.tagName == "DIV") {
                    el.dataset.beforeinputvalue = el_div_value.replaceAll("\n","&n;")
                } else {
                    el.dataset.beforeinputvalue = el.value
                }
            }
        };

        //let back = false;
        el.addEventListener("keydown", function(e) { window.fix_pattern_key=e.key });
        el.addEventListener("input", format);
        //el.addEventListener("focus", format);
        //el.addEventListener("blur", () => el.value === pattern && (el.value = ""));
        //format()
    }
}





// node_walk: walk the element tree, stop when func(node) returns false
function node_walk(node, func) {
  var result = func(node);
  for(node = node.firstChild; result !== false && node; node = node.nextSibling)
    result = node_walk(node, func);
  return result;
};

// getCaretPosition: return [start, end] as offsets to elem.textContent that
//   correspond to the selected portion of text
//   (if start == end, caret is at given position and no text is selected)
function getCaretPosition(elem) {
  var sel = window.getSelection();
  var cum_length = [0, 0];

  if(sel.anchorNode == elem)
    cum_length = [sel.anchorOffset, sel.extentOffset];
  else {
    var nodes_to_find = [sel.anchorNode, sel.extentNode];
    if(!elem.contains(sel.anchorNode) || !elem.contains(sel.extentNode))
      return undefined;
    else {
      var found = [0,0];
      var i;
      node_walk(elem, function(node) {
        for(i = 0; i < 2; i++) {
          if(node == nodes_to_find[i]) {
            found[i] = true;
            if(found[i == 0 ? 1 : 0])
              return false; // all done
          }
        }

        if(node.textContent && !node.firstChild) {
          for(i = 0; i < 2; i++) {
            if(!found[i])
              cum_length[i] += node.textContent.length;
          }
        }
      });
      cum_length[0] += sel.anchorOffset;
      cum_length[1] += sel.extentOffset;
    }
  }
  if(cum_length[0] <= cum_length[1])
    return cum_length;
  return [cum_length[1], cum_length[0]];
}

function setCurrentCursorPosition(el, chars) {
    if (chars >= 0) {
        var selection = window.getSelection();

        range = createRange(el, { count: chars });

        if (range) {
            range.collapse(false);
            selection.removeAllRanges();
            selection.addRange(range);
        }
    }
};

function createRange(node, chars, range) {
    if (!range) {
        range = document.createRange()
        range.selectNode(node);
        range.setStart(node, 0);
    }

    if (chars.count === 0) {
        range.setEnd(node, chars.count);
    } else if (node && chars.count > 0) {
        if (node.nodeType === Node.TEXT_NODE) {
            if (node.textContent.length < chars.count) {
                chars.count -= node.textContent.length;
            } else {
                range.setEnd(node, chars.count);
                chars.count = 0;
            }
        } else {
            for (var lp = 0; lp < node.childNodes.length; lp++) {
                range = createRange(node.childNodes[lp], chars, range);

                if (chars.count === 0) {
                    break;
                }
            }
        }
    }

    return range;
};

document.addEventListener('DOMContentLoaded', function () {
    patternify();
}, false);

</script>
<body>

input type='text' (maxlength=5)<br>
<input type='text' pattern='^.{0,5}$'><br>

div contenteditable (maxlength=10)
<div contenteditable='true' pattern='^[\s\S]{0,10}$' style='width:500px;height:200px;border:1px solid black'></div>

textarea (maxlength=15)<br>
<textarea pattern='^[\s\S]{0,15}$' style='width:500px;height:200px;'></textarea>

</body>
</html>
plavozont
  • 807
  • 9
  • 17
-1

If you are using react. Use this react-text-content-editable

pradeepjan07
  • 29
  • 1
  • 3
  • 1
    Please avoid link-only answers, as links can get obsolete. Try to update your answer with the essential part of what you found useful in the link you provided. While this link may solve the question, [including an explanation](https://meta.stackexchange.com/questions/114762/explaining-entirely-code-??based-answers) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking. – Vickel Dec 04 '20 at 00:16