I have a page that has fields that are validated using jquery-validate plugin, and wanted to include a twitter like character counter on the fields to see how many chars are left
Here is my demo
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) {}
});
});
Both character counters work fine until
the issue, when jquery-validate fires a validation error (required, maxlength, etc), the character counter then stops working on any element that has an error.
I do not believe this is an issue with the character counter plugin itself. I think the error generation that jquery validate does somehow causes this.
Anyways, included the full snippet below, any help is greatly appreciated
/**
* 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>
I have made a code pen with exactly this functionality here.
Codepen
I will also add and discuss the code here, it really is not that hard.
$( 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>
The document.ready function insures the function loads when the DOM is ready. You then have a function that fires whenever a key is pressed on the text area. You then have the count variable that is set to the length of the value of the current text ID. You then set the count to plus one, because it is zero index. You then represent the value on the other text area.
Problem is due to where the error element is being inserted compared to the traverse you use to set the counter text.
In your counter plugin you are looking for next() to set the count display using the following:
$(element).next("." + options.counterCssClass).html(renderText(remaining));
That is based on structure being:
<inputElement/>
<counterDisplay/>
But the validator errorPlacment is doing:
<inputElement/>
<validatorError/>
<counterDisplay/>
So now the plugin next(classSelector) returns no matches
You could simply use nextAll() instead of next() in plugin...or change the errorPlacement to something like :
error.parent().append(element);
Demo using nextAll() in plugin
Finding the reason (Problem)
I believe I've found the problem.
When the a field doesn't pass the validation rules it shows an error.
The error is being append to the DOM as:
This field is required.
When I removed it using the console the counter worked.
That made my wonder - maybe the checkCount function still works but the "output" (the span counter) doesn't.
So on line 72, I added:
console.log(characterCount);
Duplicated that scenario again - and it indeed printed the count.
So the problem is that from some reason - when the " error" appears it conflicts with the " text counter". Please notice, that after start writing again - it seems that the " error" is gone - but the truth is that it still in the DOM, it's just hidden using CSS.
<span id="ZB_note-error" class="help-block" style="display: none;"></span>
Then, I added the following code on Line 92:
console.debug( options.counterCssClass );
console.debug( $(element).next("." + options.counterCssClass).html());
Guess what was the output.
For the first debug line: text-counter (that's good)
For the second debug line: undefined (not good)
How to solve it?
Solution 1: You're using the next() function wrongly.
Description: Get the immediately following sibling of each element in
the set of matched elements. If a selector is provided, it retrieves
the next sibling only if it matches that selector.
When the " error" element is being added, the text-counter field is no longer apply to the next() rule. Consider change it with something like: .parent().find('.text-counter') in case each field+text-counter have a common parent.
Solution 2: When a user starts typing, remove the " error" element from the DOM.
Related
I have a few input fields
<input type="text" placeholder="name">
<input type="text" placeholder="age">
<input type="text" placeholder="gender">
<input type="text" placeholder="interest">
and every time I write on those input fields it should reflect to the textarea and output a format with | or pipe symbol
Example:
<textarea>
name|age|gender|interest
</textarea>
and when I add another set of fields it writes it on the second line
<textarea>
name|age|gender|interest
name|age|gender|interest
name|age|gender|interest
</textarea>
Also "Number of Children" quantity needs to adjust automatically based on per line in the text area or how many children.
Here is My fiddle to make it more clearer https://jsfiddle.net/sjgrLcqx/4/
I did a few things here.
I made your HTML string a single variable so that when I changed it I didn't have to do so twice.
I added classes to your inputs so that I could figure out which one the user is typing into.
I used a few jQuery methods you might not be aware of, like index() and parent().
I used a few JavaScript functions to iterate through the properties on the child object I created to make creating a string from its attributes easier.
Look over the code and let me know if you have any questions. Also, next time, maybe try this yourself, even if you have no idea where to start. Just keep trying stuff until something starts to work. Coding is challenging but that's what's fun about it.
jQuery(document).ready(function () {
var childInfoArray = [];
var formHtml = '<div class="optionBox"><div class="block" style=""><input class="crow fullName" type="text" placeholder="Full name"><input class="crow width50 marginsmall age" type="text" placeholder="Age"><input class="crow width50 nomargin gender" type="text" placeholder="gender"><input class="crow interest" type="text" placeholder="Interest"><span class="remove">Remove this section</span></div><div class="block"><span class="add">Add another child\'s info</span></div></div>';
jQuery('#frmPaymentSantasgrotto').append(formHtml);
jQuery('.add').click(function () {
jQuery('.block:last').before(formHtml);
});
jQuery('.optionBox').on('click', '.remove', function () {
jQuery(this).parent().remove();
});
jQuery('.optionBox').on('keyup', 'input', function () {
var index = $(this).parent().index('div.block');
var child = {};
if (childInfoArray[index] != null) {
child = childInfoArray[index];
}
else {
child = {
fullName: '',
age: '',
gender: '',
interest: ''
}
}
if ($(this).hasClass('fullName')) {
child.fullName = jQuery(this).val();
}
else if ($(this).hasClass('age')) {
child.age = jQuery(this).val();
}
else if ($(this).hasClass('gender')) {
child.gender = jQuery(this).val();
}
else if ($(this).hasClass('interest')) {
child.interest = jQuery(this).val();
}
childInfoArray[index] = child;
printChildArray();
});
function printChildArray() {
var childInfoString = "";
childInfoArray.forEach(child => {
Object.values(child).forEach((attribute, index) => {
childInfoString += attribute;
if (index !== Object.keys(child).length - 1) {
childInfoString += ' | ';
}
else {
childInfoString += ' \n';
}
});
});
$('textarea').html(childInfoString);
}
});
Hope this question is usefull.
In my autocomplete success I make my input hidden value 1 to avoid
jquery validation and append the current customer name to the
particular input field and all are working fine.
My glitch is if supposed user manually delete the value of input field
which have current customer name, I want to show jquery validation
error. But how can I show that??. Because In my autocomplete success I
made the hidden value 1. So its failed to show the error and I cant check that in keyup or keydown function, Beacuse using that input id I already written the autocomplete.
$(document).ready(function() {
$("#apendexistingCustomer").autocomplete({
autoFocus: true,
source: '{{ url("/getexistingcustomer") }}',
minLength: 2,
select: function(event, ui) {
event.preventDefault();
if (ui.item.label == 'This customer is not in our records.') {
$('#apendexistingCustomer').val('');
$('#existcustomers').val('');
$('#create').valid();
swal("This customer is not in our records.", "", "warning");
} else {
$('#apendexistingCustomer').val(ui.item.label);
$('#existcustomers').val(ui.item.key);
$('#create').valid();
getCustomerDet(ui.item.key);
}
},
focus: function(event, ui) {
selectFirst: true;
event.preventDefault();
},
open: function(event, ui) {
$(this).autocomplete("widget")
.appendTo("#results").css({
'position': 'static',
'width': '100%'
});
$('.ui-autocomplete').css('z-index', '9999999');
$('.ui-autocomplete').addClass('srchuser-dropdown');
}
}).data("ui-autocomplete")._renderItem = function(ul, item) {
return $("<li style='height:60px;'><span class='srchuser-downname'>" + item.label + "</span></li>").data("ui-autocomplete-item", item).appendTo(ul);
};
});
this is my function to fetch customer details using autocomplete
protected function getexistingcustomer() {
if (Request::ajax()) {
$data = Request::all();
$searchVal = $data['term'];
if ($searchVal != '') {
$searchResult = customers::searchCustomerAutoComplete(trim($searchVal));
}
$finalArr = array();
if (!empty($searchResult)) {
foreach($searchResult as $vk => $sf) {
$finalArr[$vk]['label'] = $sf['firstname'].
''.$sf['lastname'];
$finalArr[$vk]['key'] = 1;
}
} else {
$finalArr[0]['label'] = 'This customer is not in our records.';
}
print json_encode($finalArr);
exit;
}
}
customer Input field
<div class="row" id="selectcusDiv">
<div class="col-12 col-sm-6 col-md-4">
<div class="form-group">
<label><sub>*</sub>Customers</label>
<div class="select-container">
<input type="text" id="apendexistingCustomer" name="apendexistingCustomer" class="form-control fieldcls">
<input type="hidden" id="existcustomers" name="existcustomers" value="" class="form-control fieldcls">
</div>
</div>
</div>
</div>
Jquery Validation
$('#create').validate({
ignore: [],
rules: {
existcustomers: 'required'
},
messages: {
existcustomers: 'please enter'
}
});
In your javascript add a change listener to the autocomplete element, and check for an empty value. If the value is empty, set the "avoid validation" flag hidden input to 0, then use a required validation rule on that element.
$("#apendexistingCustomer").on("change", function(){
if($(this).val() == ""){
$("#validateFlag").val(0)
}
});
I had the basics "insert numbers, output answer" aspect of this working fine. But i need to put validation into the site so only certain things work. My site upon putting validation in, stopped working altogether, and i dont fully understand why or whats going on.
JS fiddle : http://jsfiddle.net/ufs869wu/
HTML:
<form id="form1" name="form1" method="post" action="">
<label for="txtAge">Age:</label>
<input type="text" class="txtInput" id="txtAge" value="0"/><p id="ageRes"></p>
<br/>
<label for="txtMass">Mass in Lbs:</label>
<input type="text" class="txtInput" id="txtMass" value="0"/>
<br/>
<label for="txtHinch">Height in Inches:</label>
<input type="text" class="txtInput" id="txtHinch" value="0"/>
<br/>
<input type="button" id="btnCalc" value="Calculate"/>
<p id="result2">Result</p>
</form>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script src="BMI.js"></script>
</body>
and JS
// JavaScript Document
$(function () {
//Identify Variables
var txtMass, txtHinch, result;
var isValid = $('#form1').validate().form();
// attach event listener to the toggle button's click event
$('#btnCalc').click(function () {
//Set validator
$.validator.setDefaults({
errorElement: "span",
errorClass: "form_error",
errorPlacement: function(error,element){
error.insertAfter(element)
}
});
$.extend($.validator.messages,{
required: "* Required field"
});
//Set Validation perameters
$("#form1").validate({
rules: {
txtAge: {
required: true,
range: [1, 120],
digits: true
},
txtMass: {
require: true,
digits: true
},
txtHinch: {
requre: true,
digits: true
}
}
});
if (isValid) {
//Set Age range for form accuracy
if (txtAge < 16 || txtAage > 80){
//Output
$('#ageRes').html('Results may not be accurate at your age')
} else { (txtAge >= 16 || txtAge <= 80)
$('#ageRes').html('Results should be accurate considering your age')
//Equation for BMI
result = ($('#txtMass').val() / ($('#txtHinch').val() * $('#txtHinch').val())) * 703;}
//If - Else statement from output of BMI equation
if (result < 16){
$('#result2').html('Result: '+result.toFixed(1) + ' you are Severely underweight')
} else if (result <=18 ){
$('#result2').html('Result: '+result.toFixed(1) + ' you are underweight')
} else if (result <=24){
$('#result2').html('Result: '+result.toFixed(1) + ' you are healthy')
} else if (result <= 30 ){
$('#result2').html('Result: '+result.toFixed(1) + ' you are seriously overweight')
} else if (result <=35 ){
$('#result2').html('Result: '+result.toFixed(1) + ' you are obese')
} else if (result <=40 ){
$('#result2').html('Result: '+result.toFixed(1) + ' you are seriously obese')
}
}
});
});
Thanks for any and all help!
You are calling '$' before jquery has been loaded, and are getting a '$' is undefined error.
Try moving this line up into the head section of your html.
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
Also, are you including the jquery validation plugin somewhere?. I don't see it being included anywhere.
I'm building an icon library where the user on the front end (submitting a form) can select an icon. I managed to get everything working as far as the selection process. Now, the final product will have over 400 icons, and i wanted to add a search (ajax, i guess) or autocomplete input where the user can type a couple of letters and it filter's out those icons.
They search will be filtering out some with a class that has the prefix "icon-".
I started on jsFiddle here: http://jsfiddle.net/yQMvh/28/
an example would be something like this :
http://anthonybush.com/projects/jquery_fast_live_filter/demo/
My HTML Markup:
<div class="iconDisplay">Display's selected icon</div>
<span id="selectedIcon" class="selected-icon" style="display:none"></span>
<button id="selectIconButton">Select Icon</button>
<div id="iconSelector" class="icon-list">
<div id="iconSearch">
<label for="icon-search">Search Icon: </label>
<input type="text" name="icon-search" value="">
</div>
<span class="icon-icon1"></span>
<span class="icon-icon2"></span>
<span class="icon-icon3"></span>
<span class="icon-icon4"></span>
<span class="icon-icon5"></span>
<span class="icon-icon6"></span>
<span class="icon-icon7"></span>
<span class="icon-icon8"></span>
</div>
JS (note: this includes the selection jQuery as well):
var iconVal = $(".icon_field").val();
$('#selectedIcon').addClass(iconVal);
$("#selectIconButton").click(function () {
$("#iconSelector").fadeToggle();
});
$("#iconSelector span").click(function () {
selectIcon($(this));
});
function selectIcon(e) {
var selection = e.attr('class');
$(".icon_field").val(selection);
$("#iconSelector").hide();
$('#selectedIcon').removeClass();
$('#selectedIcon').addClass(selection).show();
return;
}
Will this work for you? http://jsfiddle.net/yQMvh/37/
I've modified your input field slightly (added an id)
<input type="text" id="txt-icon-search" name="icon-search" />
and added this bit of code.
/**
* Holds information about search. (document later)
*/
var search = {
val: '',
icons: function (e) {
// get all the icons.
var icons = $('span[class*="icon-"]');
// assign the search val. (can possibly use later)
search.val = $(e.currentTarget).val();
// let the looping begin!
for (var i = 0, l = icons.length; i < l; i++) {
// get the current element, class, and icon after "icon-"
var el = $(icons[i]),
clazz = el.attr('class'),
iconEnd = clazz.substr(5, clazz.length);
// was the value found within the list of icons?
// if found, show.
// if not found, hide.
(iconEnd.indexOf(search.val) === -1) ? el.hide() : el.show();
}
}
};
$('#txt-icon-search').keyup(search.icons);
One possible way could be to use DataTables, this framework includes a search functionality, its row based tho, could be modified probably. Or if you want to present each icon with some facts like size, name, creator, it would be good maybe. The user could then sort the height etc.
Have a look here
Its a bit heavy weight but have a lot of possibilities for optimization
What you're looking for is something like this: http://jqueryui.com/autocomplete/
Pretty easy and all ready to use. You could pre-populate the available tags with your icons selection. Quick example:
$(function() {
var availableTags = [
"icon-name1",
"icon-name2",
"icon-name3",
"etc."
];
$( "input[name=icon-search]" ).autocomplete({
source: availableTags
});
});
EDIT: of course you can do something much more sophisticated, like displaying a thumbnail/preview of your icon next to each result
EDIT2:
From the sample in your link, I quickly threw something together to have it the way you wanted it:
JSCODE:
<script>
$(function() {
$.expr[':'].Contains = function(a,i,m){
return ($(a).attr("data-index") || "").toUpperCase().indexOf(m[3].toUpperCase())>=0;
};
function listFilter(header, list) {
$("input.filterinput")
.change( function () {
var filter = $(this).val();
if(filter) {
$(list).find("span:not(:Contains(" + filter + "))").parent().slideUp();
$(list).find("span:Contains(" + filter + ")").parent().slideDown();
} else {
$(list).find("li").slideDown();
}
return false;
})
.keyup( function () {
$(this).change();
});
}
$(function () {
listFilter($("#iconSearch"), $("#list"));
});
});
</script>
Your html code tweaked a little:
<div id="iconSelector" class="icon-list" style="display: block;">
<div id="iconSearch">
<label for="icon-search">Search Icon: </label>
<input type="text" name="icon-search" class="filterinput" value="">
</div>
<ul id="list">
<li><span class="icon-icon1" data-index="red"></span></li>
<li><span class="icon-icon2" data-index="yellow"></span></li>
<li><span class="icon-icon3" data-index="blue"></span></li>
</ul>
</div>
Now if you type "red" you'll get the first span since the search is looking for a match from the data-index attribute. You can replace those with "Facebook", "Twitter", or whatever the name of your icon is.
If you want to directly search from the class name you can do something like this then:
<script>
$(function() {
$.expr[':'].Contains = function(a,i,m){
return ($(a).attr("class") || "").toUpperCase().indexOf(m[3].toUpperCase())>=0;
};
function listFilter(header, list) {
$("input.filterinput")
.change( function () {
var filter = "icon-" + $(this).val();
if(filter) {
$(list).find("span:not(:Contains(" + filter + "))").parent().slideUp();
$(list).find("span:Contains(" + filter + ")").parent().slideDown();
} else {
$(list).find("li").slideDown();
}
return false;
})
.keyup( function () {
$(this).change();
});
}
$(function () {
listFilter($("#iconSearch"), $("#list"));
});
});
</script>
I'd like to validate a form using the jquery validate plugin, but I'm unable to use the 'name' value within the html - as this is a field also used by the server app.
Specifically, I need to limit the number of checkboxes checked from a group. (Maximum of 3.) All of the examples I have seen, use the name attribute of each element. What I'd like to do is use the class instead, and then declare a rule for that.
html
This works:
<input class="checkBox" type="checkbox" id="i0000zxthy" name="salutation" value="1" />
This doesn't work, but is what I'm aiming for:
<input class="checkBox" type="checkbox" id="i0000zxthy" name="i0000zxthy" value="1" />
javascript:
var validator = $(".formToValidate").validate({
rules:{
"salutation":{
required:true,
},
"checkBox":{
required:true,
minlength:3 }
}
});
Is it possible to do this - is there a way of targeting the class instead of the name within the rules options? Or do I have to add a custom method?
Cheers,
Matt
You can add the rules based on that selector using .rules("add", options), just remove any rules you want class based out of your validate options, and after calling $(".formToValidate").validate({... });, do this:
$(".checkBox").rules("add", {
required:true,
minlength:3
});
Another way you can do it, is using addClassRules.
It's specific for classes, while the option using selector and .rules is more a generic way.
Before calling
$(form).validate()
Use like this:
jQuery.validator.addClassRules('myClassName', {
required: true /*,
other rules */
});
Ref: http://docs.jquery.com/Plugins/Validation/Validator/addClassRules#namerules
I prefer this syntax for a case like this.
I know this is an old question. But I too needed the same one recently, and I got this question from stackoverflow + another answer from this blog. The answer which was in the blog was more straight forward as it focuses specially for this kind of a validation. Here is how to do it.
$.validator.addClassRules("price", {
required: true,
minlength: 2
});
This method does not require you to have validate method above this call.
Hope this will help someone in the future too. Source here.
Here's the solution using jQuery:
$().ready(function () {
$(".formToValidate").validate();
$(".checkBox").each(function (item) {
$(this).rules("add", {
required: true,
minlength:3
});
});
});
Here's my solution (requires no jQuery... just JavaScript):
function argsToArray(args) {
var r = []; for (var i = 0; i < args.length; i++)
r.push(args[i]);
return r;
}
function bind() {
var initArgs = argsToArray(arguments);
var fx = initArgs.shift();
var tObj = initArgs.shift();
var args = initArgs;
return function() {
return fx.apply(tObj, args.concat(argsToArray(arguments)));
};
}
var salutation = argsToArray(document.getElementsByClassName('salutation'));
salutation.forEach(function(checkbox) {
checkbox.addEventListener('change', bind(function(checkbox, salutation) {
var numChecked = salutation.filter(function(checkbox) { return checkbox.checked; }).length;
if (numChecked >= 4)
checkbox.checked = false;
}, null, checkbox, salutation), false);
});
Put this in a script block at the end of <body> and the snippet will do its magic, limiting the number of checkboxes checked in maximum to three (or whatever number you specify).
Here, I'll even give you a test page (paste it into a file and try it):
<!DOCTYPE html><html><body>
<input type="checkbox" class="salutation">
<input type="checkbox" class="salutation">
<input type="checkbox" class="salutation">
<input type="checkbox" class="salutation">
<input type="checkbox" class="salutation">
<input type="checkbox" class="salutation">
<input type="checkbox" class="salutation">
<input type="checkbox" class="salutation">
<input type="checkbox" class="salutation">
<input type="checkbox" class="salutation">
<script>
function argsToArray(args) {
var r = []; for (var i = 0; i < args.length; i++)
r.push(args[i]);
return r;
}
function bind() {
var initArgs = argsToArray(arguments);
var fx = initArgs.shift();
var tObj = initArgs.shift();
var args = initArgs;
return function() {
return fx.apply(tObj, args.concat(argsToArray(arguments)));
};
}
var salutation = argsToArray(document.getElementsByClassName('salutation'));
salutation.forEach(function(checkbox) {
checkbox.addEventListener('change', bind(function(checkbox, salutation) {
var numChecked = salutation.filter(function(checkbox) { return checkbox.checked; }).length;
if (numChecked >= 3)
checkbox.checked = false;
}, null, checkbox, salutation), false);
});
</script></body></html>
Since for me, some elements are created on page load, and some are dynamically added by the user; I used this to make sure everything stayed DRY.
On submit, find everything with class x, remove class x, add rule x.
$('#form').on('submit', function(e) {
$('.alphanumeric_dash').each(function() {
var $this = $(this);
$this.removeClass('alphanumeric_dash');
$(this).rules('add', {
alphanumeric_dash: true
});
});
});
If you want add Custom method you can do it
(in this case, at least one checkbox selected)
<input class="checkBox" type="checkbox" id="i0000zxthy" name="i0000zxthy" value="1" onclick="test($(this))"/>
in Javascript
var tags = 0;
$(document).ready(function() {
$.validator.addMethod('arrayminimo', function(value) {
return tags > 0
}, 'Selezionare almeno un Opzione');
$.validator.addClassRules('check_secondario', {
arrayminimo: true,
});
validaFormRichiesta();
});
function validaFormRichiesta() {
$("#form").validate({
......
});
}
function test(n) {
if (n.prop("checked")) {
tags++;
} else {
tags--;
}
}
If you need to set up multpile class rules you can do it like this:
jQuery.validator.addClassRules({
name: {
required: true,
minlength: 2
},
zip: {
required: true,
digits: true,
minlength: 5,
maxlength: 5
}
});
source: https://jqueryvalidation.org/jQuery.validator.addClassRules/
Disclaimer: Yes, I know it's 2021 and you shouldn't be using jQuery but, sometimes we have to. This information was really useful to me, so I hope to help some eventual random stranger who has to maintain some legacy system somewhere.
$(".ClassName").each(function (item) {
$(this).rules("add", {
required: true,
});
});