限制 ContentEditable div 中的字符数

IT技术 javascript jquery contenteditable
2021-01-27 01:33:23

我在我的 web 应用程序中使用 contenteditable div 元素,我试图想出一个解决方案来限制该区域允许的字符数量,一旦达到限制,尝试输入字符就什么都不做。这是我到目前为止:

var content_id = 'editable_div';

//binding keyup/down events on the contenteditable div
$('#'+content_id).keyup(function(){ check_charcount(content_id, max); });
$('#'+content_id).keydown(function(){ check_charcount(content_id, max); });

function check_charcount(content_id, max)
{   
    if($('#'+content_id).text().length > max)
    {
        $('#'+content_id).text($('#'+content_id).text().substring(0, max));
    }
}

这确实将字符数限制为“max”指定的数量,但是一旦区域的文本由 jquery .text() 函数设置,光标将自身重置到区域的开头。因此,如果用户继续输入,新输入的字符将被插入到文本的开头,而文本的最后一个字符将被删除。所以真的,我只需要某种方式将光标保持在可编辑区域文本的末尾。

6个回答

event对象传递给您的函数并e.preventDefault()在达到最大值时调用如何?

var content_id = 'editable_div';  

max = 10;

//binding keyup/down events on the contenteditable div
$('#'+content_id).keyup(function(e){ check_charcount(content_id, max, e); });
$('#'+content_id).keydown(function(e){ check_charcount(content_id, max, e); });

function check_charcount(content_id, max, e)
{   
    if(e.which != 8 && $('#'+content_id).text().length > max)
    {
       // $('#'+content_id).text($('#'+content_id).text().substring(0, max));
       e.preventDefault();
    }
}

虽然,您可能需要做更多的事情来允许用户执行诸如“删除”之类的操作。


编辑:

添加了对“删除”键的支持。


编辑2:

此外,您可能可以摆脱keyup处理程序。keydown应该够了。

