Skip to content

Commit ad5b61c

Browse files
Initial checkin
1 parent 5797eae commit ad5b61c

File tree

3 files changed

+256
-0
lines changed

3 files changed

+256
-0
lines changed

README.markdown

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
Easy Checkbox Required
2+
======================
3+
4+
One pain point in HTML5 validation is checkbox groups as you cannot simply
5+
use the `require`" attribute as it would require the inclusion of each
6+
checkbox that is part of the group. This script fixes that by using a data
7+
attribute -- `data-checkbox-required` -- to indicate the requirement.
8+
9+
Adding the `data-checkbox-required` attribute to one or more checkboxes
10+
in a group would require at least one checkbox be chosen, but you can
11+
specify lower and upper bounds by giving a value to the attribute. For
12+
example:
13+
14+
<input type="checkbox" name="test[]" value="1"
15+
data-checkbox-required="3"
16+
>
17+
18+
Would require at least 3 checkboxes in the group be checked
19+
20+
<input type="checkbox" name="test[]" value="1"
21+
data-checkbox-required="3-5"
22+
>
23+
24+
Would require at least 3, but no more than 5 checkboxes in the group be
25+
checked.
26+
27+
<input type="checkbox" name="test[]" value="1"
28+
data-checkbox-required="0-5"
29+
>
30+
31+
Would require any number (including 0), up to 5 checkboxes in the group
32+
be checked.

