Skip to content

Commit 9ac9a1a

Browse files
committed
Issue victorjonsson#315: Remove special case for <input type="number"/>
* Add tests for input type=number * Change spacing for better legibility * Remove statement in core-validators which always evaluated to true * Remove unnecessary if-else branch checking for data-validation-optional If a value is entered into an input type=number that the browser cannot parse, the browser sets the value of it to an empty string. This means that we can't tell the difference between a browser-unparsable input and an empty input.
1 parent dc9222b commit 9ac9a1a

File tree

4 files changed

+96
-50
lines changed

4 files changed

+96
-50
lines changed

form-validator/src/core-validators.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,10 @@
190190
// Fix for checking range with floats using ,
191191
val = val.replace(',', '.');
192192
}
193-
194-
if (allowing.indexOf('number') > -1 && val.replace(/[0-9-]/g, '') === '' && (!allowsRange || (val >= begin && val <= end)) && (!allowsSteps || (val % steps === 0))) {
193+
if (val.replace(/[0-9-]/g, '') === '' && (!allowsRange || (val >= begin && val <= end)) && (!allowsSteps || (val % steps === 0))) {
195194
return true;
196195
}
196+
197197
if (allowing.indexOf('float') > -1 && val.match(new RegExp('^([0-9-]+)\\.([0-9]+)$')) !== null && (!allowsRange || (val >= begin && val <= end)) && (!allowsSteps || (val % steps === 0))) {
198198
return true;
199199
}

form-validator/src/utils.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,11 +288,19 @@
288288
}
289289
}
290290

