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

form-serialize

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

form-serialize - npm Package Compare versions

Comparing version 0.6.0 to 0.7.0

.editorconfig

4

History.md

@@ -0,1 +1,5 @@

# 0.7.0 (2015-10-17)
* add bracket notation support for hash serialization
# 0.6.0 (2015-02-23)

@@ -2,0 +6,0 @@

201

index.js

@@ -11,6 +11,4 @@ // get successful control from form and assemble into object

// keys with brackets for hash keys
var object_brackets_regex = /\[(.+?)\]/g;
var array_brackets_regex = /\[\]$/;
var brackeks_prefix_regex = /^(.+?)\[/;
// Matches bracket notation.
var brackets = /(\[[^\[\]]*\])/g;

@@ -39,3 +37,3 @@ // serializes form fields

var elements = form.elements || [];
var elements = form && form.elements ? form.elements : [];

@@ -66,3 +64,3 @@ //Object store each radio and set if it's empty or not

}
// If we want empty elements

@@ -78,6 +76,6 @@ if (options.empty) {

if (!radio_store[element.name] && !element.checked) {
radio_store[element.name] = false
radio_store[element.name] = false;
}
else if (element.checked) {
radio_store[element.name] = true
radio_store[element.name] = true;
}

@@ -106,5 +104,18 @@ }

var option = selectOptions[j];
if (option.selected) {
isSelectedOptions = true
result = serializer(result, key, option.value);
var allowedEmpty = options.empty && !option.value;
var hasValue = (option.value || allowedEmpty);
if (option.selected && hasValue) {
isSelectedOptions = true;
// If using a hash serializer be sure to add the
// correct notation for an array in the multi-select
// context. Here the name attribute on the select element
// might be missing the trailing bracket pair. Both names
// "foo" and "foo[]" should be arrays.
if (options.hash && key.slice(key.length - 2) !== '[]') {
result = serializer(result, key + '[]', option.value);
}
else {
result = serializer(result, key, option.value);
}
}

@@ -117,5 +128,6 @@ }

}
continue;
}
result = serializer(result, key, val);

@@ -136,22 +148,64 @@ }