@Tim Down - 非常正确。如果使用 contentEditable div,这是不可避免的(据我所知),因为没有change事件。我的解决方案是针对这个问题的。您非常恰当地涵盖了所提出方法的一般缺点。
2021-03-15 01:33:23
奇迹般有效!:-) 我还为箭头键和退格/删除添加了条件,除此之外它工作得很好。
2021-03-20 01:33:23
通过上下文菜单或编辑菜单粘贴仍然可以使用户超过限制。
2021-03-29 01:33:23
侦听input事件将允许您捕捉键盘、粘贴和拖动更改。
2021-04-03 01:33:23
这些键也应该被允许: var allowedKeys = { 8: true, // BACKSPACE 35: true, // END 36: true, // HOME 37: true, // LEFT 38: true, // UP 39: true , // RIGHT 40: true, // DOWN 46: true // DEL }
2021-04-08 01:33:23

实现此目的的简单方法:

<div onkeypress="return (this.innerText.length <= 256)" contenteditable="true">
TypeError: this.innerText 在 FF43 中 <!DOCTYPE html> 时未定义:-(
2021-03-18 01:33:23
keypresskeydown. 在按键的情况下,它不会阻止用户在其中粘贴超过最大长度的文本,但退格键和删除键确实是“安全的”。
2021-03-20 01:33:23
为我工作。对于粘贴我只是禁用用户这个功能 onpaste="return false;"
2021-03-24 01:33:23
比其他答案简单得多。
2021-03-25 01:33:23
武士,内容可以删除。按键时不会考虑“退格”按钮。
2021-04-07 01:33:23

首先,这种事情对用户来说是令人恼火的:我建议改为做一些类似于 StackOverflow 的评论字段的事情,它允许你输入任意多或任意少,显示一条消息告诉你你输入了多少个字符无论是多还是少,都不让你提交长度无效的评论。

其次,如果你真的必须限制文本的长度,<div>如果内容太长,则每次击键都替换整个内容会不必要地昂贵,并且会使编辑器在较慢的机器上无响应。我建议处理keypress事件并简单地防止事件中插入字符preventDefault()(或在 IE 中,将事件设置returnValuetrue,假设您正在使用attachEvent)。这不会阻止用户粘贴文本,因此您需要处理paste事件(在 Opera 或 Firefox < 3 中不存在,因此您需要某种基于轮询的解决方案)。由于您将无法提前访问正在粘贴的内容,您将无法知道粘贴是否会超过字符数限制,因此您需要设置一个计时器来再次检查长度粘贴后。既然如此,第一个选项似乎对我来说更可取。

input事件可以处理的paste情况。
2021-03-16 01:33:23
input任何版本的 IE 都不支持 contenteditable,所以你甚至不能依赖它。@TimDown 指出了本文中任何其他解决方案均未涵盖的粘贴问题。此外,调用操作document.execCommand()也会以一种您无法检测和阻止的方式插入内容,并且可以被动删除(insertText、insertHTML、paste、insertOrderedList、insertUnorderedList 等都是将文本插入编辑器的命令) . 使用@TimDown 提出的解决方案 #1 的更多理由
2021-03-16 01:33:23
非常好的点蒂姆,我完全忘记了考虑粘贴操作或将文本输入编辑器的任何方法,这些方法不会为此生成按键事件。是的,我也从来没有对替换整个内容的解决方案感到兴奋,这只是对问题的快速初步尝试。所以现在看看它,我可能只需要采用最初允许无限数量字符的解决方案,但在用户结束时警告用户并且不允许保存内容。
2021-03-27 01:33:23
@Tresdin:确实,该input事件(在 2010 年没有得到很好的支持)确实简化了任务,尽管我仍然希望避免截断 textarea 的内容。
2021-04-07 01:33:23
您可以在media -editor中的 issue #962看到有关此特定问题的更多对话,我们一直在集思广益,将这一功能实现到编辑器中。在媒体编辑器中,我们还有一个editableInput自定义事件的好处,它可以检测所有浏览器中的所有类型的文本插入(包括粘贴和 document.execCommand())
2021-04-12 01:33:23

这是执行这种最概括形式的最佳方法,对我来说非常有用!

<div contenteditable="true" name="choice1" class="textfield" max="255"></div>
    $('.textfield').on("keypress paste", function (e) {
        if (this.innerHTML.length >= this.getAttribute("max")) {
            e.preventDefault();
            return false;
        }
    });
如果 contenteditable div 是动态生成的,则必须使用 $(document).on("keypress paste",".textfield",function(e){});
2021-03-21 01:33:23
有陷阱。它只检查innerHTML的长度,如果粘贴本身太大,就会超过限制。
2021-03-25 01:33:23

这就是我通过 jQuery 绑定实现的方式,只需将属性 data-input-length 添加到内容可编辑元素,这对我来说很容易。只需在文档中的任何位置添加 javascript 代码即可。

$(document).ready(function(){
	// Excempt keys(arrows, del, backspace, home, end);
	var excempt = [37,38,39,40,46,8,36,35];
	// Loop through every editiable thing
	$("[contenteditable='true']").each(function(index,elem) {
	    var $elem = $(elem);
	    // Check for a property called data-input-length="value" (<div contenteditiable="true" data-input-length="100">)
	    var length = $elem.data('input-length');
	    // Validation of value
	    if(!isNaN(length)) {
	    	// Register keydown handler
	        $elem.on('keydown',function(evt){
	        	// If the key isn't excempt AND the text is longer than length stop the action.
	            if(excempt.indexOf(evt.which) === -1 && $elem.text().length > length) {
	               evt.preventDefault();
	               return false;
	            }
	        });
	    }
	});
});
div {
  background-color:#eee;
  border: 1px solid black;
  margin:5px;
  width:300px;
  height:100px;
  }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div contenteditable="true" data-input-length="100">
You can type a 100 characters here
</div>
<div contenteditable="true" data-input-length="150">
You can type a 150 characters here
</div>
<div contenteditable="true" data-input-length="10">
You can type a 10 characters here
</div>