forked from jsonform/jsonform
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjsonform-split.js
More file actions
158 lines (140 loc) · 5.28 KB
/
jsonform-split.js
File metadata and controls
158 lines (140 loc) · 5.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/**
* @fileoverview The JSON Form "split" library exposes a "split" method
* that can be used to divide a JSON Form object into two disjoint
* JSON Form objects:
* - the first one includes the schema and layout of the form that
* contains the list of keys given as parameters as well as keys that
* cannot be separated from them (typically because they belong to the
* same array in the layout)
* - the second one includes the schema and layout of a form that does not
* contain the list of keys given as parameters.
*/
(function (serverside, global, _) {
if (serverside) {
_ = require('underscore');
}
/**
* Splits a JSON Form object into two autonomous JSON Form objects,
* one that includes the provided list of schema keys as well as keys
* that are tightly coupled to these keys, and the other that does not
* include these keys.
*
* The function operates on the "schema", "form", and "value" properties
* of the initial JSON Form object. It copies over the other properties
* to the resulting JSON Form objects.
*
* @function
* @param {Object} jsonform JSON Form object with a "schema" and "form"
* @param {Array(String)} keys Schema keys used to split the form. Each
* key must reference a schema key at the first level in the schema
* (in other words, the keys cannot include "." or "[]")
* @return {Object} An object with an "included" property whose value is
* the JSON Form object that includes the keys and an "excluded" property
* whose value is the JSON Form object that does not contain any of the
* keys. These objects may be empty.
*/
var split = function (jsonform, keys) {
if (!jsonform || !keys) return {
included: {},
excluded: {}
};
if (_.isString(keys)) {
keys = [keys];
}
// TODO: proper deep clone (note there may be event handlers, so
// JSON.parse(JSON.stringify()) cannot be used here)
var result = {
included: _.clone(jsonform),
excluded: _.clone(jsonform)
};
result.included.schema = { properties: {} };
result.included.form = [];
result.excluded.schema = { properties: {} };
result.excluded.form = [];
if (!jsonform) return result;
if (!jsonform.form) return result;
// TODO: support for '*'
// Helper function that checks the given form field definition
// and returns true when the definition contains a reference to
// one of the keys given as parameter.
var includeFormField = function (formField) {
var key = null;
if (_.isString(formField)) {
// Direct reference to a key in the schema
return _.include(keys, formField) ||
!!_.find(keys, function (key) {
return (formField.indexOf(key + '.') === 0) ||
(formField.indexOf(key + '[]') === 0);
});
}
if (formField.key) {
if (_.include(keys, formField.key) ||
_.find(keys, function (key) {
return (formField.key.indexOf(key + '.') === 0) ||
(formField.key.indexOf(key + '[]') === 0);
})
) {
return true;
}
}
return !!_.some(formField.items, function (item) {
return includeFormField(item);
});
};
// Helper function that checks the given schema key definition
// and returns true when the definition is referenced in the
// given form field definition
var includeSchemaKey = function (formField, schemaKey) {
if (!formField) return false;
if (!schemaKey) return false;
if (_.isString(formField)) {
// Direct reference to a key in the schema
return (formField === schemaKey) ||
(formField.indexOf(schemaKey + '.') === 0) ||
(formField.indexOf(schemaKey + '[]') === 0);
}
if (formField.key) {
if ((formField.key === schemaKey) ||
(formField.key.indexOf(schemaKey + '.') === 0) ||
(formField.key.indexOf(schemaKey + '[]') === 0)
) {
return true;
}
}
return !!_.some(formField.items, function (item) {
return includeSchemaKey(item, schemaKey);
});
};
// Split the form into two forms
_.each(jsonform.form, function (formField) {
if (includeFormField(formField)) {
result.included.form.push(formField);
}
else {
result.excluded.form.push(formField);
}
});
// Split the schema into two schemas.
// (note that the "excluded" JSON Form object may contain keys that
// are never referenced in the initial JSON Form layout. That's normal)
var schemaProperties = jsonform.schema;
if (schemaProperties.properties) {
schemaProperties = schemaProperties.properties;
}
_.each(schemaProperties, function (schemaDefinition, schemaKey) {
if (_.some(result.included.form, function (formField) {
return includeSchemaKey(formField, schemaKey);
})) {
result.included.schema.properties[schemaKey] = schemaDefinition;
}
else {
result.excluded.schema.properties[schemaKey] = schemaDefinition;
}
});
return result;
};
global.JSONForm = global.JSONForm || {};
global.JSONForm.split = split;
})((typeof exports !== 'undefined'),
((typeof exports !== 'undefined') ? exports : window),
((typeof _ !== 'undefined') ? _ : null));