Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

forms

Package Overview
Dependencies
Maintainers
2
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

forms - npm Package Compare versions

Comparing version 0.4.1 to 0.5.0

lib/tag.js

5

CHANGELOG.md

@@ -0,1 +1,6 @@

0.5.0 / 2014-05-01
==================
* Added new form-level validatePastFirstErrorOption. When true, all fields will validate, instead of stopping at the first error.
* Internal refactoring for improved HTML tag generation
0.4.1 / 2014-04-24

@@ -2,0 +7,0 @@ ==================

4

lib/fields.js

@@ -5,6 +5,6 @@ /*jslint node: true */

var forms = require('./forms'),
tag = require('./tag'),
is = require('is'),
async = require('async'),
validators = require('./validators'),
htmlEscape = require('./htmlEscape'),
coerceArray = function (arr) {

@@ -72,3 +72,3 @@ return Array.isArray(arr) && arr.length > 0 ? arr : [];

var classes = typeof this.cssClasses !== 'undefined' ? coerceArray(this.cssClasses.error) : [];
return this.error ? '<p class="' + htmlEscape(['error_msg'].concat(classes).join(' ')) + '">' + this.error + '</p>' : '';
return this.error ? tag('p', { classes: ['error_msg'].concat(classes) }, this.error) : '';
};