dist/jquery.easy-checkbox-required.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/jquery.easy-checkbox-required.js

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
/*! Easy Checkbox Required (c) Aaron Gustafson (@AaronGustafson). MIT License. http://github.com/easy-designs/easy-checkbox-required.js */
2+
3+
/* Easy Checkbox Required API
4+
*
5+
* One pain point in HTML5 validation is checkbox groups as you cannot simply
6+
* use the "required" attribute as it would require the inclusion of each
7+
* checkbox that is part of the group. This script fixes that by using a data
8+
* attribute -- `data-checkbox-required` -- to indicate the requirement.
9+
*
10+
* Adding the `data-checkbox-required` attribute to one or more checkboxes
11+
* in a group would require at least one checkbox be chosen, but you can
12+
* specify lower and upper bounds by giving a value to the attribute. For
13+
* example:
14+
*
15+
* <input type="checkbox" name="test[]" value="1"
16+
* data-checkbox-required="3" />
17+
*
18+
* Would require at least 3 checkboxes in the group be checked
19+
*
20+
* <input type="checkbox" name="test[]" value="1"
21+
* data-checkbox-required="3-5" />
22+
*
23+
* Would require at least 3, but no more than 5 checkboxes in the group be
24+
* checked.
25+
*
26+
* <input type="checkbox" name="test[]" value="1"
27+
* data-checkbox-required="0-5" />
28+
*
29+
* Would require any number (including 0), up to 5 checkboxes in the group
30+
* be checked.
31+
*
32+
**/
33+
;(function( $, UNDEFINED ){
34+
35+
// jQuery Requirement
36+
if ( $ == UNDEFINED ){ return; }
37+
38+
var script_name = 'checkbox-required',
39+
selector = '[data-' + script_name + ']',
40+
error_key = script_name + '-error',
41+
container = 'form > ol > li, fieldset > ol > li',
42+
ERROR = 'validation-error',
43+
html5_validation = (function( props ){
44+
45+
var input = document.createElement('input');
46+
if ( typeof(input.setCustomValidity) != 'function' )
47+
{
48+
return false;
49+
}
50+
return true;
51+
}()),
52+
set_error = function(){},
53+
remove_error = function(){};
54+
55+
if ( html5_validation )
56+
{
57+
set_error = function( field, message )
58+
{
59+
field.setCustomValidity( message );
60+
};
61+
remove_error = function( field )
62+
{
63+
field.setCustomValidity( '' );
64+
};
65+
}
66+
// < HTML5 Errors
67+
else
68+
{
69+
set_error = function( field, message )
70+
{
71+
$(field).data( error_key, message );
72+
};
73+
remove_error = function( field )
74+
{
75+
$(field).removeData( error_key );
76+
};
77+
}
78+
79+
function check_validity( e )
80+
{
81+
var $form = $(this).closest('form'),
82+
single_template = $form.data( script_name + '-message-template-single' ) || 'Please choose an option',
83+
min_template = $form.data( script_name + '-message-template-min' ) || 'Please choose at least {min} options',
84+
range_template = $form.data( script_name + '-message-template-range' ) || 'Please choose {min}-{max} options',
85+
max_template = $form.data( script_name + '-message-template-max' ) || 'Please choose at most {max} options',
86+
validated = [],
87+
error = false; // optimism
88+
89+
$form.find(selector).each(function(){
90+
91+
var $field = $(this),
92+
name = $field.attr('name'),
93+
required,
94+
checked,
95+
message;
96+
97+
remove_error( this );
98+
99+
// only once per name
100+
if ( $.inArray( name, validated ) != -1 )
101+
{
102+
return;
103+
}
104+
validated.push( name );
105+
106+
// get the count
107+
required = $field.data( script_name ).toString().split('-');
108+
checked = $field.closest('form').find('[type=checkbox][name="' + name + '"]:checked').length;
109+
110+
// empty defaults to one
111+
if ( required == '' )
112+
{
113+
required = [1];
114+
}
115+
116+
// minimum
117+
if ( checked < required[0] )
118+
{
119+
error = true;
120+
}
121+
122+
// maximum
123+
if ( error === false &&
124+
required[1] != UNDEFINED &&
125+
checked > required[1] )
126+
{
127+
error = true;
128+
}
129+
130+
if ( error )
131+
{
132+
if ( required[1] == UNDEFINED )
133+
{
134+
message = required[0] == 1 ? single_template : min_template;
135+
}
136+
else
137+
{
138+
message = required[0] == 0 ? max_template : range_template;
139+
}
140+
141+
message = message
142+
.replace( '{min}', required[0] )
143+
.replace( '{max}', required[1] );
144+
145+
set_error( this, message );
146+
147+
return false;
148+
}
149+
150+
});
151+
152+
}
153+
154+
function validate_form( e )
155+
{
156+
157+
var $form = $(this),
158+
has_validation_error = false,
159+
validated = [];
160+
161+
$form.find(selector).each(function(){
162+
163+
var field = this,
164+
$field = $(field),
165+
name = $field.attr('name');
166+
167+
// only once per name
168+
if ( $.inArray( name, validated ) != -1 )
169+
{
170+
return;
171+
}
172+
validated.push( name );
173+
174+
if ( $field.data( error_key ) != UNDEFINED )
175+
{
176+
has_validation_error = true;
177+
$field.closest( container )
178+
.addClass( ERROR );
179+
}
180+
else
181+
{
182+
$field.closest( container )
183+
.removeClass( ERROR );
184+
}
185+
186+
});
187+
188+
// return false if there’s an error (to stop form submission)
189+
return ! has_validation_error;
190+
}
191+
192+
// loop through the fields
193+
$(selector).each(function(){
194+
195+
// find the form
196+
var $form = $(this).closest('form');
197+
198+
// only assign one event handler per form
199+
if ( $form.data(script_name) )
200+
{
201+
return;
202+
}
203+
204+
$form
205+
// native validation requires assigning validity
206+
.on( 'script::load', check_validity )
207+
.on( 'change', selector, check_validity )
208+
209+
// note that this form is already being watched
210+
.data( script_name, true )
211+
212+
// init the validation
213+
.triggerHandler('script::load');
214+
215+
// non-HTML5 validation requires tweaks on submit
216+
if ( ! html5_validation )
217+
{
218+
$form.on( 'submit', validate_form );
219+
}
220+
221+
});
222+
223+
}(jQuery));

0 commit comments

Comments
 (0)