javascript 计算文本区域/输入框中字符数的优雅方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11161600/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 12:13:55  来源:igfitidea点击:

Elegant way to count the number of characters in a textarea/input box

javascriptjqueryhtml

提问by Cecil Rodriguez

So I want to tell a user how many characters they have typed, dynamically. I'm seeing several examples online of using "Onchange" or "OnKeyUp", but they're both old examples and they seem sorta kludgy.

所以我想动态地告诉用户他们输入了多少个字符。我在网上看到了几个使用“Onchange”或“OnKeyUp”的例子,但它们都是旧例子,而且看起来有点笨拙。

Is there a better way? Perhaps some method of binding/assigning (may not be using this term correctly) the value to a variable, and then checking every time a change has been made?

有没有更好的办法?也许某种绑定/分配(可能没有正确使用该术语)值到变量的方法,然后在每次进行更改时进行检查?

回答by Elias Van Ootegem

When you're talking about dynamically showing how many characters have been typed, you'll need events, like onchangeor onkeyup... there's really no other way.

当您谈论动态显示已键入的字符数时,您将需要事件,例如onchangeonkeyup...确实没有其他方法。

What's more: "assigning the value to a variable and checking each time a change was made" how else but through onchangewill you know what you need to check and when?

更重要的是:“将值分配给一个变量并在每次进行更改时进行检查”还有其他方法,但onchange您知道什么时候需要检查吗?

a quick, easy way of doing this:

一种快速、简单的方法:

document.getElementById('aninputId').onchange= function(e)
{
    console.log(this.value.length);//or alert(); do with this value what you want
};

An important thing to keep in mind is that, if you're dealing with a lot of elements, you might want to consider delegating the event. hereyou can find a similar (not duplicate) question with 2 answers that deal with event delegation. Google it to find out more about this powerful feature!

要记住的一件重要事情是,如果您要处理很多元素,您可能需要考虑委托事件。在这里,您可以找到一个类似(不重复)的问题,其中包含 2 个处理事件委托的答案。谷歌它以了解有关此强大功能的更多信息!



UPDATE(with fiddle)

更新(用小提琴)

Ok, I set up this quick fiddleas an example of using event delegation. I used onchange, so the length won't show up until the focus is lost, there's a bit of comment to tell you what the code does, but it's written rather hastily. If you have any questions regarding this example, let me know.

好的,我将这个快速小提琴设置为使用事件委托的示例。我使用了onchange,所以在失去焦点之前不会显示长度,有一些注释告诉你代码是做什么的,但它写得相当仓促。如果您对此示例有任何疑问,请告诉我。

PS: if you want the length to change in real time, just replace

PS:如果你想实时改变长度,只需更换

mainDiv.addEventListener('onchange',showLength,false);

with

mainDiv.addEventListener('keyup',showLength,false);

Nothing more to it!

仅此而已!



Update2

更新2

In response to your last comment: No, that code won't work. The alert(e);line will attempt to alert the event object, so you'll only see '[object object]', if not undefinedon IE.

回应您的最后一条评论:不,该代码不起作用。该alert(e);行将尝试提醒event object,因此如果不在undefinedIE 上,您将只会看到“[object object]” 。

To help you understand what the code from my jsfiddle does, I'll break it down and go through it, step by step:

为了帮助您了解我的 jsfiddle 中的代码的作用,我将分解并逐步完成它:

In my example, the input fields (there's only 1 but there could have been 100's) are all children of a main div element #allInputs. So first, we get a reference to that element:

在我的示例中,输入字段(只有 1 个,但可能有 100 个)都是主 div 元素的所有子元素#allInputs。所以首先,我们获得对该元素的引用:

var mainDiv = document.getElementById('allInputs');//Here's where we'll listen for events

Then, we want an event listener attached to that div. Due to event bubbling in IE, and event capturing in all other browsers, all events that are triggered within this element will pass by the div. Hereare some diagrams that might clarify what I mean by that. This is the crucial concept of event delegation. Once you get this, the rest is easy.

