Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/webroot/rsrc/js/phuix/PHUIXFormControl.js
12241 views
1
/**
2
* @provides phuix-form-control-view
3
* @requires javelin-install
4
* javelin-dom
5
*/
6
7
JX.install('PHUIXFormControl', {
8
9
members: {
10
_node: null,
11
_labelNode: null,
12
_errorNode: null,
13
_inputNode: null,
14
_className: null,
15
_valueSetCallback: null,
16
_valueGetCallback: null,
17
_rawInputNode: null,
18
_tokenizer: null,
19
20
setLabel: function(label) {
21
JX.DOM.setContent(this._getLabelNode(), label);
22
return this;
23
},
24
25
setError: function(error) {
26
JX.DOM.setContent(this._getErrorNode(), error);
27
return this;
28
},
29
30
setClass: function(className) {
31
this._className = className;
32
return this;
33
},
34
35
setControl: function(type, spec) {
36
var node = this._getInputNode();
37
38
var input;
39
switch (type) {
40
case 'tokenizer':
41
input = this._newTokenizer(spec);
42
break;
43
case 'select':
44
input = this._newSelect(spec);
45
break;
46
case 'points':
47
input = this._newPoints(spec);
48
break;
49
case 'optgroups':
50
input = this._newOptgroups(spec);
51
break;
52
case 'static':
53
input = this._newStatic(spec);
54
break;
55
case 'checkboxes':
56
input = this._newCheckboxes(spec);
57
break;
58
case 'text':
59
input = this._newText(spec);
60
break;
61
case 'remarkup':
62
input = this._newRemarkup(spec);
63
break;
64
default:
65
// TODO: Default or better error?
66
JX.$E('Bad Input Type');
67
return;
68
}
69
70
JX.DOM.setContent(node, input.node);
71
this._valueGetCallback = input.get;
72
this._valueSetCallback = input.set;
73
this._rawInputNode = input.node;
74
this._tokenizer = input.tokenizer || null;
75
76
return this;
77
},
78
79
setValue: function(value) {
80
this._valueSetCallback(value);
81
return this;
82
},
83
84
getValue: function() {
85
return this._valueGetCallback();
86
},
87
88
getRawInputNode: function() {
89
return this._rawInputNode;
90
},
91
92
getTokenizer: function() {
93
return this._tokenizer;
94
},
95
96
getNode: function() {
97
if (!this._node) {
98
99
var attrs = {
100
className: 'aphront-form-control ' + this._className + ' grouped'
101
};
102
103
var content = [
104
this._getLabelNode(),
105
this._getErrorNode(),
106
this._getInputNode()
107
];
108
109
this._node = JX.$N('div', attrs, content);
110
}
111
112
return this._node;
113
},
114
115
_getLabelNode: function() {
116
if (!this._labelNode) {
117
var attrs = {
118
className: 'aphront-form-label'
119
};
120
121
this._labelNode = JX.$N('label', attrs);
122
}
123
124
return this._labelNode;
125
},
126
127
_getErrorNode: function() {
128
if (!this._errorNode) {
129
var attrs = {
130
className: 'aphront-form-error'
131
};
132
133
this._errorNode = JX.$N('span', attrs);
134
}
135
136
return this._errorNode;
137
},
138
139
_getInputNode: function() {
140
if (!this._inputNode) {
141
var attrs = {
142
className: 'aphront-form-input'
143
};
144
145
this._inputNode = JX.$N('div', attrs);
146
}
147
148
return this._inputNode;
149
},
150
151
_newTokenizer: function(spec) {
152
var build = JX.Prefab.newTokenizerFromTemplate(
153
spec.markup,
154
spec.config);
155
build.tokenizer.start();
156
157
function get_value() {
158
return JX.keys(build.tokenizer.getTokens());
159
}
160
161
function set_value(map) {
162
var tokens = get_value();
163
for (var ii = 0; ii < tokens.length; ii++) {
164
build.tokenizer.removeToken(tokens[ii]);
165
}
166
for (var k in map) {
167
var v = JX.Prefab.transformDatasourceResults(map[k]);
168
build.tokenizer.addToken(k, v);
169
}
170
}
171
172
set_value(spec.value || {});
173
174
return {
175
node: build.node,
176
get: get_value,
177
set: set_value,
178
tokenizer: build.tokenizer
179
};
180
},
181
182
_newSelect: function(spec) {
183
var node = JX.Prefab.renderSelect(
184
spec.options,
185
spec.value,
186
{},
187
spec.order);
188
189
return {
190
node: node,
191
get: function() {
192
return node.value;
193
},
194
set: function(value) {
195
node.value = value;
196
}
197
};
198
},
199
200
_newStatic: function(spec) {
201
var node = JX.$N(
202
'div',
203
{
204
className: 'phui-form-static-action'
205
},
206
spec.description || '');
207
208
return {
209
node: node,
210
get: function() {
211
return true;
212
},
213
set: function() {
214
return;
215
}
216
};
217
},
218
219
_newCheckboxes: function(spec) {
220
var checkboxes = [];
221
var checkbox_list = [];
222
for (var ii = 0; ii < spec.keys.length; ii++) {
223
var key = spec.keys[ii];
224
var checkbox_id = 'checkbox-' + Math.floor(Math.random() * 1000000);
225
226
var checkbox = JX.$N(
227
'input',
228
{
229
type: 'checkbox',
230
value: key,
231
id: checkbox_id
232
});
233
234
checkboxes.push(checkbox);
235
236
var label = JX.$N(
237
'label',
238
{
239
className: 'phuix-form-checkbox-label',
240
htmlFor: checkbox_id
241
},
242
JX.$H(spec.labels[key] || ''));
243
244
var display = JX.$N(
245
'div',
246
{
247
className: 'phuix-form-checkbox-item'
248
},
249
[checkbox, label]);
250
251
checkbox_list.push(display);
252
}
253
254
var node = JX.$N(
255
'div',
256
{
257
className: 'phuix-form-checkbox-action'
258
},
259
checkbox_list);
260
261
var get_value = function() {
262
var list = [];
263
for (var ii = 0; ii < checkboxes.length; ii++) {
264
if (checkboxes[ii].checked) {
265
list.push(checkboxes[ii].value);
266
}
267
}
268
return list;
269
};
270
271
var set_value = function(value) {
272
value = value || [];
273
274
if (!value.length) {
275
value = [];
276
}
277
278
var map = {};
279
var ii;
280
for (ii = 0; ii < value.length; ii++) {
281
map[value[ii]] = true;
282
}
283
284
for (ii = 0; ii < checkboxes.length; ii++) {
285
if (map.hasOwnProperty(checkboxes[ii].value)) {
286
checkboxes[ii].checked = 'checked';
287
} else {
288
checkboxes[ii].checked = false;
289
}
290
}
291
};
292
293
set_value(spec.value);
294
295
return {
296
node: node,
297
get: get_value,
298
set: set_value
299
};
300
},
301
302
_newPoints: function(spec) {
303
return this._newText(spec);
304
},
305
306
_newText: function(spec) {
307
var attrs = {
308
type: 'text',
309
value: spec.value
310
};
311
312
var node = JX.$N('input', attrs);
313
314
return {
315
node: node,
316
get: function() {
317
return node.value;
318
},
319
set: function(value) {
320
node.value = value;
321
}
322
};
323
},
324
325
_newRemarkup: function(spec) {
326
var attrs = {};
327
328
// We could imagine a world where this renders a full remarkup control
329
// with all the hint buttons and client behaviors, but today much of that
330
// behavior is defined server-side and thus this isn't a world we
331
// currently live in.
332
333
var node = JX.$N('textarea', attrs);
334
node.value = spec.value || '';
335
336
return {
337
node: node,
338
get: function() {
339
return node.value;
340
},
341
set: function(value) {
342
node.value = value;
343
}
344
};
345
},
346
347
_newOptgroups: function(spec) {
348
var value = spec.value || null;
349
350
var optgroups = [];
351
for (var ii = 0; ii < spec.groups.length; ii++) {
352
var group = spec.groups[ii];
353
var options = [];
354
for (var jj = 0; jj < group.options.length; jj++) {
355
var option = group.options[jj];
356
options.push(JX.$N('option', {value: option.key}, option.label));
357
358
if (option.selected && (value === null)) {
359
value = option.key;
360
}
361
}
362
optgroups.push(JX.$N('optgroup', {label: group.label}, options));
363
}
364
365
var node = JX.$N('select', {}, optgroups);
366
node.value = value;
367
368
return {
369
node: node,
370
get: function() {
371
return node.value;
372
},
373
set: function(value) {
374
node.value = value;
375
}
376
};
377
}
378
379
}
380
381
});
382
383