@@ -75,0 +75,0 @@ f.labelText = function (name) {

@@ -5,3 +5,3 @@ /*jslint node: true */

var async = require('async'),
is = require('is'),
is = require('is'),
http = require('http'),

@@ -18,3 +18,7 @@ querystring = require('qs'),

exports.create = function (fields) {
exports.create = function (fields, opts) {
if (!opts) { opts = {}; }
var validatePastFirstError = !!opts.validatePastFirstError;
Object.keys(fields).forEach(function (k) {

@@ -51,3 +55,3 @@ // if it's not a field object, create an object field.

b.fields[k] = bound_field;
callback(err);
callback(validatePastFirstError ? null : err);
});

@@ -82,3 +86,3 @@ }, function (err) {

if (err) { throw err; }
fields = querystring.parse(querystring.stringify(fields));
fields = querystring.parse(querystring.stringify(fields));
f.handle(fields, callbacks);

@@ -85,0 +89,0 @@ });

/*jslint node: true */
'use strict';
var htmlEscape = require('./htmlEscape');
var wrapWith = function (tag) {
var tag = require('./tag');
var wrapWith = function (tagName) {
return function (name, field, opt) {
if (!opt) { opt = {}; }
var html = ['<' + tag + ' class="' + htmlEscape(field.classes().join(' ')) + '">'],
errorHTML = field.errorHTML();
var wrappedContent = [];
var errorHTML = field.errorHTML();
if (field.widget.type === 'multipleCheckbox' || field.widget.type === 'multipleRadio') {
html = html.concat([
'<fieldset>',
'<legend>', field.labelText(name), '</legend>',
var fieldset = tag('fieldset', {}, [
tag('legend', {}, field.labelText(name)),
opt.errorAfterField ? '' : errorHTML,
field.widget.toHTML(name, field),
opt.errorAfterField ? errorHTML : '',
'</fieldset>'
]);
opt.errorAfterField ? errorHTML : ''
].join(''));
wrappedContent.push(fieldset);
} else {
html = html.concat([
opt.errorAfterField ? '' : errorHTML,
field.labelHTML(name, field.id),
field.widget.toHTML(name, field),
opt.errorAfterField ? errorHTML : '',
]);
var fieldHTMLs = [field.labelHTML(name, field.id), field.widget.toHTML(name, field)];
if (opt.errorAfterField) { fieldHTMLs.push(errorHTML); }
else { fieldHTMLs.unshift(errorHTML); }
wrappedContent = wrappedContent.concat(fieldHTMLs);
}
return html.join('') + '</' + tag + '>';
return tag(tagName, {
classes: field.classes()
}, wrappedContent.join(''));
};

@@ -36,14 +35,13 @@ };

if (!opt) { opt = {}; }
var th = tag('th', {}, field.labelHTML(name, field.id));
var tdContent = field.widget.toHTML(name, field);
var errorHTML = field.errorHTML();
return [
'<tr class="', htmlEscape(field.classes().join(' ')), '">',
'<th>', field.labelHTML(name, field.id), '</th>',
'<td>',
opt.errorAfterField ? '' : errorHTML,
field.widget.toHTML(name, field),
opt.errorAfterField ? errorHTML : '',
'</td>',
'</tr>'
].join('');
if (opt.errorAfterField) { tdContent += errorHTML; }
else { tdContent = errorHTML + tdContent; }
var td = tag('td', {}, tdContent);
return tag('tr', { classes: field.classes() }, th + td);
};
/*jslint node: true */
'use strict';
var htmlEscape = require('./htmlEscape');
var is = require('is');
var tag = require('./tag');
// generates a string for common widget attributes
var attrs = function (a) {
if (typeof a.id === 'boolean') {
a.id = a.id ? 'id_' + a.name : null;
}
if (Array.isArray(a.classes) && a.classes.length > 0) {
a['class'] = a.classes.join(' ');
}
a.classes = null;
var pairs = [];
Object.keys(a).map(function (field) {
var value = a[field];
if (typeof value === 'boolean') {
value = value ? field : null;
} else if (typeof value === 'string' && value.length === 0) {
value = null;
} else if (typeof value === 'number' && isNaN(value)) {
value = null;
}
if (typeof value !== 'undefined' && value !== null) {
pairs.push(htmlEscape(field) + '="' + htmlEscape(value) + '"');
}
});
return pairs.length > 0 ? ' ' + pairs.join(' ') : '';
};
var tag = function tag(tagName, attrsMap, content) {
tagName = htmlEscape(tagName);
var attrsHTML = !Array.isArray(attrsMap) ? attrs(attrsMap) : attrsMap.reduce(function (html, attrsMap) {
return html + attrs(attrsMap);
}, '');
return '<' + tagName + attrsHTML + '>' + content + '</' + tagName + '>';
};
var singleTag = function tag(tagName, attrsMap) {
tagName = htmlEscape(tagName);
var attrsHTML = !Array.isArray(attrsMap) ? attrs(attrsMap) : attrsMap.reduce(function (html, attrsMap) {
return html + attrs(attrsMap);
}, '');
return '<' + tagName + attrsHTML + ' />';
};
// used to generate different input elements varying only by type attribute
var input = function (type) {
var dataRegExp = /^data-[a-z]+$/,
var dataRegExp = /^data-[a-z]+([-][a-z]+)*$/,
ariaRegExp = /^aria-[a-z]+$/,

@@ -74,3 +33,3 @@ legalAttrs = ['autocomplete', 'autocorrect', 'autofocus', 'autosuggest', 'checked', 'dirname', 'disabled', 'tabindex', 'list', 'max', 'maxlength', 'min', 'multiple', 'novalidate', 'pattern', 'placeholder', 'readonly', 'required', 'size', 'step'],

if (!f) { f = {}; }
return singleTag('input', [{
return tag('input', [{
type: type,

@@ -135,3 +94,3 @@ name: name,

if (!f) { f = {}; }
return singleTag('input', [{
return tag('input', [{
type: 'checkbox',

@@ -203,3 +162,3 @@ name: name,

html += singleTag('input', [{
html += tag('input', [{
type: 'checkbox',

@@ -249,3 +208,3 @@ name: name,

html += singleTag('input', [{
html += tag('input', [{
type: 'radio',

@@ -252,0 +211,0 @@ name: name,

@@ -6,3 +6,3 @@ {

"author": "Caolan McMahon",
"version": "0.4.1",
"version": "0.5.0",
"repository": {

@@ -22,3 +22,3 @@ "type": "git",

"dependencies": {
"async": "~0.7.0",
"async": "~0.8.0",
"qs": "~0.6.5",

@@ -25,0 +25,0 @@ "formidable": "~1.0.14",

@@ -210,3 +210,10 @@ # Forms <sup>[![Version Badge][9]][8]</sup>

#### forms.create(fields, options)
Forms can be created with an optional "options" object as well.
#### Supported options:
* `validatePastFirstError`: `true`, otherwise assumes `false`
* If `false`, the first validation error will halt form validation.
* If `true`, all fields will be validated.
### Form object

@@ -213,0 +220,0 @@

@@ -332,2 +332,40 @@ /*jslint node: true */

test('validation stops on first error', function (t) {
t.plan(3);
var f = forms.create({
field1: forms.fields.string({ required: true }),
field2: forms.fields.string({ required: true }),
field3: forms.fields.string({ required: true })
});
f.handle({ field1: 'test' }, {
error: function(form) {
t.equal(form.fields.field1.error, undefined);
t.equal(form.fields.field2.error, 'field2 is required.');
t.equal(form.fields.field3.error, undefined);
t.end();
}
});
});
test('validates past first error with validatePastFirstError option', function (t) {
t.plan(3);
var f = forms.create({
field1: forms.fields.string({ required: true }),
field2: forms.fields.string({ required: true }),
field3: forms.fields.string({ required: true })
}, {
validatePastFirstError: true
});
f.handle({ field1: 'test' }, {
error: function(form) {
t.equal(form.fields.field1.error, undefined);
t.equal(form.fields.field2.error, 'field2 is required.');
t.equal(form.fields.field3.error, 'field3 is required.');
t.end();
}
});
});
test('handle ServerRequest POST with bodyDecoder', function (t) {

@@ -334,0 +372,0 @@ t.plan(1);

@@ -183,14 +183,14 @@ /*jslint node: true */

t.plan(4);
validators.url(false, 'URL was invalid.')('form', {data: 'asdf.com'}, function (err) {
t.equal(err, 'URL was invalid.');
validators.url()('form', {data: 'http://asdf.com'}, function (err) {
t.equal(err, undefined);
});
});
validators.url(true)('form', {data: 'localhost/test.html'}, function (err) {
t.equal(err, 'Please enter a valid URL.');
validators.url(true)('form', {data: 'http://localhost/test.html'}, function (err) {
t.equal(err, undefined);
});
});
validators.url(false, 'URL was invalid.')('form', {data: 'asdf.com'}, function (err) {
t.equal(err, 'URL was invalid.');
validators.url()('form', {data: 'http://asdf.com'}, function (err) {
t.equal(err, undefined);
});
});
validators.url(true)('form', {data: 'localhost/test.html'}, function (err) {
t.equal(err, 'Please enter a valid URL.');
validators.url(true)('form', {data: 'http://localhost/test.html'}, function (err) {
t.equal(err, undefined);
});
});
t.end();

@@ -201,14 +201,14 @@ });

t.plan(4);
validators.date('Date input must contain a valid date.')('form', {data: '02/28/2012'}, function (err) {
t.equal(err, 'Date input must contain a valid date.');
validators.date()('form', {data: '2012-02-28'}, function (err) {
t.equal(err, undefined);
});
});
validators.date()('form', {data: '2012.02.30'}, function (err) {
t.equal(err, 'Inputs of type "date" must be valid dates in the format "yyyy-mm-dd"');
validators.date()('form', {data: '2012-02-30'}, function (err) {
t.equal(err, undefined);
});
});
validators.date('Date input must contain a valid date.')('form', {data: '02/28/2012'}, function (err) {
t.equal(err, 'Date input must contain a valid date.');
validators.date()('form', {data: '2012-02-28'}, function (err) {
t.equal(err, undefined);
});
});
validators.date()('form', {data: '2012.02.30'}, function (err) {
t.equal(err, 'Inputs of type "date" must be valid dates in the format "yyyy-mm-dd"');
validators.date()('form', {data: '2012-02-30'}, function (err) {
t.equal(err, undefined);
});
});
t.end();

@@ -241,14 +241,14 @@ });

t.plan(4);
validators.rangelength(2, 4, 'Enter between %s and %s characters.')('form', {data: '12345'}, function (err) {
t.equal(err, 'Enter between 2 and 4 characters.');
});
validators.rangelength(2, 4)('form', {data: '1'}, function (err) {
t.equal(err, 'Please enter a value between 2 and 4 characters long.');
});
validators.rangelength(2, 4)('form', {data: '12'}, function (err) {
t.equal(err, undefined);
});
validators.rangelength(2, 4)('form', {data: '1234'}, function (err) {
t.equal(err, undefined);
});
validators.rangelength(2, 4, 'Enter between %s and %s characters.')('form', {data: '12345'}, function (err) {
t.equal(err, 'Enter between 2 and 4 characters.');
});
validators.rangelength(2, 4)('form', {data: '1'}, function (err) {
t.equal(err, 'Please enter a value between 2 and 4 characters long.');
});
validators.rangelength(2, 4)('form', {data: '12'}, function (err) {
t.equal(err, undefined);
});
validators.rangelength(2, 4)('form', {data: '1234'}, function (err) {
t.equal(err, undefined);
});
t.end();

@@ -255,0 +255,0 @@ });

@@ -296,2 +296,4 @@ /*jslint node: true */

t.equal(re.test('data_input'), false);
t.equal(re.test('data--'), false);
t.equal(re.test('data-foo-bar'), true);
t.end();

@@ -298,0 +300,0 @@ });

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc