jquery 使用字符计数器插件进行验证
Posted
技术标签:
【中文标题】jquery 使用字符计数器插件进行验证【英文标题】:jquery validate with a character counter plugin 【发布时间】:2015-10-13 22:30:17 【问题描述】:我有一个页面,其中包含使用 jquery-validate 插件验证的字段,并希望在字段上包含一个类似 twitter 的字符计数器,以查看剩余的字符数
这是我的演示 http://jsfiddle.net/4k1vokgv/1/
$(document).ready(function()
$(".counter").characterCounter(
counterCssClass: 'text-counter',
limit: 1000,
counterFormat: 'Characters Remaining: %1',
);
var validatorStrat = $("#strategyForm").validate(
rules:
exampleInputEmail1:
required: true,
,
ZB_note:
required: true,
maxlength: 140,
,
ZC_note:
required: true,
maxlength: 140,
,
,
submitHandler: function(form)
);
);
两个字符计数器都可以正常工作,直到 问题是,当 jquery-validate 触发验证错误(必需、maxlength 等)时,字符计数器会停止对任何有错误的元素工作。
我不认为这是字符计数器插件本身的问题。我认为 jquery 验证的错误生成确实会导致这种情况。
无论如何,包括下面的完整sn-p,非常感谢任何帮助
/**
* Character Counter v1.0
* ======================
*
* Character Counter is a simple, Twitter style character counter.
*
* https://github.com/dtisgodsson/jquery-character-counter
*
* @author Darren Taylor
* @author Email: shout@darrenonthe.net
* @author Twitter: darrentaytay
* @author Website: http://darrenonthe.net
*
*/
(function($)
$.fn.characterCounter = function(options)
var defaults =
exceeded: false,
limit: 150,
counterWrapper: 'span',
counterCssClass: 'help-block',
counterFormat: '%1',
counterExceededCssClass: 'exceeded',
onExceed: function(count) ,
onDeceed: function(count) ,
customFields: ,
;
var options = $.extend(defaults, options);
return this.each(function()
$(this).after(generateCounter());
bindEvents(this);
checkCount(this);
);
function customFields(params)
var html='';
for (var i in params)
html += ' ' + i + '="' + params[i] + '"';
return html;
function generateCounter()
var classString = options.counterCssClass;
if(options.customFields.class)
classString += " " + options.customFields.class;
delete options.customFields['class'];
return '<'+ options.counterWrapper +customFields(options.customFields)+' class="' + classString + '"></'+ options.counterWrapper +'>';
function renderText(count)
return options.counterFormat.replace(/%1/, count);
function checkCount(element)
var characterCount = $(element).val().length;
var remaining = options.limit - characterCount;
if( remaining < 0 )
$(element).next("." + options.counterCssClass).addClass(options.counterExceededCssClass);
options.exceeded = true;
options.onExceed(characterCount);
else
if(options.exceeded)
$(element).next("." + options.counterCssClass).removeClass(options.counterExceededCssClass);
options.onDeceed(characterCount);
options.exceeded = false;
$(element).next("." + options.counterCssClass).html(renderText(remaining));
;
function bindEvents(element)
$(element)
.bind("keyup", function ()
checkCount(element);
)
.bind("paste", function ()
var self = this;
setTimeout(function () checkCount(self); , 0);
);
;
)(jQuery);
$.validator.setDefaults(
errorElement: "span",
errorClass: "help-block",
// validClass: 'stay',
highlight: function (element, errorClass, validClass)
$(element).addClass(errorClass); //.removeClass(errorClass);
$(element).closest('.form-group').removeClass('has-success').addClass('has-error');
,
unhighlight: function (element, errorClass, validClass)
$(element).removeClass(errorClass); //.addClass(validClass);
$(element).closest('.form-group').removeClass('has-error').addClass('has-success');
,
errorPlacement: function(error, element)
if(element.parent('.input-group').length)
error.insertAfter(element.parent());
else if (element.hasClass('select2'))
error.insertAfter(element.next('span'));
else
error.insertAfter(element);
);
$(document).ready(function()
$(".counter").characterCounter(
counterCssClass: 'text-counter',
limit: 140,
counterFormat: 'Characters Remaining: %1',
);
var validatorStrat = $("#strategyForm").validate(
rules:
exampleInputEmail1:
required: true,
,
ZB_note:
required: true,
maxlength: 1000,
,
ZC_note:
required: true,
maxlength: 1000,
,
,
submitHandler: function(form)
);
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<script src="http://cdn.jsdelivr.net/jquery.validation/1.14.0/jquery.validate.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css" rel="stylesheet"/>
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet"/>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<form role="form" id="strategyForm">
<div class="form-group">
<label for="exampleInputEmail1" class="control-label">Email address</label>
<input type="email" class="form-control" name="exampleInputEmail1" placeholder="Enter email" />
</div>
<div class="form-group">
<label class="control-label">What amount is to be solicited and when?</label>
<textarea class="form-control counter" rows="1" id="ZB_note" name="ZB_note" ></textarea>
</div>
<div class="form-group">
<label class="control-label">Who will be involved in the soliciation?</label>
<textarea class="form-control counter" rows="1" id="ZC_note" name="ZC_note" ></textarea>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
【问题讨论】:
旁注:由于“自动分号插入”,您可能需要重新考虑使用 javascript 的 Allman 样式代码格式。见:***.com/q/11247328/594235 @Sparky 谢谢你的提醒,从来不知道 【参考方案1】:我在这里制作了具有此功能的代码笔。
Codepen
这里我也会补充和讨论代码,真的没那么难。
$( document ).ready(function()
$('#text').on('keypress', function(e)
var count = $(this).val().length;
if(count != 0)
count += 1;
else
count = count;
$('#characterCount').text(count);
)
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="row">
<div class="col m-2">
<textarea id="text" rows="4" cols="50"></textarea>
</div>
<div class="col m-2">
<textarea id="characterCount" rows="4" cols="50"></textarea>
</div>
</div>
document.ready 函数确保函数在 DOM 准备就绪时加载。然后你有一个函数,只要在文本区域上按下一个键就会触发。然后,您将 count 变量设置为当前文本 ID 值的长度。然后将计数设置为加一,因为它是零索引。然后,您在另一个文本区域中表示该值。
【讨论】:
【参考方案2】:问题在于插入错误元素的位置与用于设置计数器文本的遍历相比。
在您的计数器插件中,您正在寻找 next()
以使用以下设置计数显示:
$(element).next("." + options.counterCssClass).html(renderText(remaining));
这是基于结构是:
<inputElement/>
<counterDisplay/>
但验证器 errorPlacment 正在做:
<inputElement/>
<validatorError/>
<counterDisplay/>
所以现在插件next(classSelector)
没有返回匹配项
您可以简单地在插件中使用nextAll()
而不是next()
...或者将errorPlacement 更改为类似:
error.parent().append(element);
Demo using nextAll()
in plugin
【讨论】:
【参考方案3】:找出原因(问题)
我相信我已经找到了问题所在。 当 a 字段未通过验证规则时,它会显示错误。 错误被附加到 DOM 为:
此字段为必填项。
当我使用控制台删除它时,计数器工作了。
这让我很奇怪——也许 checkCount 函数仍然可以工作,但“输出”(span
计数器)却不行。
所以在第 72 行,我添加了:
console.log(characterCount);
再次复制该场景 - 它确实打印了计数。 所以问题是由于某种原因 - 当“错误”出现时,它与“文本计数器”冲突。请注意,在重新开始编写之后 - 似乎“错误”消失了 - 但事实是它仍在 DOM 中,只是使用 CSS 隐藏了。
<span id="ZB_note-error" class="help-block" style="display: none;"></span>
然后,我在第 92 行添加了以下代码:
console.debug( options.counterCssClass );
console.debug( $(element).next("." + options.counterCssClass).html());
猜猜输出是什么。 对于第一个调试行: text-counter (很好) 对于第二个调试行:未定义(不好)
如何解决?
解决方案 1:您错误地使用了 next()
函数。
描述:获取立即中每个元素的跟随兄弟 匹配元素的集合。如果提供了选择器,它将检索 仅当它与该选择器匹配时才是下一个兄弟。
添加“错误”元素时,文本计数器字段不再适用于next()
规则。考虑将其更改为:.parent().find('.text-counter')
,以防每个字段+文本计数器都有一个共同的父级。
解决方案 2:当用户开始输入时,从 DOM 中移除“error”元素。
【讨论】:
以上是关于jquery 使用字符计数器插件进行验证的主要内容,如果未能解决你的问题,请参考以下文章