然后,我们想要一个附加到该 div 的事件侦听器。由于 IE 中的事件冒泡,以及所有其他浏览器中的事件捕获,在该元素内触发的所有事件都将通过 div。这里有一些图表可以阐明我的意思。这是事件委托的关键概念。一旦你得到了这个,剩下的就很容易了。

Now, back to listening in on events: addEventListenerdoes what it says on the tin: it's attached to an element and listens to the events that are fired/dispatched within that element. If any of those events is of the specified type, it calls a function. This function is what is referred to as a callback, or -in this case- the event handler. As always IE doesn't work like all other browsers, so first we check to see if the addEventHandlermethod is available to us.

现在,回到监听事件:addEventListener做它在罐头上所说的:它附加到一个元素并监听在该元素内触发/调度的事件。如果这些事件中的任何一个是指定类型的,它就会调用一个函数。这个函数就是所谓的回调,或者——在这种情况下——事件处理程序。一如既往,IE 不像所有其他浏览器那样工作,所以首先我们检查该addEventHandler方法是否对我们可用。

if (!(mainDiv.addEventListener))
{//if not: this is the IE way
    mainDiv.attachEvent('onfocusout',showLength);
}
else
{
    mainDiv.addEventListener('change',showLength,false);
}

In both cases, the first argument is a string, stating the event type we want to listen to, In most cases addEventListenerdrops the onfrom the event type's name. IE, again being stubborn doesn't support the onchangeevent to be delegated (it doesn't bubble), we get around this issue by listening to another event: IE's own onfocusout event (if an input element looses focus, it has most likely been used for input, and has a new value. That makes it the right moment to check the value length.
addEventListenerhas a third parameter, to capturethe event, this is irrelevant in this case, but on quirksmode (the link above), you can read more on this topic, and I recommend you do.

在这两种情况下,第一个参数是一个字符串,说明我们想要侦听的事件类型,在大多数情况addEventListener下,on从事件类型的名称中删除。IE,再次顽固不支持onchange要委托的事件(它不会冒泡),我们通过侦听另一个事件来解决这个问题:IE 自己的 onfocusout 事件(如果输入元素失去焦点,它很可能是用于输入,并有一个新值。这使它成为检查值长度的正确时机。
addEventListener有第三个参数,用于捕获事件,这在这种情况下无关紧要,但在 quirksmode(上面的链接)上,您可以阅读有关此主题的更多信息,我建议您这样做。

function showLength(e)
{
    e = e || window.event;
    var target = e.target || e.srcElement;//ie== srcElement, good browsers: target
    if (target.tagName.toLowerCase() === 'input' && target.type === 'text')
    {
        document.getElementById(target.id + 'Span').innerHTML = target.value.length;
    }
}

Now for the actual callback. Declare this function, like you would any other function, and specify 1 argument, in this case e, or event- doesn't matter what you call it. (multiple arguments are possible, but then we have to get into closures, I'll try and stick to the basics here).
The event object will be passed to the handler function when it is called by most browsers, guess which browser doesn't pass this object? Yes, our old pal IE, but that's an easy fix: first line of the function e = e || window.event;can be written as:

现在是实际的回调。声明这个函数,就像你声明任何其他函数一样,并指定 1 个参数,在这种情况下是e,或者event- 与你怎么称呼它无关。(多个参数是可能的,但是我们必须进入闭包,我将在这里尝试坚持基础知识)。
大多数浏览器调用时都会将事件对象传递给处理函数,猜猜哪个浏览器没有传递这个对象?是的,我们的老朋友 IE,但这是一个简单的修复:函数的第一行e = e || window.event;可以写成:

if (e === undefined)
{
    e = window.event;
}

Why? because our dear friend Internet Explorer doesn't pass the event object to the handler, but rather keeps it in the global object, which we can access via window.event.

为什么?因为我们亲爱的 Internet Explorer 不会将事件对象传递给处理程序,而是将其保存在全局对象中,我们可以通过window.event.

Next thing we need, is to figure out on which element the event was triggered. Suppose you have a form, with 20 input fields, 10 radio buttons and 16 select elements, we're detecting the event at the level of the div#allInputs, we only know that the event was set off within this element. Luckily the event object has a property that holds a reference to the element we need:

接下来我们需要确定事件是在哪个元素上触发的。假设您有一个表单,有 20 个输入字段、10 个单选按钮和 16 个选择元素,我们在 级别检测事件div#allInputs,我们只知道该事件是在该元素内触发的。幸运的是,事件对象有一个属性来保存对我们需要的元素的引用:

var target = e.target || e.srcElement;

Again, IE is different. If you've read (and remembered) what was on the quirksmode page: IE events are triggered first at element level, and then bubble their way upward in the DOM, while all W3C browsers dispatch the event at the top level, and passes it down to the actual element. This explains the different names of what is, essentially, the same property: W3C events are dispatched, and then seek out their targetelement, IE events are dispatched at the element, and bubble up from their source. --I'm drifting off.

同样,IE 是不同的。如果您已经阅读(并记住)了 quirksmode 页面上的内容:IE 事件首先在元素级别触发,然后在 DOM 中向上冒泡,而所有 W3C 浏览器都在顶层调度事件,并传递它到实际元素。这解释了本质上相同属性的不同名称:调度 W3C 事件,然后查找它们的target元素,在元素上调度 IE 事件,并从它们的源冒泡。——我要飘了。

What do we know at this stage? Everything we need to know, really. We know what event was fired (e.typewill tell us that - in this case either change or focusout). We what element has changed/lost focus, and have a reference to that element in a variable target, so we can get at it's value (target.value), it's id (target.id) and and, more importantly: we can check if we want to do anything further:

在这个阶段我们知道什么?我们需要知道的一切,真的。我们知道触发了什么事件(e.type会告诉我们 - 在这种情况下,要么改变要么聚焦)。我们知道哪个元素已经改变/失去了焦点,并且在一个变量中引用了那个元素target,所以我们可以得到它的值(target.value),它的 id(target.id),而且,更重要的是:我们可以检查我们是否想要进一步做任何事情:

if (target.tagName.toLowerCase() === 'input' && target.type === 'text')

Remember that I talked about a situation where you're dealing with a form of 30+ elements, not all text inputs? If a new option is selected in a select element, we don't want to show the length of the select's value property, do we? So we check to see if the targetis an inputtag.
This can still be any input element imaginable, so let's also check if its type, only if targetis a text input will we display the length:

还记得我谈到过一种情况,即您正在处理 30 多个元素的表单,而不是所有文本输入吗?如果在 select 元素中选择了一个新选项,我们不想显示 select 的 value 属性的长度,对吗?所以我们检查它是否target是一个input标签。
这仍然可以是任何可以想象的输入元素,所以让我们也检查它的类型,只有当target是文本输入时,我们才会显示长度:

document.getElementById(target.id + 'Span').innerHTML = target.value.length;
//or, if you want:
alert(target.value.length);


What are the advantages of this over direct binding of events? Again: if you're binding change events to several elements individually, your users WILLnotice. As an added bonus: the change events of selects, text inputs, radio's,... all can be handled by 1 function. All it takes is a switch statement. Instead of:

与直接绑定事件相比,这有什么优势?还是那句话:如果你结合改变事件的几个元素单独,用户WILL通知。作为一个额外的好处:选择、文本输入、收音机等的更改事件都可以由 1 个函数处理。它所需要的只是一个 switch 语句。代替:

if (target.tagName.toLowerCase() === 'input' && target.type === 'text')
{
    document.getElementById(target.id + 'Span').innerHTML = target.value.length;
}

Try this:

试试这个:

if (target.tagName.toLowerCase() === 'select')
{
    alert('You\'ve selected option number: ' + (target.selectedIndex + 1));
}
if (target.tagName.toLowerCase() !== 'input')
{//suppose I only want to deal with input and select elements
    return;
}
switch(target.type)
{
    case 'text':
        alert(target.value.length);//alerts length of input value
        return;//this event is done, return
    case 'radio':
        alert('The radio button is ' + (target.checked ? '' : 'un') + 'checked');
        return;
    case 'password': 
        if (target.value.length < 8)
        {
            alert('The password is too short, add '+(8 - target.value.length)+'chars');
            return;
        }
        var verifyPass = 'passIn_' + (target.id.match(/_1$/) ? '2' : '1');
        verifyPass = document.getElementById(verifyPass);
        if (verifyPass.value.length > 0 && target.value.length > 0 && verifyPass.value !== target.value)
        {
            alert('password confirmation failed');
        }
}
return;

As you can see, a ton of events can be dealt with in a single function, binding 1 event listener. If you bind directly you'd need to bind a ton of handlers, probably need to write several functions, which can be harder to maintain and even worse: makes your site sluggish for the user.

如您所见,可以在单个函数中处理大量事件,绑定 1 个事件侦听器。如果直接绑定,则需要绑定大量处理程序,可能需要编写几个函数,这可能更难维护,甚至更糟:使您的站点对用户来说变得迟钝。



Ok, I'm done now and ready for bed. I hope this clears things out a little for you. Read the page on quirksmode, google a tutorial on event delegation if this dribble wasn't very clear to you, but I hope I did provide you with adequate explanation of the code I provided, and gave you some insight as to why event delegation is the right way of doing things, and why -behind the screens- most libraries work this way, too.
If you're really hesitant to include code that you can't understand, you might find it useful to know that jQuery delegates nearly all events, rather the binding them directly.

好的,我现在完成了,准备睡觉了。我希望这可以为您解决一些问题。阅读有关 quirksmode 的页面,如果您对此不太清楚,请在谷歌上搜索有关事件委托的教程,但我希望我确实为您提供了对我提供的代码的充分解释,并让您了解为什么事件委托是正确的做事方式,以及为什么 - 在屏幕后面 - 大多数图书馆也是这样工作的。
如果您真的不愿意包含您无法理解的代码,您可能会发现知道 jQuery 委托几乎所有事件而不是直接绑定它们很有用。

回答by Mohamed Khamis

You need a listener to detect added/removed characters, and accordingly change the counter. So you have to either use a key listener, or use onchange

您需要一个侦听器来检测添加/删除的字符,并相应地更改计数器。因此,您必须使用密钥侦听器,或者使用onchange

here's an example: Twitter-like Textbox Character Count with inline alert

这是一个例子: 带有内联警报的类似 Twitter 的文本框字符计数

回答by Justin Schier

If you're using jQuery, there is a plugin that does this. I have used it in production and it works great.

如果您使用 jQuery,有一个插件可以做到这一点。我在生产中使用过它,效果很好。

http://cssglobe.com/post/7161/jquery-plugin-simplest-twitterlike-dynamic-character-count-for-textareas

http://cssglobe.com/post/7161/jquery-plugin-simplest-twitterlike-dynamic-character-count-for-textareas

回答by Xenione

with jquery

使用 jquery

$('input[name='the name of the input']').bind('keyup',function(){
 $('#show').val($(this).length)
});

回答by Nishu Tayal

There are various jquery plugins which provides this feature and various configurations
You can have a look on :

有各种 jquery 插件提供此功能和各种配置
您可以查看:

http://youhack.me/2010/04/22/live-character-count-with-progress-bar-using-jquery/

http://youhack.me/2010/04/22/live-character-count-with-progress-bar-using-jquery/

http://qwertypants.me/counter/

http://qwertypants.me/counter/

Hope, it'll help you.

希望,它会帮助你。