// obj/hash encoding serializer
function hash_serializer(result, key, value) {
var is_array_key = has_array_brackets(key);
if (is_array_key) {
key = key.replace(array_brackets_regex, '');
function parse_keys(string) {
var keys = [];
var prefix = /^([^\[\]]*)/;
var children = new RegExp(brackets);
var match = prefix.exec(string);
if (match[1]) {
keys.push(match[1]);
}
if (key in result) {
var existing = result[key];
if (!Array.isArray(existing)) {
result[key] = [existing];
while ((match = children.exec(string)) !== null) {
keys.push(match[1]);
}
return keys;
}
function hash_assign(result, keys, value) {
if (keys.length === 0) {
result = value;
return result;
}
var key = keys.shift();
var between = key.match(/^\[(.+?)\]$/);
if (key === '[]') {
result = result || [];
if (Array.isArray(result)) {
result.push(hash_assign(null, keys, value));
}
result[key].push(value);
else {
// This might be the result of bad name attributes like "[][foo]",
// in this case the original `result` object will already be
// assigned to an object literal. Rather than coerce the object to
// an array, or cause an exception the attribute "_values" is
// assigned as an array.
result._values = result._values || [];
result._values.push(hash_assign(null, keys, value));
}
return result;
}
// Key is an attribute name and can be assigned directly.
if (!between) {
result[key] = hash_assign(result[key], keys, value);
}
else {
if (has_object_brackets(key)) {
extract_from_brackets(result, key, value);
var string = between[1];
var index = parseInt(string, 10);
// If the characters between the brackets is not a number it is an
// attribute name and can be assigned directly.
if (isNaN(index)) {
result = result || {};
result[string] = hash_assign(result[string], keys, value);
}
else {
result[key] = is_array_key ? [value] : value;
result = result || [];
result[index] = hash_assign(result[index], keys, value);
}

@@ -161,76 +215,51 @@ }

return result;
};
// urlform encoding serializer
function str_serialize(result, key, value) {
// encode newlines as \r\n cause the html spec says so
value = value.replace(/(\r)?\n/g, '\r\n');
value = encodeURIComponent(value);
// spaces should be '+' rather than '%20'.
value = value.replace(/%20/g, '+');
return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + value;
};
function has_object_brackets(string) {
return string.match(object_brackets_regex);
};
function has_array_brackets(string) {
return string.match(array_brackets_regex);
}
function matches_between_brackets(string) {
// Make sure to isolate object_brackets_regex from .exec() calls
var regex = new RegExp(object_brackets_regex);
var matches = [];
var match;
// Object/hash encoding serializer.
function hash_serializer(result, key, value) {
var matches = key.match(brackets);
while (match = regex.exec(string)) {
matches.push(match[1]);
// Has brackets? Use the recursive assignment function to walk the keys,
// construct any missing objects in the result tree and make the assignment
// at the end of the chain.
if (matches) {
var keys = parse_keys(key);
hash_assign(result, keys, value);
}
else {
// Non bracket notation can make assignments directly.
var existing = result[key];
return matches;
};
function extract_from_brackets(result, key, value) {
var prefix = key.match(brackeks_prefix_regex)[1];
// Set the key if it doesn't exist
if (! result[prefix]) result[prefix] = {};
var parent = result[prefix];
var matches_between = matches_between_brackets(key);
var length = matches_between.length;
for (var i = 0; i < length; i++) {
var child = matches_between[i];
var isLast = (length === i + 1);
if (isLast) {
var existing = parent[child];
if (existing) {
if (! Array.isArray(existing)) {
parent[child] = [ existing ];
}
parent[child].push(value);
// If the value has been assigned already (for instance when a radio and
// a checkbox have the same name attribute) convert the previous value
// into an array before pushing into it.
//
// NOTE: If this requirement were removed all hash creation and
// assignment could go through `hash_assign`.
if (existing) {
if (!Array.isArray(existing)) {
result[key] = [ existing ];
}
else {
// Finally make the assignment
parent[child] = value;
}
result[key].push(value);
}
else {
// This is a nested key, set it properly for the next iteration
parent[child] = parent[child] || {};
parent = parent[child];
result[key] = value;
}
}
parent = value;
};
return result;
}
// urlform encoding serializer
function str_serialize(result, key, value) {
// encode newlines as \r\n cause the html spec says so
value = value.replace(/(\r)?\n/g, '\r\n');
value = encodeURIComponent(value);
// spaces should be '+' rather than '%20'.
value = value.replace(/%20/g, '+');
return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + value;
}
module.exports = serialize;
{
"name": "form-serialize",
"version": "0.6.0",
"version": "0.7.0",
"description": "serialize html forms",

@@ -11,3 +11,3 @@ "main": "index.js",

"domify": "~1.0.0",
"zuul": "~1.15.1"
"zuul": "~3.6.0"
},

@@ -14,0 +14,0 @@ "scripts": {

@@ -93,2 +93,50 @@ # form-serialize [![Build Status](https://travis-ci.org/defunctzombie/form-serialize.png?branch=master)](https://travis-ci.org/defunctzombie/form-serialize)

### indexed arrays
Adding numbers between brackets for the array notation above will result in a hash serialization with explicit ordering based on the index number regardless of element ordering.
Like the "[explicit array fields](explicit-array-fields)" this does not affect url-encoding mode output in any way.
```html
<form id="todos-form">
<input type="text" name="todos[1]" value="milk" />
<input type="text" name="todos[0]" value="eggs" />
<input type="text" name="todos[2]" value="flour" />
</form>
```
```js
var serialize = require('form-serialize');
var form = document.querySelector('#todos-form');
var obj = serialize(form, { hash: true });
// obj -> { todos: ['eggs', 'milk', 'flour'] }
var str = serialize(form);
// str -> "todos[1]=milk&todos[0]=eggs&todos[2]=flour"
```
### nested objects
Similar to the indexed array notation, attribute names can be added by inserting a string value between brackets. The notation can be used to create deep objects and mixed with the array notation.
Like the "[explicit array fields](explicit-array-fields)" this does not affect url-encoding mode output.
```html
<form id="nested-example">
<input type="text" name="foo[bar][baz]" value="qux" />
<input type="text" name="foo[norf][]" value="item 1" />
</form>
```
```js
var serialize = require('form-serialize');
var form = document.querySelector('#todos-form');
var obj = serialize(form, { hash: true });
// obj -> { foo: { bar: { baz: 'qux' } }, norf: [ 'item 1' ] }
```
## references

@@ -95,0 +143,0 @@

@@ -26,3 +26,18 @@ var assert = require('assert');

test('nothing', function() {
test('null form', function() {
hash_check(null, {});
str_check(null, '');
empty_check(null, '');
empty_check_hash(null, {});
});
test('bad form', function() {
var form = {};
hash_check(form, {});
str_check(form, '');
empty_check(form, '');
empty_check_hash(form, {});
});
test('empty form', function() {
var form = domify('<form></form>');

@@ -260,3 +275,3 @@ hash_check(form, {});

// leading checkbox
var form = domify('<form>' +
form = domify('<form>' +
'<input type="checkbox" name="foo" value="bar3" checked="checked"/>' +

@@ -266,10 +281,11 @@ '<input type="radio" name="foo" value="bar1" checked="checked"/>' +

'<input type="checkbox" name="foo" value="bar4"/>' +
'<input type="checkbox" name="foo" value="bar5" checked="checked"/>' +
'</form>');
hash_check(form, {
foo: ['bar3', 'bar1']
foo: ['bar3', 'bar1', 'bar5']
});
str_check(form, 'foo=bar3&foo=bar1');
str_check(form, 'foo=bar3&foo=bar1&foo=bar5');
});
test('nested hashes with brackets', function() {
test('bracket notation - hashes', function() {
var form = domify('<form>' +

@@ -281,12 +297,47 @@ '<input type="email" name="account[name]" value="Foo Dude">' +

'<input type="text" name="account[address][empty]" value="">' +
'<select name="beer[type]" multiple>' +
' <option value="ipa" selected>IPA</option>' +
' <option value="pale-ale">Pale Ale</option>' +
' <option value="amber-ale" selected>Amber Ale</option>' +
'</form>');
hash_check(form, {
account: {
name: 'Foo Dude',
email: 'foobar@example.org',
address: {
city: 'Qux',
state: 'CA'
}
}
});
empty_check_hash(form, {
account: {
name: 'Foo Dude',
email: 'foobar@example.org',
address: {
city: 'Qux',
state: 'CA',
empty: ''
}
}
});
});
test('bracket notation - select multiple', function() {
var form = domify('<form>' +
'<select name="foo" multiple>' +
' <option value="bar" selected>Bar</option>' +
' <option value="baz">Baz</option>' +
' <option value="qux" selected>Qux</option>' +
'</select>' +
'<select name="wine[type]" multiple>' +
' <option value="">No wine</option>' +
' <option value="white">White</option>' +
' <option value="red">Red</option>' +
' <option value="sparkling">Sparkling</option>' +
'</form>');
hash_check(form, {
foo: [ 'bar', 'qux' ]
});
// Trailing notation on select.name.
form = domify('<form>' +
'<select name="foo[]" multiple>' +
' <option value="bar" selected>Bar</option>' +
' <option value="baz">Baz</option>' +
' <option value="qux" selected>Qux</option>' +
'</select>' +

@@ -296,35 +347,124 @@ '</form>');

hash_check(form, {
account: {
name: 'Foo Dude',
email: 'foobar@example.org',
address: {
city: 'Qux',
state: 'CA'
foo: [ 'bar', 'qux' ]
});
});
test('bracket notation - select multiple, nested', function() {
var form = domify('<form>' +
'<select name="foo[bar]" multiple>' +
' <option value="baz" selected>Baz</option>' +
' <option value="qux">Qux</option>' +
' <option value="norf" selected>Norf</option>' +
'</select>' +
'</form>');
hash_check(form, {
foo: {
bar: [ 'baz', 'norf' ]
}
},
beer: {
type: [ 'ipa', 'amber-ale' ]
});
});
test('bracket notation - select multiple, empty values', function() {
var form = domify('<form>' +
'<select name="foo[bar]" multiple>' +
' <option selected>Default value</option>' +
' <option value="" selected>Empty value</option>' +
' <option value="baz" selected>Baz</option>' +
' <option value="qux">Qux</option>' +
' <option value="norf" selected>Norf</option>' +
'</select>' +
'</form>');
hash_check(form, {
foo: {
bar: [ 'Default value', 'baz', 'norf' ]
}
});
empty_check_hash(form, {
account: {
name: 'Foo Dude',
email: 'foobar@example.org',
address: {
city: 'Qux',
state: 'CA',
empty: ''
foo: {
bar: [ 'Default value', '', 'baz', 'norf' ]
}
},
beer: {
type: [ 'ipa', 'amber-ale' ]
},
wine: {
type: ""
});
});
test('bracket notation - non-indexed arrays', function() {
var form = domify('<form>' +
'<input name="people[][name]" value="fred" />' +
'<input name="people[][name]" value="bob" />' +
'<input name="people[][name]" value="bubba" />' +
'</form>');
hash_check(form, {
people: [
{ name: "fred" },
{ name: "bob" },
{ name: "bubba" },
]
});
});
test('bracket notation - nested, non-indexed arrays', function() {
var form = domify('<form>' +
'<input name="user[tags][]" value="cow" />' +
'<input name="user[tags][]" value="milk" />' +
'</form>');
hash_check(form, {
user: {
tags: [ "cow", "milk" ],
}
});
str_check(form, 'account%5Bname%5D=Foo+Dude&account%5Bemail%5D=foobar%40example.org&account%5Baddress%5D%5Bcity%5D=Qux&account%5Baddress%5D%5Bstate%5D=CA&beer%5Btype%5D=ipa&beer%5Btype%5D=amber-ale');
empty_check(form, 'account%5Bname%5D=Foo+Dude&account%5Bemail%5D=foobar%40example.org&account%5Baddress%5D%5Bcity%5D=Qux&account%5Baddress%5D%5Bstate%5D=CA&account%5Baddress%5D%5Bempty%5D=&beer%5Btype%5D=ipa&beer%5Btype%5D=amber-ale&wine%5Btype%5D=')
});
test('bracket notation - indexed arrays', function() {
var form = domify('<form>' +
'<input name="people[2][name]" value="bubba" />' +
'<input name="people[2][age]" value="15" />' +
'<input name="people[0][name]" value="fred" />' +
'<input name="people[0][age]" value="12" />' +
'<input name="people[1][name]" value="bob" />' +
'<input name="people[1][age]" value="14" />' +
'<input name="people[][name]" value="frank">' +
'<input name="people[3][age]" value="2">' +
'</form>');
hash_check(form, {
people: [
{
name: "fred",
age: "12"
},
{
name: "bob",
age: "14"
},
{
name: "bubba",
age: "15"
},
{
name: "frank",
age: "2"
}
]
});
});
test('bracket notation - bad notation', function() {
var form = domify('<form>' +
'<input name="[][foo]" value="bar" />' +
'<input name="[baz][qux]" value="norf" />' +
'</form>');
hash_check(form, {
_values: [
{ foo: 'bar' }
],
baz: { qux: 'norf' }
});
});
test('custom serializer', function() {

@@ -331,0 +471,0 @@ var form = domify('<form><input type="text" name="node" value="zuul">/</form>');

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