This repository has been archived by the owner on Apr 3, 2024. It is now read-only.
/
field.js
203 lines (174 loc) · 6.59 KB
/
field.js
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
// Dependencies.
let AddClasses = require("./add-classes");
// Variables.
let idCount = 0;
/**
* Utility functions for working with form fields.
* @constructor
*/
function Field() {
}
/**
* Initializes a field renderer prototype to ensure it has all the necessary functions.
* @param fieldPrototype The prototype for the field renderer.
*/
Field.initializeFieldPrototype = function (fieldPrototype) {
// Use a fallback for setData?
if (!fieldPrototype.setData) {
fieldPrototype.setData = function () {};
}
// Use a fallback for checkValidity?
if (!fieldPrototype.checkValidity) {
fieldPrototype.checkValidity = function () {
return [];
};
}
// Use fallback for getCategory?
if (!fieldPrototype.getCategory) {
fieldPrototype.getCategory = function () {
return null;
};
}
};
/**
* Adds the data for a field to the specified instance of either FormData or an object.
* @param data The FormData or object to set the field data on.
* @param value The value to set.
* @param options {{rawDataByAlias: boolean}} Optional. The options for setting the data.
* @param alias The field alias.
* @param id The field ID.
*/
Field.setData = function (data, value, options, alias, id) {
// Adjust options.
options = options || {};
options.rawDataByAlias = options.rawDataByAlias || false;
// Set data.
if (options.rawDataByAlias) {
if (alias) {
data[alias] = value;
}
} else {
data.append(id, value);
}
};
/**
* Initializes a field renderer.
* @param fieldRenderer The field renderer to initialize.
* @param fieldData The field data that should be used to render the field.
* @param fieldValidators The associative array of the field validating functions.
* @param options {{type: string, usePlaceholder: boolean, useLabel: boolean, useWrapper: boolean, cssClasses: string[], nodeName: string, nestFieldInLabel: boolean, wrapperElement: HTMLElement, wrapperElementType: string, wrapLabelText: boolean, fieldBeforeLabelText: boolean, name: string, label: string, label2: string}}
* The options to use when constructing the field.
*/
Field.initializeField = function (fieldRenderer, fieldData, fieldValidators, options) {
// Variables.
let fieldElement, labelElement, fieldId, textNode, labelTextWrapper,
useWrapper = options.useWrapper !== false,
wrapperElement = options.wrapperElement,
wrapperElementType = options.wrapperElementType || 'div',
useLabel = options.useLabel !== false,
labelText = options.hasOwnProperty("label")
? options.label
: fieldData.label,
hasLabel2 = options.hasOwnProperty("label2");
// Create element.
fieldElement = document.createElement(options.nodeName || "input");
if (options.type) {
try {
fieldElement.type = options.type;
} catch (ex) {
// Fallback for IE11 (throws an error in some cases, such as when type="date").
fieldElement.setAttribute("type", options.type);
}
}
if (options.hasOwnProperty("name")) {
fieldElement.name = options.name;
}
// Add the catagory to the field.
if (fieldData.category) {
fieldElement.setAttribute("data-category", fieldData.category);
}
// Set value?
if (options.hasOwnProperty("value")) {
fieldElement.value = options.value;
}
// Set aria label.
if (useLabel) {
fieldElement.setAttribute("aria-label", labelText);
}
// Create wrapper element, or just use the field element as the wrapper.
wrapperElement = useWrapper
? (wrapperElement || document.createElement(wrapperElementType))
: fieldElement;
// Attach CSS classes.
if (options.cssClasses) {
AddClasses(wrapperElement, options.cssClasses);
}
AddClasses(wrapperElement, Object.keys(fieldValidators).map(function (x) {
return "formulate__validation-type--" + x;
}));
// Add placeholder?
if (options.usePlaceholder !== false) {
fieldElement.setAttribute("placeholder", labelText);
}
// Create label element?
if (useLabel) {
fieldId = Field.generateId("formulate-field-");
fieldElement.setAttribute("id", fieldId);
labelElement = document.createElement("label");
labelElement.setAttribute("for", fieldId);
labelElement.classList.add("formulate__field__label");
textNode = document.createTextNode(labelText);
if (options.wrapLabelText) {
labelTextWrapper = document.createElement("span");
labelTextWrapper.classList.add("formulate__field__label-text");
labelTextWrapper.appendChild(textNode);
labelElement.appendChild(labelTextWrapper);
if (hasLabel2) {
labelTextWrapper = labelTextWrapper.cloneNode();
textNode = document.createTextNode(options.label2);
labelTextWrapper.appendChild(textNode);
labelElement.appendChild(labelTextWrapper);
}
} else {
labelElement.appendChild(textNode);
}
wrapperElement.appendChild(labelElement);
}
// Add element to wrapper?
if (useWrapper) {
if (options.nestFieldInLabel) {
if (options.fieldBeforeLabelText) {
labelElement.insertBefore(fieldElement, labelElement.childNodes[0]);
} else {
labelElement.appendChild(fieldElement);
}
} else {
if (options.fieldBeforeLabelText === false || window.labelAfterTextInput === false) {
wrapperElement.appendChild(fieldElement);
} else {
wrapperElement.insertBefore(fieldElement, wrapperElement.childNodes[wrapperElement.childNodes.length - 1]);
}
}
}
// Retain DOM elements and field properties.
if (useWrapper) {
fieldRenderer.wrapper = wrapperElement;
}
fieldRenderer.element = fieldElement;
fieldRenderer.id = fieldData.id;
fieldRenderer.alias = fieldData.alias;
fieldRenderer.label = labelElement;
// Prepare the validators and retain them for later use.
fieldRenderer.validators = require("./validation").prepareValidators(fieldData.validations, fieldValidators);
};
/**
* Generates a unique ID for an HTML element.
* @param prefix {string} The prefix to use for the ID.
* @returns {string} The unique ID.
*/
Field.generateId = function (prefix) {
idCount++;
return prefix + idCount.toString();
};
// Export the form field utility functions.
module.exports = Field;