291+
292+
// For input type="number", browsers attempt to parse the entered value into a number.
293+
// If the input is not numeric, browsers handle the situation differently:
294+
// Chrome 48 simply disallows non-numeric input; FF 44 clears out the input box on blur;
295+
// Safari 5 parses the entered string to find a leading number.
296+
// If the input fails browser validation, the browser sets the input value equal to an empty string.
297+
// Therefore, we cannot distinguish (apart from hacks) between an empty input type="text" and one with a
298+
// value that can't be parsed by the browser.
299+
291300
// validation checkpoint
292301
// if empty AND optional attribute is present
293302
// OR depending on a checkbox being checked AND checkbox is checked, return true
294-
var isInvalidNumberInput = !value && $elem[0].type === 'number';
295-
if ((!value && optional === 'true' && !isInvalidNumberInput) || (validationDependsOnCheckedInput && !validationDependentInputIsChecked)) {
303+
if ((!value && optional === 'true') || (validationDependsOnCheckedInput && !validationDependentInputIsChecked)) {
296304
result.shouldChangeDisplay = conf.addValidClassOnAll;
297305
return result;
298306
}

test/form.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,10 @@ <h2>HTML5 attributes</h2>
307307
<label class="control-label">type="number"</label>
308308
<input type="number" required="required" maxlength="30" />
309309
</div>
310+
<div class="form-group">
311+
<label class="control-label">type="number" (optional)</label>
312+
<input type="number" data-validation-optional="true"/>
313+
</div>
310314
<div class="form-group">
311315
<label class="control-label">type="number" range[-5;5]</label>
312316
<input type="number" min="-5" max="5" required="required" />

test/qunit.html

Lines changed: 80 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@
2424
function input(val, dataValidationAttr, elAttr) {
2525
if(!elAttr)
2626
elAttr = {};
27-
if( typeof dataValidationAttr == 'string') {
27+
if( typeof dataValidationAttr === 'string') {
2828
elAttr['data-validation'] = dataValidationAttr;
2929
} else if(dataValidationAttr) {
3030
$.each(dataValidationAttr, function(x, val) {
31-
if( x == '' ) {
31+
if( x === '' ) {
3232
elAttr['data-validation'] = val;
3333
} else {
3434
elAttr['data-validation-'+x] = val;
@@ -51,31 +51,18 @@
5151
var result = $.formUtils.validateInput($el, $.formUtils.LANG, $.formUtils.defaultConfig(), $form);
5252

5353
var message;
54-
if( typeof obj.val == 'string' ) {
54+
if (typeof obj.val === 'string' ) {
5555
message = 'Check that "'+obj.val+'" is '+(obj.isValid ? 'valid':'invalid');
56-
} else {
56+
}
57+
else {
5758
message = 'Check that input[value="'+obj.val.attr('value')+'"] is '+(obj.isValid ? 'valid':'invalid');
5859
}
5960

60-
if( !result.shouldChangeDisplay && obj.isValid ) {
61-
equal(
62-
null,
63-
null,
64-
message
65-
);
61+
if (!result.shouldChangeDisplay && obj.isValid ) {
62+
equal(null, null, message);
6663
}
67-
else if( $el.attr('data-validation-optional') && !$el.val() ) {
68-
equal(
69-
null,
70-
null,
71-
message
72-
);
73-
} else {
74-
equal(
75-
result.isValid,
76-
obj.isValid,
77-
message
78-
);
64+
else {
65+
equal(result.isValid, obj.isValid, message);
7966
}
8067
}
8168

@@ -460,42 +447,89 @@
460447
});
461448

462449
/*
463-
* NUMBER VALIDATION
450+
* NUMBER VALIDATION type=text (HTML4)
464451
*/
465-
test("Number validation", function() {
452+
test('Number validation for <input type=text"/>', function() {
466453

467454
clearForm();
468455

469456
var links = [
470-
{val:'123', isValid:true},
471-
{val:'', isValid:false},
472-
{val:'asdfsd', isValid:false},
473-
{val:'-123', isValid:false},
474-
{val:input('-123', {'allowing':'negative', '':'number'}), isValid:true},
475-
{val:'1.032', isValid:false},
476-
{val:input('1.023', {'allowing':'float', '':'number'}), isValid:true},
477-
{val:'-1.032', isValid:false},
478-
{val:input('-1.023', {'allowing':'float,negative', '':'number'}), isValid:true},
479-
{val:input('1.0234', {'allowing':'float,negative', '':'number'}), isValid:true},
480-
{val:input('1.0235', {'allowing':'float,negative,number', '':'number'}), isValid:true},
481-
{val:input('1.0236', {'allowing':'float,negative,number', 'decimal-separator':',', '':'number'}), isValid:false},
482-
{val:input('1,023', {'allowing':'float,negative,number', 'decimal-separator':',', '':'number'}), isValid:true},
483-
{val:'123', isValid:true},
484-
{val:input('12', {'allowing':'range[1;10]', '':'number'}), isValid:false},
485-
{val:input('-1', {'allowing':'range[1;10]', '':'number'}), isValid:false},
486-
{val:input('1', {'allowing':'range[1;10]', '':'number'}), isValid:true},
487-
{val:input('10', {'allowing':'range[1;10]', '':'number'}), isValid:true},
488-
{val:input('5', {'allowing':'range[1;10]', '':'number'}), isValid:true},
489-
{val:input('-1', {'allowing':'range[-10;10],negative', '':'number'}), isValid:true},
490-
{val:input('0.0001', {'allowing':'range[0.05;0.9]', '':'number'}), isValid:false},
491-
{val:input('0.06', {'allowing':'range[0.05;0.9],float', '':'number'}), isValid:true}
457+
{val: '123', isValid: true},
458+
{val: '', isValid: false},
459+
{val: 'asdfsd', isValid: false},
460+
{val: '-123', isValid: false},
461+
{val: '1.032', isValid: false},
462+
{val: '-1.032', isValid: false},
463+
{val: input('-123' , {'allowing': 'negative', '': 'number'}), isValid: true},
464+
{val: input('-1', {'allowing': 'range[-10;10],negative', '': 'number'}), isValid: true},
465+
//Test ranges
466+
{val: input('12', {'allowing': 'range[1;10]', '':'number'}), isValid: false},
467+
{val: input('-1', {'allowing': 'range[1;10]', '':'number'}), isValid: false},
468+
{val: input('1', {'allowing': 'range[1;10]', '':'number'}), isValid: true},
469+
{val: input('10', {'allowing': 'range[1;10]', '':'number'}), isValid: true},
470+
{val: input('5', {'allowing': 'range[1;10]', '':'number'}), isValid: true},
471+
{val: input('', {'optional': true, '': 'number' }), isValid: true},
472+
//Test floats
473+
{val: input('1.023' , {'allowing': 'float', '': 'number'}), isValid: true},
474+
{val: input('-1.023', {'allowing': 'float,negative', '': 'number'}), isValid: true},
475+
{val: input('1.0234', {'allowing': 'float,negative', '': 'number'}), isValid: true},
476+
{val: input('1.0235', {'allowing': 'float,negative,number', '': 'number'}), isValid: true},
477+
{val: input('1.0236', {'allowing': 'float,negative,number', 'decimal-separator': ',',
478+
'': 'number'}), isValid: false},
479+
{val: input('1,023', {'allowing': 'float,negative,number', 'decimal-separator':',',
480+
'': 'number'}), isValid: true},
481+
{val: input('0.0001', {'allowing': 'range[0.05;0.9]', '': 'number'}), isValid: false},
482+
{val: input('0.06', {'allowing': 'range[0.05;0.9],float', '': 'number'}), isValid: true}
492483
];
493484

494485
$.each(links, function(i, obj) {
495486
runTest(obj, 'number');
496487
});
497488
});
498489

490+
/**
491+
* NUMBER VALIDATION for type = "number" (HTML5)
492+
*/
493+
test('Number validation for <input type="number"/>', function () {
494+
clearForm();
495+
var links = [];
496+
var numberType = {type: 'number'};
497+
links.push(
498+
{val: input('123', {'': 'number'}, numberType), isValid: true},
499+
{val: input('', {'': 'number'}, numberType), isValid: false},
500+
{val: input('asdfsd', {'': 'number'}, numberType), isValid: false},
501+
{val: input('-123', {'': 'number'}, numberType), isValid: false},
502+
{val: input('1.032', {'': 'number'}, numberType), isValid: false},
503+
{val: input('-1.032', {'': 'number'}, numberType), isValid: false},
504+
{val: input('-123' , {'allowing': 'negative', '': 'number'}, numberType), isValid: true},
505+
{val: input('', {'optional': true, '': 'number' }, numberType), isValid: true},
506+
//Test ranges
507+
{val: input('12', {'allowing': 'range[1;10]', '':'number'}, numberType), isValid: false},
508+
{val: input('-1', {'allowing': 'range[1;10]', '':'number'}, numberType), isValid: false},
509+
{val: input('1', {'allowing': 'range[1;10]', '':'number'}, numberType), isValid: true},
510+
{val: input('10', {'allowing': 'range[1;10]', '':'number'}, numberType), isValid: true},
511+
{val: input('5', {'allowing': 'range[1;10]', '':'number'}, numberType), isValid: true},
512+
{val: input('-1', {'allowing': 'range[-10;10],negative', '': 'number'}, numberType), isValid: true},
513+
//Test floats
514+
{val: input('1.023' , {'allowing': 'float', '': 'number'}, numberType), isValid: true},
515+
{val: input('-1.023', {'allowing': 'float,negative', '': 'number'}, numberType), isValid: true},
516+
{val: input('1.0234', {'allowing': 'float,negative', '': 'number'}, numberType), isValid: true},
517+
{val: input('1.0235', {'allowing': 'float,negative,number', '': 'number'}, numberType), isValid: true},
518+
{val: input('1.0236', {'allowing': 'float,negative,number', 'decimal-separator': ',',
519+
'': 'number'}, numberType), isValid: false},
520+
{val: input('0.0001', {'allowing': 'range[0.05;0.9]', '': 'number'}, numberType), isValid: false},
521+
{val: input('0.06', {'allowing': 'range[0.05;0.9],float', 'decimal-separator': '.',
522+
'': 'number'}, numberType), isValid: true}
523+
);
524+
/* Tests that fail with HTML input type number because of bugs in how browsers handle decimal separators:
525+
{val: input('1,023', {'allowing': 'float,negative,number', 'decimal-separator':',',
526+
'': 'number'}, {'lang': 'no', type: 'number'}), isValid: true},
527+
*/
528+
529+
$.each(links, function(i, obj) {
530+
runTest(obj, 'number');
531+
});
532+
});
499533
/*
500534
* DATE VALIDATION
501535
*/

0 commit comments

Comments
 (0)