文本区域 onchange 检测
Posted
技术标签:
【中文标题】文本区域 onchange 检测【英文标题】:Textarea onchange detection 【发布时间】:2011-02-18 21:44:06 【问题描述】:如何使用 javascript 检测 textarea 上的更改事件? 我正在尝试检测您键入时剩余的可用字符数。
我尝试使用 onchange 事件,但似乎只有在焦点消失时才会启动。
【问题讨论】:
【参考方案1】:最好的方法是跨浏览器:结合使用input
和onpropertychange
事件,如下所示:
var area = container.querySelector('textarea');
if (area.addEventListener)
area.addEventListener('input', function()
// event handling code for sane browsers
, false);
else if (area.attachEvent)
area.attachEvent('onpropertychange', function()
// IE-specific event handling code
);
input
事件处理IE9+, FF, Chrome, Opera and Safari,onpropertychange
处理IE8(它也适用于 IE6 和 7,但存在一些错误)。
使用input
和onpropertychange
的优点是它们不会不必要地触发(例如按下Ctrl
或Shift
键时);所以如果您希望在 textarea 内容发生变化时运行相对昂贵的操作,这是可行的方法。
现在 IE 一如既往地支持这一点:当字符从 textarea 中删除时,input
和 onpropertychange
在 IE 中都不会触发。因此,如果您需要处理 IE 中的字符删除,请使用 keypress
(而不是使用 keyup
/ keydown
,因为即使用户按下并按住某个键,它们也只会触发一次)。
来源:http://www.alistapart.com/articles/expanding-text-areas-made-elegant/
编辑: 似乎即使上述解决方案也不完美,正如 cmets 中正确指出的那样:textarea 上 addEventListener
属性的存在确实不暗示您正在使用健全的浏览器;同样,attachEvent
属性的存在确实不暗示 IE。如果您希望您的代码真正密封,您应该考虑更改它。有关指针,请参阅 Tim Down's comment。
【讨论】:
这是最好的方法。我不喜欢这里的推论(浏览器支持addEventListener
并不意味着支持input
事件,反之亦然);特征检测会更好。有关此问题的讨论,请参阅 this blog post。
完全同意蒂姆的观点。 oninput
是我们应该这样做的,但您可能不应该使用 addEventListener
作为浏览器支持的测试。无论如何 +1。
不同意,输入无法处理 IE9。不幸的是,通过上下文菜单剪切/粘贴也是输入,退格也是。我没有费心去测试,但我不会押注 IE10+ 解决了这个问题。
@StefanSteiger 这就是为什么我的回答建议使用keypress
事件来处理 IE9(可能还有更高版本)中的这种情况。
input
event 处理程序也可以通过实现.oninput
对象属性来定义。【参考方案2】:
您需要为此使用onkeyup
和 onchange
。 onchange 将阻止上下文菜单粘贴,并且 onkeyup 将在每次击键时触发。
有关代码示例,请参阅我在 How to impose maxlength on textArea 上的回答。
【讨论】:
只是想强调 Josh 已经说过的话,你应该使用 keyup,而不是 keydown:keydown 似乎是在对 textarea 进行实际更改之前调用的,所以你将使用错误的长度(而且你真的不知道自己有多差:可能正在输入或删除,并且可能选择了文本,这意味着它不仅仅是 +/- 1)。 我在这里给-1,对不起!onkeyup
是输入检测的可怕事件。使用oninput
和onpropertychange
(用于IE 支持)。
唯一的问题是onchange
在上下文菜单剪切/粘贴发生时不被触发。
使用 onkeydown 和 setTimeout 响应速度更快,因此您可以即时检测更改,而不是等待密钥被释放。如果您还需要捕获剪切和粘贴,请使用剪切和粘贴事件。
警告:onkeyup 会给你带来麻烦。示例:假设您只应该在输入内容更改时才做某事。如果您假设 keyup 会更改输入,那么它不是真的。把重点放在输入上。使用“制表符”移动到下一个字段。现在使用“shift+tab”返回输入。 keyup 触发,但用户实际上并未更改输入。【参考方案3】:
对于 Google-Chrome,oninput 就足够了(在版本 22.0.1229.94 m 的 Windows 7 上测试)。
对于 IE 9,oninput 将捕获除通过上下文菜单和退格键剪切之外的所有内容。
对于 IE 8,除了 oninput 之外,还需要 onpropertychange 来捕获粘贴。
对于 IE 9 + 8,需要 onkeyup 才能捕获退格键。
对于 IE 9 + 8,onmousemove 是我发现通过上下文菜单捕捉剪切的唯一方法
未在 Firefox 上测试。
var isIE = /*@cc_on!@*/false; // Note: This line breaks closure compiler...
function SuperDuperFunction()
// DoSomething
function SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally()
if(isIE) // For Chrome, oninput works as expected
SuperDuperFunction();
<textarea id="taSource"
class="taSplitted"
rows="4"
cols="50"
oninput="SuperDuperFunction();"
onpropertychange="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();"
onmousemove="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();"
onkeyup="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();">
Test
</textarea>
【讨论】:
很棒的函数名:)【参考方案4】:我知道这不完全是您的问题,但我认为这可能有用。 对于某些应用程序,最好不要在每次按下键时触发更改功能。这可以通过以下方式实现:
var text = document.createElement('textarea');
text.rows = 10;
text.cols = 40;
document.body.appendChild(text);
text.onkeyup = function()
var callcount = 0;
var action = function()
alert('changed');
var delayAction = function(action, time)
var expectcallcount = callcount;
var delay = function()
if(callcount == expectcallcount)
action();
setTimeout(delay, time);
return function(eventtrigger)
++callcount;
delayAction(action, 1200);
();
这通过测试是否在某个延迟期内触发了更新的事件来起作用。祝你好运!
【讨论】:
+1 表示“节流”延迟操作!我在我的应用中使用了类似的东西。【参考方案5】:我知道这个问题是特定于 JavaScript 的,但是,似乎没有一种好的、干净的方法来始终检测所有当前浏览器中的文本区域何时发生变化。我了解到 jquery 已经为我们处理好了。它甚至可以处理文本区域的上下文菜单更改。无论输入类型如何,都使用相同的语法。
$('div.lawyerList').on('change','textarea',function()
// Change occurred so count chars...
);
或
$('textarea').on('change',function()
// Change occurred so count chars...
);
【讨论】:
我发现 change 事件与 jQuery 的一致性并不比与普通 JS 的一致性好。我使用了 jQuery 的bind("input cut paste"...
,它就像一个魅力——使用键盘或上下文菜单输入、剪切和粘贴;甚至拖放文本。
不幸的是,FF 不会为textarea
触发change
事件。【参考方案6】:
您可以收听文本区域更改的事件并根据需要进行更改。这是一个例子。
const textArea = document.getElementById('my_text_area');
textArea.addEventListener('input', () =>
var textLn = textArea.value.length;
if(textLn >= 100)
textArea.style.fontSize = '10pt';
)
<html>
<textarea id='my_text_area' rows="4" cols="50" style="font-size:40pt">
This text will change font after 100.
</textarea>
</html>
【讨论】:
最短的最佳答案【参考方案7】:如果与 HTML5 输入验证/模式属性配对,Keyup 就足够了。因此,创建一个模式(正则表达式)来验证输入并根据 .checkValidity() 状态采取行动。像下面这样的东西可以工作。在您的情况下,您需要一个正则表达式来匹配长度。我的解决方案正在使用/可在线演示here。
<input type="text" pattern="[a-zA-Z]+" id="my-input">
var myInput = document.getElementById = "my-input";
myInput.addEventListener("keyup", function()
if(!this.checkValidity() || !this.value)
submitButton.disabled = true;
else
submitButton.disabled = false;
);
【讨论】:
【参考方案8】:我在没有 jquery 的情况下用于 IE 11 并且仅用于单个 textarea 的代码:
Javascript:
// Impede que o comentário tenha mais de num_max caracteres
var internalChange= 0; // important, prevent reenter
function limit_char(max)
if (internalChange == 1)
internalChange= 0;
return;
internalChange= 1;
// <form> and <textarea> are the ID's of your form and textarea objects
<form>.<textarea>.value= <form>.<textarea>.value.substring(0,max);
和html:
<TEXTAREA onpropertychange='limit_char(5)' ...
【讨论】:
【参考方案9】:试试这个。这很简单,因为它是 2016 年,我相信它可以在大多数浏览器上运行。
<textarea id="text" cols="50" rows="5" onkeyup="check()" maxlength="15"></textarea>
<div><span id="spn"></span> characters left</div>
function check()
var string = document.getElementById("url").value
var left = 15 - string.length;
document.getElementById("spn").innerHTML = left;
【讨论】:
所以你通过 id 获取 url,但它没有显示在你的代码中。【参考方案10】:你能做的最好的事情是设置一个函数在给定的时间内被调用,这个函数来检查你的文本区域的内容。
self.setInterval('checkTextAreaValue()', 50);
【讨论】:
轮询是一个非常糟糕的主意。它只会破坏性能。此外,与其他发布的一样,存在一些解决方案 这是 21 世纪。任何浏览器都不应该在每 50 毫秒处理一次字符串比较时遇到问题。缓存你的选择器,这是一个完全可以接受的解决方案。 哇!跳出框框思考,但想法很糟糕。以上是关于文本区域 onchange 检测的主要内容,如果未能解决你的问题,请参考以下文章
使用 Jquery 从 CKEditor 检测 onChange 事件