@livinglogic/livingapi 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/livingapi.js CHANGED
@@ -2,8 +2,8 @@
2
2
  * LivingAPI JavaScript Library
3
3
  * https://my.living-apps.de/docs/LivingAPI.html
4
4
  *
5
- * Copyright 2017-2019 by LivingLogic AG, Bayreuth/Germany
6
- * Copyright 2017-2019 by Walter Dörwald
5
+ * Copyright 2017-2022 by LivingLogic AG, Bayreuth/Germany
6
+ * Copyright 2017-2022 by Walter Dörwald
7
7
  *
8
8
  * All Rights Reserved
9
9
  *
@@ -34,6 +34,30 @@ export { version };
34
34
  import * as ul4 from '@livinglogic/ul4';
35
35
 
36
36
 
37
+ export function element(name, ...args)
38
+ {
39
+ let dom_node = document.createElement(name);
40
+ for (let arg of args)
41
+ {
42
+ if (typeof(arg) === "string")
43
+ dom_node.appendChild(document.createTextNode(arg));
44
+ let ismap = arg instanceof Map;
45
+ let isobject = ul4._isobject(arg);
46
+ if (ismap || isobject)
47
+ {
48
+ if (isobject)
49
+ arg = Object.entries(arg);
50
+ for (let [name, value] of arg)
51
+ {
52
+ if (value !== null)
53
+ dom_node.setAttribute(name, value);
54
+ }
55
+ }
56
+ }
57
+ return dom_node;
58
+ }
59
+
60
+
37
61
  export class Base extends ul4.Proto
38
62
  {
39
63
  constructor(id)
@@ -99,9 +123,24 @@ export class Base extends ul4.Proto
99
123
  }
100
124
  return value;
101
125
  }
126
+ else if (name.startsWith("x_"))
127
+ {
128
+ return this.hasOwnProperty(name) ? this[name] : null;
129
+ }
102
130
  throw new ul4.AttributeError(this, name);
103
131
  }
104
132
 
133
+ [ul4.symbols.setattr](name, value)
134
+ {
135
+ if (name.startsWith("x_"))
136
+ {
137
+ this[name] = value;
138
+ }
139
+ else
140
+ throw new ul4.AttributeError(this, name);
141
+ }
142
+
143
+
105
144
  [ul4.symbols.repr]()
106
145
  {
107
146
  return "<" + this.constructor.name + ">";
@@ -126,10 +165,19 @@ export class Handler
126
165
  };
127
166
 
128
167
 
129
- export class Globals extends Base
168
+ class GlobalsType extends ul4.Type
130
169
  {
131
- static classdoc = "Global information";
170
+ instancecheck(obj)
171
+ {
172
+ return obj instanceof Globals;
173
+ }
174
+ };
175
+
176
+ let globalstype = new GlobalsType("la", "Globals", "Global information");
132
177
 
178
+
179
+ export class Globals extends Base
180
+ {
133
181
  constructor(id)
134
182
  {
135
183
  super(id);
@@ -138,16 +186,27 @@ export class Globals extends Base
138
186
  this.platform = null;
139
187
  this.user = null;
140
188
  this.lang = null;
189
+ this.datasources = null;
141
190
  this.app = null;
142
191
  this.record = null;
192
+ this.mode = null;
143
193
  this.maxdbactions = null;
144
194
  this.maxtemplateruntime = null;
145
195
  this.flashmessages = null;
196
+ this.view_template_id = null;
197
+ this.email_template_id = null;
146
198
  this.handler = new Handler();
199
+ this._log_stack = [];
200
+ this._current_geo = null;
201
+ }
202
+
203
+ [ul4.symbols.type]()
204
+ {
205
+ return globalstype;
147
206
  }
148
207
 
149
208
  // distance between two geo coordinates (see https://de.wikipedia.org/wiki/Orthodrome#Genauere_Formel_zur_Abstandsberechnung_auf_der_Erde)
150
- static geodist(geo1, geo2)
209
+ geo_dist(geo1, geo2)
151
210
  {
152
211
  let sqsin = function sqsin(x) {x = Math.sin(x); return x*x};
153
212
  let sqcos = function sqsos(x) {x = Math.cos(x); return x*x};
@@ -173,15 +232,15 @@ export class Globals extends Base
173
232
  return s;
174
233
  }
175
234
 
176
- scaledURL(url, width, height, type="fill", enlarge=true, gravity="sm", quality=null, rotate=null, blur=null, sharpen=null, format=null, cache=true)
235
+ scaled_url(image, width, height, type="fill", enlarge=true, gravity="sm", quality=null, rotate=null, blur=null, sharpen=null, format=null, cache=true)
177
236
  {
178
237
  let filename = null;
179
238
 
180
- if (url instanceof File)
239
+ if (image instanceof File)
181
240
  {
182
- url = "https://" + this.hostname + url.url;
183
- filename = encodeURIComponent(url.filename);
184
- if (filename != url.filename)
241
+ image = "https://" + this.hostname + image.archive_url;
242
+ filename = encodeURIComponent(image.filename);
243
+ if (filename != image.filename)
185
244
  filename = null;
186
245
  }
187
246
 
@@ -225,24 +284,207 @@ export class Globals extends Base
225
284
  if (filename !== null && filename !== undefined)
226
285
  result += "/fn:" + filename;
227
286
 
228
- result += "/plain/" + encodeURIComponent(url);
287
+ result += "/plain/" + encodeURIComponent(image);
229
288
 
230
289
  return result;
231
290
  }
232
291
 
233
292
  [ul4.symbols.repr]()
234
293
  {
235
- return "<Globals version=" + ul4._repr(this.version) + ">";
294
+ return "<Globals version=" + ul4._repr(this.version) + " mode=" + ul4._repr(this.mode) + ">";
295
+ }
296
+
297
+ current_geo()
298
+ {
299
+ return this._current_geo;
300
+ }
301
+
302
+ set_current_geo(position)
303
+ {
304
+ this._current_geo = new Geo(position.coords.latitude, position.coords.longitude);
305
+ }
306
+
307
+ _in_form()
308
+ {
309
+ return this.mode !== null && this.mode.startsWith("form/");
310
+ }
311
+
312
+ msg_bool(value)
313
+ {
314
+ switch (value)
315
+ {
316
+ case true:
317
+ return this.msg_bool_true();
318
+ case false:
319
+ return this.msg_bool_false();
320
+ default:
321
+ return null;
322
+ }
323
+ }
324
+
325
+ msg_bool_true(value)
326
+ {
327
+ switch (this.lang)
328
+ {
329
+ case "de":
330
+ return "Ja";
331
+ default:
332
+ return "Yes";
333
+ }
334
+ }
335
+
336
+ msg_bool_false(value)
337
+ {
338
+ switch (this.lang)
339
+ {
340
+ case "de":
341
+ return "Nein";
342
+ default:
343
+ return "No";
344
+ }
345
+ }
346
+
347
+ msg_no_fields()
348
+ {
349
+ switch (this.lang)
350
+ {
351
+ case "de":
352
+ return "(Keine Felder gefunden)";
353
+ default:
354
+ return "(No fields found)";
355
+ }
356
+ }
357
+
358
+ msg_nothing_selected()
359
+ {
360
+ switch (this.lang)
361
+ {
362
+ case "de":
363
+ return "(Nichts ausgewählt)";
364
+ default:
365
+ return "(Nothing selected)";
366
+ }
367
+ }
368
+
369
+ _make_log_message(messages)
370
+ {
371
+ return messages
372
+ .map(m => typeof(m) !== "string" ? ul4._repr(m) : m)
373
+ .join(" ")
374
+ ;
375
+ }
376
+
377
+ begin_logging(header)
378
+ {
379
+ this._log_stack.push({header: header, output: false});
380
+ }
381
+
382
+ end_logging()
383
+ {
384
+ if (this._log_stack)
385
+ {
386
+ if (this._log_stack[this._log_stack.length-1].output && console && console.groupEnd)
387
+ console.groupEnd();
388
+ this._log_stack.pop();
389
+ }
390
+ }
391
+
392
+ group_logging(header, callback)
393
+ {
394
+ this.begin_logging(header);
395
+ try
396
+ {
397
+ callback();
398
+ }
399
+ finally
400
+ {
401
+ this.end_logging();
402
+ }
403
+ }
404
+
405
+ _start_log_message()
406
+ {
407
+ for (let level of this._log_stack)
408
+ {
409
+ if (!level.output)
410
+ {
411
+ if (console && console.group)
412
+ console.group(level.header)
413
+ level.output = true;
414
+ }
415
+ }
416
+ }
417
+
418
+ log_debug(...message)
419
+ {
420
+ this._start_log_message();
421
+ if (console && console.debug)
422
+ console.debug(this._make_log_message(message))
423
+ }
424
+
425
+ log_info(...message)
426
+ {
427
+ this._start_log_message();
428
+ if (console && console.info)
429
+ console.info(this._make_log_message(message))
430
+ }
431
+
432
+ log_warning(...message)
433
+ {
434
+ this._start_log_message();
435
+ if (console && console.warn)
436
+ console.warn(this._make_log_message(message))
437
+ }
438
+
439
+ log_error(...message)
440
+ {
441
+ this._start_log_message();
442
+ if (console && console.error)
443
+ console.error(this._make_log_message(message))
236
444
  }
237
445
  };
238
446
 
239
- Globals.prototype._ul4onattrs = ["version", "platform", "user", "maxdbactions", "maxtemplateruntime", "flashmessages", "lang", "datasources", "hostname", "app", "record", "google_api_key", "mode", "view_template_id", "email_template_id", "view_id"];
240
- Globals.prototype._ul4attrs = new Set(["version", "hostname", "platform", "user", "lang", "app", "record", "maxdbactions", "maxtemplateruntime", "flashmessages", "mode"]);
447
+ Globals.prototype._ul4onattrs = ["version", "platform", "user", "maxdbactions", "maxtemplateruntime", "lang", "datasources", "hostname", "app", "record", "mode", "view_template_id", "email_template_id", "view_id"];
448
+ Globals.prototype._ul4attrs = new Set(["version", "hostname", "platform", "user", "lang", "datasources", "app", "record", "maxdbactions", "maxtemplateruntime", "flashmessages", "mode", "scaled_url", "geo_dist", "current_geo", "log_debug", "log_info", "log_warning", "log_error"]);
449
+ ul4.expose(Globals.prototype.log_debug, ["message", "*"]);
450
+ ul4.expose(Globals.prototype.log_info, ["message", "*"]);
451
+ ul4.expose(Globals.prototype.log_warning, ["message", "*"]);
452
+ ul4.expose(Globals.prototype.log_error, ["message", "*"]);
453
+ ul4.expose(Globals.prototype.geo_dist, ["geo1", "pk", "geo2", "pk"]);
454
+ ul4.expose(Globals.prototype.current_geo, []);
455
+ ul4.expose(Globals.prototype.scaled_url, [
456
+ "image", "p",
457
+ "width", "p",
458
+ "height", "p",
459
+ "type", "k=", "fill",
460
+ "enlarge", "k=", true,
461
+ "gravity", "k=", "sm",
462
+ "quality", "k=", null,
463
+ "rotate", "k=", null,
464
+ "blur", "k=", null,
465
+ "sharpen", "k=", null,
466
+ "format", "k=", null,
467
+ "cache", "k=", true
468
+ ]);
469
+
470
+
471
+ class FlashMessageType extends ul4.Type
472
+ {
473
+ instancecheck(obj)
474
+ {
475
+ return obj instanceof FlashMessage;
476
+ }
477
+ };
478
+
479
+ let flashmessagetype = new FlashMessageType("la", "FlashMessage", "A flash message in a web page");
241
480
 
242
481
 
243
482
  export class FlashMessage extends Base
244
483
  {
245
- static classdoc = "A flash message in a web page";
484
+ [ul4.symbols.type]()
485
+ {
486
+ return flashmessagetype;
487
+ }
246
488
 
247
489
  [ul4.symbols.repr]()
248
490
  {
@@ -254,9 +496,23 @@ FlashMessage.prototype._ul4onattrs = ["timestamp", "type", "title", "message"];
254
496
  FlashMessage.prototype._ul4attrs = new Set(["timestamp", "type", "title", "message"]);
255
497
 
256
498
 
499
+ class AppType extends ul4.Type
500
+ {
501
+ instancecheck(obj)
502
+ {
503
+ return obj instanceof App;
504
+ }
505
+ };
506
+
507
+ let apptype = new AppType("la", "App", "A LivingApps application");
508
+
509
+
257
510
  export class App extends Base
258
511
  {
259
- static classdoc = "A LivingApps application";
512
+ [ul4.symbols.type]()
513
+ {
514
+ return apptype;
515
+ }
260
516
 
261
517
  [ul4.symbols.repr]()
262
518
  {
@@ -311,6 +567,24 @@ export class App extends Base
311
567
  throw new ul4.AttributeError(this, name);
312
568
  return this.controls.get(name.substr(2));
313
569
  }
570
+ else if (name.startsWith("lc_"))
571
+ {
572
+ if (this.layout_controls === null || !this.layout_controls.has(name.substr(3)))
573
+ throw new ul4.AttributeError(this, name);
574
+ return this.layout_controls.get(name.substr(3));
575
+ }
576
+ else if (name.startsWith("p_") && this.params !== null)
577
+ {
578
+ if (!this.params.has(name.substr(2)))
579
+ throw new ul4.AttributeError(this, name);
580
+ return this.params.get(name.substr(2));
581
+ }
582
+ else if (name.startsWith("pv_") && this.params !== null)
583
+ {
584
+ if (!this.params.has(name.substr(3)))
585
+ throw new ul4.AttributeError(this, name);
586
+ return this.params.get(name.substr(3)).value;
587
+ }
314
588
  else
315
589
  return super[ul4.symbols.getattr](name);
316
590
  }
@@ -345,18 +619,39 @@ export class App extends Base
345
619
 
346
620
  this._active_view = view;
347
621
  }
622
+
623
+ get layout_controls()
624
+ {
625
+ if (this.active_views === null)
626
+ return new Map();
627
+ return this.active_view.layout_controls;
628
+ }
348
629
  };
349
630
 
350
631
 
351
632
  App.prototype._ul4onattrs = ["globals", "name", "description", "lang", "startlink", "iconlarge", "iconsmall", "createdby", "controls", "records", "recordcount", "installation", "categories", "params", "views", "datamanagement_identifier", "basetable", "primarykey", "insertprocedure", "updateprocedure", "deleteprocedure", "templates", "createdat", "updatedat", "updatedby", "superid", "favorite", "_active_view"];
352
- App.prototype._ul4attrs = new Set(["id", "globals", "name", "description", "lang", "startlink", "iconlarge", "iconsmall", "createdat", "createdby", "updatedat", "updatedby", "controls", "records", "recordcount", "installation", "categories", "params", "views", "datamanagement_identifier", "insert", "favorite", "_active_view"]);
353
- ul4.expose(App.prototype[ul4.symbols.call], ["**values"], {"needsobject": true});
354
- ul4.expose(App.prototype.insert, ["**values"], {"needsobject": true});
633
+ App.prototype._ul4attrs = new Set(["id", "globals", "name", "description", "lang", "startlink", "iconlarge", "iconsmall", "createdat", "createdby", "updatedat", "updatedby", "controls", "layout_controls", "records", "recordcount", "installation", "categories", "params", "views", "datamanagement_identifier", "insert", "favorite", "_active_view"]);
634
+ ul4.expose(App.prototype[ul4.symbols.call], ["values", "**"], {"needsobject": true});
635
+ ul4.expose(App.prototype.insert, ["values", "**"], {"needsobject": true});
636
+
637
+
638
+ class ViewType extends ul4.Type
639
+ {
640
+ instancecheck(obj)
641
+ {
642
+ return obj instanceof View;
643
+ }
644
+ };
645
+
646
+ let viewtype = new ViewType("la", "View", "An input form for a LivingViews application");
355
647
 
356
648
 
357
649
  export class View extends Base
358
650
  {
359
- static classdoc = "An input form for a LivingApps application";
651
+ [ul4.symbols.type]()
652
+ {
653
+ return viewtype;
654
+ }
360
655
 
361
656
  [ul4.symbols.repr]()
362
657
  {
@@ -364,28 +659,51 @@ export class View extends Base
364
659
  }
365
660
  };
366
661
 
367
- View.prototype._ul4onattrs = ["name", "combined_type", "app", "order", "width", "height", "start", "end", "controls", "layout_controls", "lang"];
368
- View.prototype._ul4attrs = new Set(["id", "name", "combined_type", "app", "order", "width", "height", "start", "end", "controls", "layout_controls", "lang"]);
662
+ View.prototype._ul4onattrs = ["name", "combined_type", "app", "order", "width", "height", "start", "end", "controls", "layout_controls", "lang", "login_required", "result_page", "use_geo"];
663
+ View.prototype._ul4attrs = new Set(["id", "name", "combined_type", "app", "order", "width", "height", "start", "end", "controls", "layout_controls", "lang", "login_required", "result_page", "use_geo"]);
369
664
 
370
665
 
371
- export class DataSourceData extends Base
666
+ class DataSourceType extends ul4.Type
372
667
  {
373
- static classdoc = "The data resulting from a data source configuration";
668
+ instancecheck(obj)
669
+ {
670
+ return obj instanceof DataSource;
671
+ }
672
+ };
673
+
674
+ let datasourcetype = new DataSourceType("la", "DataSource", "The data resulting from a data source configuration");
675
+
676
+
677
+ export class DataSource extends Base
678
+ {
679
+ [ul4.symbols.type]()
680
+ {
681
+ return datasourcetype;
682
+ }
374
683
 
375
684
  [ul4.symbols.repr]()
376
685
  {
377
- return "<DataSource.Data id=" + ul4._repr(this.id) + " identifier=" + ul4._repr(this.identifier) + ">";
686
+ return "<DataSource id=" + ul4._repr(this.id) + " identifier=" + ul4._repr(this.identifier) + ">";
378
687
  }
379
688
  };
380
689
 
381
- DataSourceData.prototype._ul4onattrs = ["identifier", "app", "apps"];
382
- DataSourceData.prototype._ul4attrs = new Set(["id", "identifier", "app", "apps"]);
690
+ DataSource.prototype._ul4onattrs = ["identifier", "app", "apps"];
691
+ DataSource.prototype._ul4attrs = new Set(["id", "identifier", "app", "apps"]);
383
692
 
384
693
 
385
- export class Record extends Base
694
+ class RecordType extends ul4.Type
386
695
  {
387
- static classdoc = "A record of a LivingApp application";
696
+ instancecheck(obj)
697
+ {
698
+ return obj instanceof Record;
699
+ }
700
+ };
701
+
702
+ let recordtype = new RecordType("la", "Record", "A record of a LivingApp application");
388
703
 
704
+
705
+ export class Record extends Base
706
+ {
389
707
  constructor(id, app)
390
708
  {
391
709
  super(id);
@@ -407,6 +725,35 @@ export class Record extends Base
407
725
  this._is_new = true;
408
726
  }
409
727
 
728
+ [ul4.symbols.type]()
729
+ {
730
+ return recordtype;
731
+ }
732
+
733
+ as_text(maxlevel=3, controls=null)
734
+ {
735
+ if (maxlevel == 0)
736
+ return "...";
737
+ let fields = [];
738
+ for (let [identifier, control] of (controls || this.app.controls))
739
+ {
740
+ if (controls !== null || control.priority)
741
+ {
742
+ let fieldvalue = this.fields.get(identifier).value_as_text(maxlevel-1);
743
+ if (fieldvalue !== null)
744
+ fields.push([control.label, fieldvalue]);
745
+ }
746
+ }
747
+ if (fields.length === 0)
748
+ return this.globals.msg_no_fields();
749
+ else if (fields.length === 1)
750
+ return fields[0][1];
751
+ let result = [];
752
+ for (let [label, fieldvalue] of fields)
753
+ result.push(label + ": " + fieldvalue);
754
+ return result.join(", ");
755
+ }
756
+
410
757
  _make_fields(defaults, values, errors, lookupdata)
411
758
  {
412
759
  let fields = new Map();
@@ -422,7 +769,7 @@ export class Record extends Base
422
769
  else if (values.has(identifier))
423
770
  value = values.get(identifier);
424
771
  }
425
- let field = new Field(control, this, value);
772
+ let field = new control.fieldtype(control, this, value);
426
773
  fields.set(identifier, field);
427
774
  if (errors !== null && errors.has(identifier))
428
775
  field.errors = errors.get(identifier);
@@ -436,6 +783,13 @@ export class Record extends Base
436
783
  this._sparselookupdata = null;
437
784
  }
438
785
 
786
+ _in_form()
787
+ {
788
+ let globals = this.app.globals;
789
+
790
+ return globals._in_form() && this === globals.record;
791
+ }
792
+
439
793
  [ul4.symbols.repr]()
440
794
  {
441
795
  let v = ["<Record id=", ul4._repr(this.id)];
@@ -596,9 +950,9 @@ export class Record extends Base
596
950
  else if (name.startsWith("f_"))
597
951
  return this.fields.get(name.substr(2))
598
952
  else if (name.startsWith("v_"))
599
- return this.values.get(name.substr(2))
953
+ return this.fields.get(name.substr(2)).value
600
954
  else
601
- return this[name];
955
+ return super[ul4.symbols.getattr](name);
602
956
  }
603
957
 
604
958
  [ul4.symbols.setattr](name, value)
@@ -608,37 +962,58 @@ export class Record extends Base
608
962
  else if (name.startsWith("v_"))
609
963
  this.fields.get(name.substr(2)).value = value;
610
964
  else
611
- throw new ul4.AttributeError(this, name);
965
+ return super[ul4.symbols.setattr](name, value);
612
966
  }
613
967
  };
614
968
 
615
969
  Record.prototype._ul4onattrs = ["app", "createdat", "createdby", "updatedat", "updatedby", "updatecount", "_sparsevalues", "attachments", "children", "errors", "_sparsefielderrors", "_sparsefieldlookupdata"];
616
- Record.prototype._ul4attrs = new Set(["id", "app", "createdat", "createdby", "updatedat", "updatedby", "updatecount", "values", "attachments", "children", "errors"]);
970
+ Record.prototype._ul4attrs = new Set(["id", "app", "createdat", "createdby", "updatedat", "updatedby", "updatecount", "values", "fields", "attachments", "children", "errors"]);
617
971
  ul4.expose(Record.prototype.is_dirty, []);
618
972
  ul4.expose(Record.prototype.has_errors, []);
619
973
  ul4.expose(Record.prototype.delete, []);
620
974
  ul4.expose(Record.prototype.save, []);
621
- ul4.expose(Record.prototype.update, ["**values"], {"needsobject": true});
975
+ ul4.expose(Record.prototype.update, ["values", "**"], {"needsobject": true});
622
976
 
623
977
 
624
- export class Field extends Base
978
+ class FieldType extends ul4.Type
625
979
  {
626
- static classdoc = "Holds the value of a field of a record (and related information)";
980
+ instancecheck(obj)
981
+ {
982
+ return obj instanceof Field;
983
+ }
984
+ };
985
+
986
+ let fieldtype = new FieldType("la", "Field", "Holds the value of a field of a record (and related information)");
987
+
627
988
 
989
+ export class Field extends Base
990
+ {
628
991
  constructor(control, record, value)
629
992
  {
630
993
  super(null);
631
994
  this.control = control;
632
995
  this.record = record;
633
996
  this._label = null;
634
- this._value = value;
635
- this._dirty = false;
636
- this._lookupdate = null;
997
+ this._lookupdata = null;
637
998
  this.errors = [];
999
+ this._value = null;
1000
+ if (!this._in_form())
1001
+ this.value = value;
1002
+ this._dirty = false;
1003
+ this._enabled = true;
1004
+ this._writable = true;
1005
+ this._visible = true;
1006
+ }
1007
+
1008
+ [ul4.symbols.type]()
1009
+ {
1010
+ return fieldtype;
638
1011
  }
639
1012
 
640
1013
  get value()
641
1014
  {
1015
+ if (this._in_form())
1016
+ return this._get_dom_value();
642
1017
  return this._value;
643
1018
  }
644
1019
 
@@ -656,6 +1031,13 @@ export class Field extends Base
656
1031
  this._dirty = true;
657
1032
  }
658
1033
  this.errors = change.errors;
1034
+ if (this._in_form())
1035
+ this._set_dom_value(this._value);
1036
+ }
1037
+
1038
+ value_as_text(maxlevel=3)
1039
+ {
1040
+ return null;
659
1041
  }
660
1042
 
661
1043
  _validate(change)
@@ -663,16 +1045,21 @@ export class Field extends Base
663
1045
  // Do nothing, i.e. accept the value unchanged and without errors
664
1046
  }
665
1047
 
1048
+ _set_dom_label()
1049
+ {
1050
+ if (this._in_form())
1051
+ this._dom_label.textContent = this.label;
1052
+ }
1053
+
666
1054
  get label()
667
1055
  {
668
- if (this._label !== null)
669
- return this._label;
670
- return this.control.label;
1056
+ return this._label ?? this.control.label;
671
1057
  }
672
1058
 
673
1059
  set label(value)
674
1060
  {
675
1061
  this._label = value;
1062
+ this._set_dom_label();
676
1063
  }
677
1064
 
678
1065
  get globals()
@@ -682,7 +1069,7 @@ export class Field extends Base
682
1069
 
683
1070
  is_empty()
684
1071
  {
685
- return this._value === null || (ul4._islist(this._value) && this._value.length === 0);
1072
+ return this._value === null;
686
1073
  }
687
1074
 
688
1075
  is_dirty()
@@ -723,7 +1110,7 @@ export class Field extends Base
723
1110
 
724
1111
  msg_string_tooshort(value)
725
1112
  {
726
- return `"${this.label}" is too short. Tou must use at least ${this.control.minlength} characters!`;
1113
+ return `"${this.label}" is too short. You must use at least ${this.control.minlength} characters!`;
727
1114
  }
728
1115
 
729
1116
  msg_string_toolong(value)
@@ -751,6 +1138,11 @@ export class Field extends Base
751
1138
  return `"${this.label}" doesn't support this date format!`;
752
1139
  }
753
1140
 
1141
+ msg_number_format(value)
1142
+ {
1143
+ return `"${this.label}" doesn't support this number format!`;
1144
+ }
1145
+
754
1146
  msg_lookup_wrongitem(value)
755
1147
  {
756
1148
  return `The option ${ul4._repr(value)} for "${this.label}" doesn't belong to this lookup!`;
@@ -771,70 +1163,360 @@ export class Field extends Base
771
1163
  return `The record ${ul4._repr(value)} for "${this.label}" can't be found!`;
772
1164
  }
773
1165
 
774
- [ul4.symbols.repr]()
1166
+ /*
1167
+ The following methods are used in the input form.
1168
+
1169
+ I.e. they are expected to be executed inside a browser.
1170
+ */
1171
+ _in_form()
775
1172
  {
776
- let s = "<Field identifier=";
777
- s += ul4._repr(this.control.identifier)
778
- if (this._dirty)
779
- s += " is_dirty()=True";
780
- if (this.errors.length > 0)
781
- s += " has_errors()=True";
782
- s += ">"
783
- return s;
1173
+ return this.record._in_form();
784
1174
  }
785
- };
786
1175
 
787
- Field.prototype._ul4onattrs = ["control", "record", "label", "value", "errors", "enabled", "writable", "visible"];
788
- Field.prototype._ul4attrs = new Set(["control", "record", "label", "value", "errors", "enabled", "writable", "visible"]);
1176
+ get _sel_root()
1177
+ {
1178
+ return "#livingapps-form ." + this.control._cssclass_root + ".llft-id-" + this.control.identifier;
1179
+ }
789
1180
 
1181
+ get _sel_label()
1182
+ {
1183
+ return this._sel_root + " label span";
1184
+ }
790
1185
 
791
- export class BoolField extends Field
792
- {
793
- static classdoc = "Holds the value of a bool field of a record (and related information)";
1186
+ get _sel_control()
1187
+ {
1188
+ return this._sel_root + " " + this.control._cssclass_control;
1189
+ }
794
1190
 
795
- _validate(change)
1191
+ get _dom_root()
796
1192
  {
797
- if (change.value === null)
798
- {
799
- if (this.control.required)
800
- change.errors.push(this.msg_field_required(change.value));
801
- }
802
- else if (typeof(change.value) === "boolean")
803
- {
804
- if (this.control.required && !change.value)
805
- change.errors.push(this.msg_bool_truerequired(change.value));
806
- }
807
- else
808
- {
809
- change.errors.push(this.msg_field_wrong_type(change.value));
810
- change.value = null;
811
- }
1193
+ return document.querySelector(this._sel_root);
812
1194
  }
813
- };
814
1195
 
1196
+ get _dom_label()
1197
+ {
1198
+ return document.querySelector(this._sel_label);
1199
+ }
815
1200
 
816
- export class IntField extends Field
817
- {
818
- static classdoc = "Holds the value of an int field of a record (and related information)";
1201
+ get _dom_control()
1202
+ {
1203
+ return document.querySelector(this._sel_control);
1204
+ }
819
1205
 
820
- _validate(change)
1206
+ get _dom_controls()
821
1207
  {
822
- if (change.value === null)
823
- {
824
- if (this.control.required)
1208
+ return document.querySelectorAll(this._sel_control);
1209
+ }
1210
+
1211
+ _get_dom_value()
1212
+ {
1213
+ return this._dom_control.value;
1214
+ }
1215
+
1216
+ _set_dom_value(value)
1217
+ {
1218
+ this._dom_control.value = value;
1219
+ }
1220
+
1221
+ get visible()
1222
+ {
1223
+ return this._visible;
1224
+ }
1225
+
1226
+ set visible(value)
1227
+ {
1228
+ if (this._in_form())
1229
+ this._dom_root.hidden = !value;
1230
+ this._visible = value;
1231
+ }
1232
+
1233
+ get enabled()
1234
+ {
1235
+ if (this._in_form())
1236
+ return !this._dom_root.classList.contains("llft-control-readonly");
1237
+ else
1238
+ return this._enabled;
1239
+ }
1240
+
1241
+ set enabled(value)
1242
+ {
1243
+ if (this._in_form())
1244
+ {
1245
+ let disabled = !value;
1246
+ for (let node of this._dom_controls)
1247
+ node.disabled = disabled;
1248
+ this._dom_root.classList.toggle("llft-control-readonly", disabled);
1249
+ }
1250
+ this._enabled = value;
1251
+ }
1252
+
1253
+ get writable()
1254
+ {
1255
+ return this._writable;
1256
+ }
1257
+
1258
+ set writable(value)
1259
+ {
1260
+ this._writable = value;
1261
+ }
1262
+
1263
+ [ul4.symbols.repr]()
1264
+ {
1265
+ let s = "<" + this.constructor.name + " identifier=";
1266
+ s += ul4._repr(this.control.identifier)
1267
+ if (this._dirty)
1268
+ s += " is_dirty()=True";
1269
+ if (this.errors.length > 0)
1270
+ s += " has_errors()=True";
1271
+ s += ">"
1272
+ return s;
1273
+ }
1274
+
1275
+ [ul4.symbols.setattr](name, value)
1276
+ {
1277
+ if (name === "value")
1278
+ this.value = value;
1279
+ else if (name === "visible")
1280
+ this.visible = ul4._bool(value);
1281
+ else if (name === "enabled")
1282
+ this.enabled = ul4._bool(value);
1283
+ else if (name === "writable")
1284
+ this.writable = ul4._bool(value);
1285
+ else
1286
+ return super[ul4.symbols.getattr](name);
1287
+ }
1288
+ };
1289
+
1290
+ Field.prototype._ul4onattrs = ["control", "record", "label", "value", "errors", "_visible", "_enabled", "_writable"];
1291
+ Field.prototype._ul4attrs = new Set(["control", "record", "label", "value", "errors", "visible", "enabled", "writable"]);
1292
+ Field.prototype._inputevent = "input";
1293
+
1294
+
1295
+ class BoolFieldType extends FieldType
1296
+ {
1297
+ instancecheck(obj)
1298
+ {
1299
+ return obj instanceof BoolField;
1300
+ }
1301
+ };
1302
+
1303
+ let boolfieldtype = new BoolFieldType("la", "BoolField", "Holds the value of a bool field of a record (and related information)");
1304
+
1305
+
1306
+ export class BoolField extends Field
1307
+ {
1308
+ [ul4.symbols.type]()
1309
+ {
1310
+ return boolfieldtype;
1311
+ }
1312
+
1313
+ _validate(change)
1314
+ {
1315
+ if (change.value === null)
1316
+ {
1317
+ if (this.control.required)
1318
+ change.errors.push(this.msg_field_required(change.value));
1319
+ }
1320
+ else if (typeof(change.value) === "boolean")
1321
+ {
1322
+ if (this.control.required && !change.value)
1323
+ change.errors.push(this.msg_bool_truerequired(change.value));
1324
+ }
1325
+ else
1326
+ {
1327
+ change.errors.push(this.msg_field_wrong_type(change.value));
1328
+ change.value = null;
1329
+ }
1330
+ }
1331
+
1332
+ _get_dom_value()
1333
+ {
1334
+ return this._dom_control.checked;
1335
+ }
1336
+
1337
+ _set_dom_value(value)
1338
+ {
1339
+ this._dom_control.checked = value;
1340
+ }
1341
+
1342
+ value_as_text(maxlevel=3)
1343
+ {
1344
+ return this.globals.msg_bool(this.value);
1345
+ }
1346
+ };
1347
+
1348
+
1349
+ class IntFieldType extends FieldType
1350
+ {
1351
+ instancecheck(obj)
1352
+ {
1353
+ return obj instanceof IntField;
1354
+ }
1355
+ };
1356
+
1357
+ let intfieldtype = new IntFieldType("la", "IntField", "Holds the value of an int field of a record (and related information)");
1358
+
1359
+
1360
+ export class IntField extends Field
1361
+ {
1362
+ [ul4.symbols.type]()
1363
+ {
1364
+ return intfieldtype;
1365
+ }
1366
+
1367
+ _parse(value)
1368
+ {
1369
+ if (/^\s*[-+]?\d+\s*$/.test(value))
1370
+ return parseInt(value);
1371
+ else
1372
+ return null;
1373
+ }
1374
+
1375
+ _validate(change)
1376
+ {
1377
+ if (change.value === null)
1378
+ {
1379
+ if (this.control.required)
825
1380
  change.errors.push(this.msg_field_required(change.value));
826
1381
  }
827
- else if (typeof(change.value) !== "number" || Math.round(change.value) !== change.value)
1382
+ else if (typeof(change.value) === "string")
1383
+ {
1384
+ let value = this._parse(change.value);
1385
+ if (value !== null)
1386
+ change.value = value;
1387
+ else
1388
+ change.errors.push(this.msg_number_format(change.value));
1389
+ // Keep original invalid string
1390
+ }
1391
+ else if (typeof(change.value) === "number")
1392
+ {
1393
+ if (Math.round(change.value) !== change.value)
1394
+ change.errors.push(this.msg_field_wrong_type(change.value));
1395
+ // Keep original floating point number
1396
+ }
1397
+ else
828
1398
  {
829
1399
  change.errors.push(this.msg_field_wrong_type(change.value));
1400
+ change.value = null;
1401
+ }
1402
+ }
1403
+
1404
+ _get_dom_value()
1405
+ {
1406
+ let value = super._get_dom_value();
1407
+ if (value)
1408
+ {
1409
+ let testvalue = this._parse(value);
1410
+ if (testvalue !== null)
1411
+ value = testvalue;
1412
+ }
1413
+ return value;
1414
+ }
1415
+
1416
+ _set_dom_value(value)
1417
+ {
1418
+ super._set_dom_value(value + "");
1419
+ }
1420
+
1421
+ value_as_text(maxlevel=3)
1422
+ {
1423
+ let value = this.value;
1424
+ return value != null ? value + "" : null;
1425
+ }
1426
+
1427
+ get writable()
1428
+ {
1429
+ return this._writable;
1430
+ }
1431
+
1432
+ set writable(value)
1433
+ {
1434
+ if (this._in_form())
1435
+ {
1436
+ let readonly = !value;
1437
+ for (let node of this._dom_controls)
1438
+ node.readOnly = readonly;
830
1439
  }
1440
+ super.writable = value;
1441
+ }
1442
+ };
1443
+
1444
+
1445
+ class NumberFieldType extends FieldType
1446
+ {
1447
+ instancecheck(obj)
1448
+ {
1449
+ return obj instanceof NumberField;
831
1450
  }
832
1451
  };
833
1452
 
1453
+ let numberfieldtype = new NumberFieldType("la", "NumberField", "Holds the value of a number field of a record (and related information)");
1454
+
834
1455
 
835
1456
  export class NumberField extends Field
836
1457
  {
837
- static classdoc = "Holds the value of a number field of a record (and related information)";
1458
+ [ul4.symbols.type]()
1459
+ {
1460
+ return numberfieldtype;
1461
+ }
1462
+
1463
+ _parse(value)
1464
+ {
1465
+ if (value === null)
1466
+ return null;
1467
+
1468
+ // Try to ignore thousands separators and return the value as a number
1469
+ let testvalue = value;
1470
+ // Count decimal delimiters
1471
+ let seps = "";
1472
+ let commas = 0;
1473
+ let dots = 0
1474
+ for (let i = 0; i < value.length; ++i)
1475
+ {
1476
+ let c = value[i];
1477
+ if (c == ",")
1478
+ {
1479
+ commas++;
1480
+ seps += c;
1481
+ }
1482
+ else if (c == ".")
1483
+ {
1484
+ dots++;
1485
+ seps += c;
1486
+ }
1487
+ }
1488
+ let convert = null;
1489
+ if (commas == 0)
1490
+ {
1491
+ if (dots <= 1)
1492
+ ; // nothing to do
1493
+ else
1494
+ convert = "de";
1495
+ }
1496
+ else if (commas == 1)
1497
+ {
1498
+ if (dots == 1)
1499
+ convert = (seps == ".,") ? "de" : "en";
1500
+ else
1501
+ convert = "de";
1502
+ }
1503
+ else // commas > 1
1504
+ {
1505
+ if (dots <= 1)
1506
+ convert = "en";
1507
+ else
1508
+ return null; // We can't guess what the user meant
1509
+ }
1510
+
1511
+ if (convert === "de")
1512
+ testvalue = testvalue.replace(/\./g, "").replace(/,/g, ".");
1513
+ else if (convert === "en")
1514
+ testvalue = testvalue.replace(/,/g, "");
1515
+ let floatvalue = parseFloat(testvalue);
1516
+ if (isNaN(floatvalue))
1517
+ return value;
1518
+ return floatvalue;
1519
+ }
838
1520
 
839
1521
  _validate(change)
840
1522
  {
@@ -844,34 +1526,739 @@ export class NumberField extends Field
844
1526
  change.errors.push(this.msg_field_required(change.value));
845
1527
  change.value = null;
846
1528
  }
847
- else if (typeof(change.value) !== "number")
1529
+ else if (typeof(change.value) === "string")
1530
+ {
1531
+ let value = this._parse(change.value);
1532
+ if (value !== null)
1533
+ {
1534
+ value = this._bound_value(value);
1535
+ if (this.control.precision !== null)
1536
+ value = ul4._round(value, this.control.precision);
1537
+ change.value = value;
1538
+ }
1539
+ else
1540
+ change.errors.push(this.msg_number_format(change.value));
1541
+ // Keep original invalid string
1542
+ }
1543
+ else if (typeof(change.value) === "number")
1544
+ {
1545
+ let value = this._bound_value(change.value);
1546
+ if (this.control.precision !== null)
1547
+ value = ul4._round(value, this.control.precision);
1548
+ change.value = value;
1549
+ }
1550
+ else
848
1551
  {
849
1552
  change.errors.push(this.msg_field_wrong_type(change.value));
1553
+ change.value = null;
1554
+ }
1555
+ }
1556
+
1557
+ _bound_value(value)
1558
+ {
1559
+ if (this.control.minimum !== null)
1560
+ {
1561
+ if (value < this.control.minimum)
1562
+ value = this.control.minimum;
1563
+ }
1564
+ if (this.control.maximum !== null)
1565
+ {
1566
+ if (value > this.control.maximum)
1567
+ value = this.control.maximum;
850
1568
  }
1569
+ return value;
1570
+ }
1571
+
1572
+ _get_dom_value()
1573
+ {
1574
+ let value = super._get_dom_value();
1575
+ if (value)
1576
+ {
1577
+ if (typeof(value) == "string")
1578
+ {
1579
+ let testvalue = this._parse(value);
1580
+ if (testvalue !== null)
1581
+ value = testvalue;
1582
+ }
1583
+ if (typeof(value) === "number")
1584
+ {
1585
+ if (this.control.precision !== null)
1586
+ value = ul4._round(value, this.control.precision);
1587
+ value = this._bound_value(value);
1588
+ }
1589
+ }
1590
+ else
1591
+ value = null;
1592
+ return value;
1593
+ }
1594
+
1595
+ _set_dom_value(value)
1596
+ {
1597
+ if (typeof(value) === "number")
1598
+ {
1599
+ value = this._bound_value(value);
1600
+ if (this.control.precision !== null)
1601
+ value = value.toFixed(this.control.precision);
1602
+ }
1603
+ value += "";
1604
+ if (this.globals.lang == "de" && this.control.precision === null)
1605
+ value = value.replace(".", ",");
1606
+ super._set_dom_value(value);
1607
+ }
1608
+
1609
+ value_as_text(maxlevel=3)
1610
+ {
1611
+ let value = this.value;
1612
+ if (value === null)
1613
+ return null;
1614
+ if (this.control.precision !== null)
1615
+ return value.toFixed(this.control.precision);
1616
+ return value.toString();
1617
+ }
1618
+
1619
+ get writable()
1620
+ {
1621
+ return this._writable;
1622
+ }
1623
+
1624
+ set writable(value)
1625
+ {
1626
+ if (this._in_form())
1627
+ {
1628
+ let readonly = !value;
1629
+ for (let node of this._dom_controls)
1630
+ node.readOnly = readonly;
1631
+ }
1632
+ super.writable = value;
1633
+ }
1634
+ };
1635
+
1636
+
1637
+ class StringFieldType extends FieldType
1638
+ {
1639
+ instancecheck(obj)
1640
+ {
1641
+ return obj instanceof StringField;
851
1642
  }
852
1643
  };
853
1644
 
1645
+ let stringfieldtype = new StringFieldType("la", "StringField", "Holds the value of a string field of a record (and related information)");
1646
+
854
1647
 
855
1648
  export class StringField extends Field
856
1649
  {
857
- static classdoc = "Holds the value of a string field of a record (and related information)";
1650
+ [ul4.symbols.type]()
1651
+ {
1652
+ return stringfieldtype;
1653
+ }
858
1654
 
859
1655
  _validate(change)
860
1656
  {
861
1657
  if (change.value === null || change.value === "")
862
1658
  {
863
- if (this.control.required)
864
- change.errors.push(this.msg_field_required(change.value));
865
- change.value = null;
1659
+ if (this.control.required)
1660
+ change.errors.push(this.msg_field_required(change.value));
1661
+ change.value = null;
1662
+ }
1663
+ else if (typeof(change.value) === "string")
1664
+ {
1665
+ let minlength = this.control.minlength;
1666
+ let maxlength = this.control.maxlength;
1667
+ if (minlength !== null && change.value.length < minlength)
1668
+ change.errors.push(this.msg_string_tooshort(change.value))
1669
+ if (maxlength !== null && change.value.length > maxlength)
1670
+ change.errors.push(this.msg_string_toolong(change.value))
1671
+ }
1672
+ else
1673
+ {
1674
+ change.errors.push(this.msg_field_wrong_type(change.value));
1675
+ change.value = null;
1676
+ }
1677
+ }
1678
+
1679
+ get writable()
1680
+ {
1681
+ return this._writable;
1682
+ }
1683
+
1684
+ set writable(value)
1685
+ {
1686
+ if (this._in_form())
1687
+ {
1688
+ let readonly = !value;
1689
+ for (let node of this._dom_controls)
1690
+ node.readOnly = readonly;
1691
+ }
1692
+ super.writable = value;
1693
+ }
1694
+
1695
+ value_as_text(maxlevel=3)
1696
+ {
1697
+ return this.value;
1698
+ }
1699
+ };
1700
+
1701
+
1702
+ class PasswordFieldType extends StringFieldType
1703
+ {
1704
+ instancecheck(obj)
1705
+ {
1706
+ return obj instanceof PasswordField;
1707
+ }
1708
+ };
1709
+
1710
+ let passwordfieldtype = new PasswordFieldType("la", "PasswordField", "Holds the value of a string/password field of a record (and related information)");
1711
+
1712
+
1713
+ export class PasswordField extends StringField
1714
+ {
1715
+ [ul4.symbols.type]()
1716
+ {
1717
+ return passwordfieldtype;
1718
+ }
1719
+ };
1720
+
1721
+
1722
+ class EmailFieldType extends StringFieldType
1723
+ {
1724
+ instancecheck(obj)
1725
+ {
1726
+ return obj instanceof EmailField;
1727
+ }
1728
+ };
1729
+
1730
+ let emailfieldtype = new EmailFieldType("la", "EmailField", "Holds the value of a string/email field of a record (and related information)");
1731
+
1732
+
1733
+ export class EmailField extends StringField
1734
+ {
1735
+ [ul4.symbols.type]()
1736
+ {
1737
+ return emailfieldtype;
1738
+ }
1739
+
1740
+ _validate(change)
1741
+ {
1742
+ if (typeof(change.value) === "string" && change.value.length > 0)
1743
+ {
1744
+ const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/i;
1745
+ if (!re.test(change.value))
1746
+ change.errors.push(this.msg_email_format(change.value));
1747
+ }
1748
+ super._validate(change);
1749
+ }
1750
+ };
1751
+
1752
+
1753
+ class URLFieldType extends StringFieldType
1754
+ {
1755
+ instancecheck(obj)
1756
+ {
1757
+ return obj instanceof URLField;
1758
+ }
1759
+ };
1760
+
1761
+ let urlfieldtype = new URLFieldType("la", "URLField", "Holds the value of a string/url field of a record (and related information)");
1762
+
1763
+
1764
+ export class URLField extends StringField
1765
+ {
1766
+ [ul4.symbols.type]()
1767
+ {
1768
+ return urlfieldtype;
1769
+ }
1770
+
1771
+ _validate(change)
1772
+ {
1773
+ if (typeof(change.value) === "string" && change.value.length > 0)
1774
+ {
1775
+ let url = null;
1776
+ try
1777
+ {
1778
+ url = new URL(change.value);
1779
+ }
1780
+ catch (exc)
1781
+ {
1782
+ change.errors.push(this.msg_url_format(change.value));
1783
+ }
1784
+ if (url !== null && url.protocol !== "http:" && url.protocol !== "https:")
1785
+ {
1786
+ change.errors.push(this.msg_url_format(change.value));
1787
+ }
1788
+ }
1789
+ super._validate(change);
1790
+ }
1791
+ };
1792
+
1793
+
1794
+ class TelFieldType extends StringFieldType
1795
+ {
1796
+ instancecheck(obj)
1797
+ {
1798
+ return obj instanceof TelField;
1799
+ }
1800
+ };
1801
+
1802
+ let telfieldtype = new TelFieldType("la", "TelField", "Holds the value of a string/tel field of a record (and related information)");
1803
+
1804
+
1805
+ export class TelField extends StringField
1806
+ {
1807
+ [ul4.symbols.type]()
1808
+ {
1809
+ return telfieldtype;
1810
+ }
1811
+
1812
+ _validate(change)
1813
+ {
1814
+ if (typeof(change.value) === "string" && change.value.length > 0)
1815
+ {
1816
+ const re = /^\\+?[0-9 /()-]+$/;
1817
+ if (!re.test(change.value))
1818
+ change.errors.push(this.msg_tel_format(change.value));
1819
+ }
1820
+ super._validate(change);
1821
+ }
1822
+ };
1823
+
1824
+
1825
+ class TextAreaFieldType extends StringFieldType
1826
+ {
1827
+ instancecheck(obj)
1828
+ {
1829
+ return obj instanceof TextAreaField;
1830
+ }
1831
+ };
1832
+
1833
+ let textareafieldtype = new TextAreaFieldType("la", "TextAreaField", "Holds the value of a string/textarea field of a record (and related information)");
1834
+
1835
+
1836
+ export class TextAreaField extends StringField
1837
+ {
1838
+ [ul4.symbols.type]()
1839
+ {
1840
+ return textareafieldtype;
1841
+ }
1842
+ };
1843
+
1844
+
1845
+ class HTMLFieldType extends StringFieldType
1846
+ {
1847
+ instancecheck(obj)
1848
+ {
1849
+ return obj instanceof HTMLField;
1850
+ }
1851
+ };
1852
+
1853
+ let htmlfieldtype = new HTMLFieldType("la", "HTMLField", "Holds the value of a string/html field of a record (and related information)");
1854
+
1855
+
1856
+ export class HTMLField extends StringField
1857
+ {
1858
+ [ul4.symbols.type]()
1859
+ {
1860
+ return htmlfieldtype;
1861
+ }
1862
+ };
1863
+
1864
+
1865
+ class GeoFieldType extends FieldType
1866
+ {
1867
+ instancecheck(obj)
1868
+ {
1869
+ return obj instanceof GeoField;
1870
+ }
1871
+ };
1872
+
1873
+ let geofieldtype = new GeoFieldType("la", "GeoField", "Holds the value of a geo field of a record (and related information)");
1874
+
1875
+
1876
+ export class GeoField extends Field
1877
+ {
1878
+ [ul4.symbols.type]()
1879
+ {
1880
+ return geofieldtype;
1881
+ }
1882
+
1883
+ _get_dom_value()
1884
+ {
1885
+ for (let dom_node of this._dom_controls)
1886
+ {
1887
+ if (dom_node.id.endsWith("_geoinfo"))
1888
+ {
1889
+ let value = dom_node.value;
1890
+ if (value)
1891
+ {
1892
+ value = JSON.parse(value);
1893
+ return new Geo(
1894
+ value.geometry.coordinates[0],
1895
+ value.geometry.coordinates[1],
1896
+ value.properties.formatted_address
1897
+ );
1898
+ }
1899
+ }
1900
+ }
1901
+ return null;
1902
+ }
1903
+
1904
+ _set_dom_value(value)
1905
+ {
1906
+ if (value === null)
1907
+ {
1908
+ for (let dom_node of this._dom_controls)
1909
+ {
1910
+ dom_node.value = null;
1911
+ }
1912
+ }
1913
+ else
1914
+ {
1915
+ for (let dom_node of this._dom_controls)
1916
+ {
1917
+ if (dom_node.id.endsWith("_geoinfo"))
1918
+ {
1919
+ let dom_value = {
1920
+ "type": "Feature",
1921
+ "geometry": {
1922
+ "coordinates": [
1923
+ value.lat,
1924
+ value.long
1925
+ ]
1926
+ },
1927
+ "properties": {
1928
+ "formatted_address": value.info
1929
+ }
1930
+ };
1931
+ dom_node.value = ul4._asjson(dom_value);
1932
+ }
1933
+ else
1934
+ dom_node.value = value.info;
1935
+ }
1936
+ }
1937
+ }
1938
+
1939
+ value_as_text(maxlevel=3)
1940
+ {
1941
+ let value = this.value;
1942
+ if (this.value === null)
1943
+ return null;
1944
+ // FIXME: Show N/S and W/E? Show arc minutes/seconds?
1945
+ let result = value.lat.toFixed(5) + ", " + value.long.toFixed(5);
1946
+ if (value.info !== null)
1947
+ result += " (" + value.info + ")";
1948
+ return result;
1949
+ }
1950
+
1951
+ _validate(change)
1952
+ {
1953
+ if (change.value === null || change.value === "")
1954
+ {
1955
+ if (this.control.required)
1956
+ change.errors.push(this.msg_field_required(change.value));
1957
+ change.value = null;
1958
+ }
1959
+ else if (!(change.value instanceof Geo))
1960
+ {
1961
+ change.errors.push(this.msg_field_wrong_type(change.value));
1962
+ change.value = null;
1963
+ }
1964
+ }
1965
+ };
1966
+ GeoField.prototype._inputevent = "llgeo";
1967
+
1968
+
1969
+ class FileFieldType extends FieldType
1970
+ {
1971
+ instancecheck(obj)
1972
+ {
1973
+ return obj instanceof FileField;
1974
+ }
1975
+ };
1976
+
1977
+ let filefieldtype = new FileFieldType("la", "FileField", "Holds the value of a file field of a record (and related information)");
1978
+
1979
+
1980
+ export class FileField extends Field
1981
+ {
1982
+ [ul4.symbols.type]()
1983
+ {
1984
+ return filefieldtype;
1985
+ }
1986
+
1987
+ _validate(change)
1988
+ {
1989
+ if (change.value === null || change.value === "")
1990
+ {
1991
+ if (this.control.required)
1992
+ change.errors.push(this.msg_field_required(change.value));
1993
+ change.value = null;
1994
+ }
1995
+ else if (!(change.value instanceof File))
1996
+ {
1997
+ change.errors.push(this.msg_field_wrong_type(change.value));
1998
+ change.value = null;
1999
+ }
2000
+ }
2001
+
2002
+ _get_dom_value()
2003
+ {
2004
+ // Always return `null``
2005
+ return null;
2006
+ }
2007
+
2008
+ _set_dom_value()
2009
+ {
2010
+ // Do nothing
2011
+ }
2012
+ };
2013
+
2014
+
2015
+ class FileSignatureFieldType extends FileFieldType
2016
+ {
2017
+ instancecheck(obj)
2018
+ {
2019
+ return obj instanceof FileSignatureField;
2020
+ }
2021
+ };
2022
+
2023
+ let filesignaturefieldtype = new FileSignatureFieldType("la", "FileSignatureField", "Holds the value of a file/signature field of a record (and related information)");
2024
+
2025
+
2026
+ export class FileSignatureField extends FileField
2027
+ {
2028
+ [ul4.symbols.type]()
2029
+ {
2030
+ return filesignaturefieldtype;
2031
+ }
2032
+
2033
+ _validate(change)
2034
+ {
2035
+ // FIXME: Implement handling of data URLs.
2036
+ super._validate(change);
2037
+ }
2038
+ };
2039
+
2040
+
2041
+ class DateFieldBaseType extends FieldType
2042
+ {
2043
+ instancecheck(obj)
2044
+ {
2045
+ return obj instanceof DateFieldBase;
2046
+ }
2047
+ };
2048
+
2049
+ let datefieldbasetype = new DateFieldBaseType("la", "DateFieldBase", "Holds the value of a date field of a record (and related information)");
2050
+
2051
+
2052
+ export class DateFieldBase extends Field
2053
+ {
2054
+ [ul4.symbols.type]()
2055
+ {
2056
+ return datefieldbasetype;
2057
+ }
2058
+
2059
+ value_as_text(maxlevel=3)
2060
+ {
2061
+ let value = this.value;
2062
+ if (value === null)
2063
+ return null;
2064
+ if (typeof(value) === "string")
2065
+ return value;
2066
+ return ul4._format(value, this.control.formatstring())
2067
+ }
2068
+
2069
+ _parse(value, format)
2070
+ {
2071
+ let year = null, month = null, day = null, hour = 0, minute = 0, second = 0, ispm = null;
2072
+
2073
+ function _int(v, len, min, max)
2074
+ {
2075
+ v = v.substring(0, len);
2076
+ if (v.length != len)
2077
+ return null;
2078
+ v = parseInt(v, 10);
2079
+ if (isNaN(v) || v < min || v > max)
2080
+ return null;
2081
+ return v;
2082
+ }
2083
+
2084
+ while (value)
2085
+ {
2086
+ // Are both `value` and `format` not `null`,
2087
+ // i.e. neither `value` nor `format` is exhaused?
2088
+ if (!format)
2089
+ return null;
2090
+ if (format.startsWith("%Y"))
2091
+ {
2092
+ year = _int(value, 4);
2093
+ if (year === null)
2094
+ return null;
2095
+ value = value.substring(4);
2096
+ format = format.substring(2);
2097
+ }
2098
+ else if (format.startsWith("%y"))
2099
+ {
2100
+ year = _int(value, 2);
2101
+ if (year === null)
2102
+ return null;
2103
+ value = value.substring(2);
2104
+ format = format.substring(2);
2105
+ }
2106
+ else if (format.startsWith("%m"))
2107
+ {
2108
+ month = _int(value, 2);
2109
+ if (month === null)
2110
+ return null;
2111
+ value = value.substring(2);
2112
+ format = format.substring(2);
2113
+ }
2114
+ else if (format.startsWith("%d"))
2115
+ {
2116
+ day = _int(value, 2);
2117
+ if (day === null)
2118
+ return null;
2119
+ value = value.substring(2);
2120
+ format = format.substring(2);
2121
+ }
2122
+ else if (format.startsWith("%H"))
2123
+ {
2124
+ hour = _int(value, 2);
2125
+ if (hour === null)
2126
+ return null;
2127
+ value = value.substring(2);
2128
+ format = format.substring(2);
2129
+ }
2130
+ else if (format.startsWith("%I"))
2131
+ {
2132
+ hour = _int(value, 2);
2133
+ if (hour === null)
2134
+ return null;
2135
+ value = value.substring(2);
2136
+ format = format.substring(2);
2137
+ }
2138
+ else if (format.startsWith("%M"))
2139
+ {
2140
+ minute = _int(value, 2);
2141
+ if (minute === null)
2142
+ return null;
2143
+ value = value.substring(2);
2144
+ format = format.substring(2);
2145
+ }
2146
+ else if (format.startsWith("%S"))
2147
+ {
2148
+ second = _int(value, 2);
2149
+ if (second === null)
2150
+ return null;
2151
+ value = value.substring(2);
2152
+ format = format.substring(2);
2153
+ }
2154
+ else if (format.startsWith("%p"))
2155
+ {
2156
+ if (value.toLowerCase().startsWith("pm"))
2157
+ ispm = true;
2158
+ else if (value.toLowerCase().startsWith("am"))
2159
+ ispm = false;
2160
+ else
2161
+ return null;
2162
+ value = value.substring(2);
2163
+ format = format.substring(2);
2164
+ }
2165
+ else if (format.startsWith("%%"))
2166
+ {
2167
+ if (!value.startsWith("%"))
2168
+ return null;
2169
+ value = value.substring(1);
2170
+ format = format.substring(2);
2171
+ }
2172
+ else if (format.startsWith("%z"))
2173
+ {
2174
+ if (!value.startsWith("-") && !value.startsWith("+"))
2175
+ return null;
2176
+ value = value.substring(1);
2177
+ let _tzhour = _int(value, 2);
2178
+ if (_tzhour === null)
2179
+ return null;
2180
+ value = value.substring(2);
2181
+ if (!value.startsWith(":"))
2182
+ return null;
2183
+ value = value.substring(1);
2184
+ let _tzminute = _int(value, 2);
2185
+ if (_tzminute === null)
2186
+ return null;
2187
+ value = value.substring(2);
2188
+ format = format.substring(2);
2189
+ }
2190
+ else
2191
+ {
2192
+ if (!value.startsWith(format.substring(0, 1)))
2193
+ return null;
2194
+ value = value.substring(1);
2195
+ format = format.substring(1);
2196
+ }
2197
+ }
2198
+ // Are both `value` and `format` `null`?
2199
+ // I.e. both `value` and `format` must be exhausted, otherwise ...
2200
+ if (format)
2201
+ // ... `format` has remaining content that the value didn't provide
2202
+ return null;
2203
+
2204
+ // Check existance of values and their range
2205
+ if (year === null)
2206
+ return null;
2207
+ if (month === null || month < 1 || month > 12)
2208
+ return null;
2209
+ if (day === null || day < 1 || day > 31) // FIXME: Use the actuall number of days
2210
+ return null;
2211
+ if (ispm === null)
2212
+ {
2213
+ if (hour < 0 || hour > 23)
2214
+ return null;
2215
+ }
2216
+ else
2217
+ {
2218
+ if (hour < 0 || hour > 11)
2219
+ return null;
2220
+ if (ispm)
2221
+ hour += 12;
2222
+ }
2223
+ if (minute < 0 || minute > 59)
2224
+ return null;
2225
+ if (minute < 0 || minute > 59)
2226
+ return null;
2227
+ if (second < 0 || second > 60)
2228
+ return null;
2229
+ return new Date(year, month-1, day, hour, minute, second);
2230
+ }
2231
+
2232
+ _validate(change)
2233
+ {
2234
+ if (change.value === null || change.value === "")
2235
+ {
2236
+ if (this.control.required)
2237
+ change.errors.push(this.msg_field_required(change.value));
2238
+ change.value = null;
2239
+ }
2240
+ else if (change.value instanceof Date)
2241
+ {
2242
+ change.value = this._convert(change.value);
2243
+ }
2244
+ else if (change.value instanceof ul4.Date_)
2245
+ {
2246
+ change.value = this._convert(change.value._date);
866
2247
  }
867
2248
  else if (typeof(change.value) === "string")
868
2249
  {
869
- let minlength = this.control.minlength;
870
- let maxlength = this.control.maxlength;
871
- if (minlength !== null && change.value.length < minlength)
872
- change.errors.push(this.msg_string_tooshort(change.value))
873
- if (maxlength !== null && change.value.length > maxlength)
874
- change.errors.push(this.msg_string_toolong(change.value))
2250
+ let value = null;
2251
+ for (let format of this.control.formatstrings_parse())
2252
+ {
2253
+ value = this._parse(change.value, format);
2254
+ if (value !== null)
2255
+ break;
2256
+ }
2257
+ if (value !== null)
2258
+ change.value = this._convert(value);
2259
+ else
2260
+ change.errors.push(this.msg_date_format(change.value));
2261
+ // Keep original invalid string
875
2262
  }
876
2263
  else
877
2264
  {
@@ -879,234 +2266,275 @@ export class StringField extends Field
879
2266
  change.value = null;
880
2267
  }
881
2268
  }
882
- };
883
-
884
-
885
- export class EmailField extends StringField
886
- {
887
- static classdoc = "Holds the value of a string/email field of a record (and related information)";
888
2269
 
889
- _validate(change)
2270
+ _get_dom_value()
890
2271
  {
891
- if (typeof(change.value) === "string" && change.value.length > 0)
2272
+ let value = super._get_dom_value();
2273
+ if (!value)
2274
+ return null;
2275
+
2276
+ for (let format of this.control.formatstrings_parse())
892
2277
  {
893
- const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/i;
894
- if (!re.test(change.value))
895
- change.errors.push(this.msg_email_format(change.value));
2278
+ let date = this._parse(value, format);
2279
+ if (date !== null)
2280
+ return this._convert(date);
896
2281
  }
897
- super._validate(change);
2282
+ return null;
2283
+ }
2284
+
2285
+ _set_dom_value(value)
2286
+ {
2287
+ if (value !== null)
2288
+ value = ul4._format(value, this.control.formatstring(), this.globals.lang);
2289
+ super._set_dom_value(value);
898
2290
  }
899
2291
  };
900
2292
 
901
2293
 
902
- export class URLField extends StringField
2294
+ class DateFieldType extends DateFieldBaseType
903
2295
  {
904
- static classdoc = "Holds the value of a string/url field of a record (and related information)";
905
-
906
- _validate(change)
2296
+ instancecheck(obj)
907
2297
  {
908
- if (typeof(change.value) === "string" && change.value.length > 0)
909
- {
910
- let url = null;
911
- try
912
- {
913
- url = new URL(change.value);
914
- }
915
- catch (exc)
916
- {
917
- change.errors.push(this.msg_url_format(change.value));
918
- }
919
- if (url !== null && url.protocol !== "http:" && url.protocol !== "https:")
920
- {
921
- change.errors.push(this.msg_url_format(change.value));
922
- }
923
- }
924
- super._validate(change);
2298
+ return obj instanceof DateField;
925
2299
  }
926
2300
  };
927
2301
 
2302
+ let datefieldtype = new DateFieldType("la", "DateField", "Holds the value of a date/date field of a record (and related information)");
928
2303
 
929
- export class TelField extends StringField
2304
+
2305
+ export class DateField extends DateFieldBase
930
2306
  {
931
- static classdoc = "Holds the value of a string/tel field of a record (and related information)";
2307
+ [ul4.symbols.type]()
2308
+ {
2309
+ return datefieldtype;
2310
+ }
932
2311
 
933
- _validate(change)
2312
+ _convert(date)
934
2313
  {
935
- if (typeof(change.value) === "string" && change.value.length > 0)
936
- {
937
- const re = /^\\+?[0-9 /()-]+$/;
938
- if (!re.test(change.value))
939
- change.errors.push(this.msg_tel_format(change.value));
940
- }
941
- super._validate(change);
2314
+ return new ul4.Date_(date.getFullYear(), date.getMonth()+1, date.getDate());
942
2315
  }
943
2316
  };
944
2317
 
945
2318
 
946
- export class TextAreaField extends StringField
2319
+ class DatetimeMinuteFieldType extends DateFieldBaseType
947
2320
  {
948
- static classdoc = "Holds the value of a string/textarea field of a record (and related information)";
2321
+ instancecheck(obj)
2322
+ {
2323
+ return obj instanceof DatetimeMinuteField;
2324
+ }
949
2325
  };
950
2326
 
951
-
952
- export class HTMLField extends StringField
953
- {
954
- static classdoc = "Holds the value of a string/html field of a record (and related information)";
955
- };
2327
+ let datetimeminutefieldtype = new DatetimeMinuteFieldType("la", "DatetimeMinuteField", "Holds the value of a date/datetimeminute field of a record (and related information)");
956
2328
 
957
2329
 
958
- export class GeoField extends Field
2330
+ export class DatetimeMinuteField extends DateFieldBase
959
2331
  {
960
- static classdoc = "Holds the value of a geo field of a record (and related information)";
2332
+ [ul4.symbols.type]()
2333
+ {
2334
+ return datetimeminutefieldtype;
2335
+ }
961
2336
 
962
- _validate(change)
2337
+ _convert(date)
963
2338
  {
964
- if (change.value === null || change.value === "")
965
- {
966
- if (this.control.required)
967
- change.errors.push(this.msg_field_required(change.value));
968
- change.value = null;
969
- }
970
- else if (!(change.value instanceof Geo))
971
- {
972
- change.errors.push(this.msg_field_wrong_type(change.value));
973
- change.value = null;
974
- }
2339
+ // Get rid of seconds and milliseconds, this modifies the object passed in.
2340
+ date.setSeconds(0);
2341
+ date.setMilliseconds(0);
2342
+ return date;
975
2343
  }
976
2344
  };
977
2345
 
978
2346
 
979
- export class FileField extends Field
2347
+ class DatetimeSecondFieldType extends DateFieldBaseType
980
2348
  {
981
- static classdoc = "Holds the value of a file field of a record (and related information)";
982
-
983
- _validate(change)
2349
+ instancecheck(obj)
984
2350
  {
985
- if (change.value === null || change.value === "")
986
- {
987
- if (this.control.required)
988
- change.errors.push(this.msg_field_required(change.value));
989
- change.value = null;
990
- }
991
- else if (!(change.value instanceof File))
992
- {
993
- change.errors.push(this.msg_field_wrong_type(change.value));
994
- change.value = null;
995
- }
2351
+ return obj instanceof DatetimeSecondField;
996
2352
  }
997
2353
  };
998
2354
 
2355
+ let datetimesecondfieldtype = new DatetimeSecondFieldType("la", "DatetimeSecondField", "Holds the value of a date/datetimesecond field of a record (and related information)");
999
2356
 
1000
- export class FileSignatureField extends FileField
2357
+
2358
+ export class DatetimeSecondField extends DateFieldBase
1001
2359
  {
1002
- static classdoc = "Holds the value of a file/signature field of a record (and related information)";
2360
+ [ul4.symbols.type]()
2361
+ {
2362
+ return datetimesecondfieldtype;
2363
+ }
1003
2364
 
1004
- _validate(change)
2365
+ _convert(date)
1005
2366
  {
1006
- // FIXME: Implement handling of data URLs.
1007
- super._validate(change);
2367
+ // Get rid of milliseconds, this modifies the object passed in.
2368
+ date.setMilliseconds(0);
2369
+ return date;
1008
2370
  }
1009
2371
  };
1010
2372
 
2373
+ /*
2374
+ `ChoiceFieldBase` is used as the base class for all `lookup`, `multiplelookup`,
2375
+ `applookup` and `multipleapplookup` fields.
1011
2376
 
1012
- export class DateFieldBase extends Field
2377
+ Since the inheritance hierarchy follows the data model *not* which HTML element
2378
+ is used for editing, we would have to implement the same DOM interaction logic
2379
+ in multiple classes (i.e. we would have to handle a HTML `select` element in
2380
+ `LookupSelectField`, `MultipleLookupSelectField`, `AppLookupSelectField`
2381
+ and `MultipleAppLookupSelectField`).
2382
+
2383
+ To solve this problem, all methods that handle HTML elements are implemented in
2384
+ this class. Subclasses then simply call the appropriate method.
2385
+ */
2386
+ export class ChoiceFieldBase extends Field
1013
2387
  {
1014
- static classdoc = "Holds the value of a date field of a record (and related information)";
2388
+ _make_option(selected, value, label)
2389
+ {
2390
+ let option = element(
2391
+ "option",
2392
+ label,
2393
+ {
2394
+ "value": value,
2395
+ "class": value === this.control.nonekey ? "la-none-option" : null,
2396
+ "selected": selected ? "selected" : null,
2397
+ }
2398
+ );
2399
+ return option;
2400
+ }
1015
2401
 
1016
- _validate(change)
2402
+ _set_dom_lookupdata_select(lookupdata)
1017
2403
  {
1018
- if (change.value === null || change.value === "")
2404
+ if (lookupdata === null)
2405
+ lookupdata = this.control.lookup_data;
2406
+ if (ul4._isobject(lookupdata))
2407
+ lookupdata = new Map(Object.entries(lookupdata));
2408
+
2409
+ let none_selected = false;
2410
+ let selected = new Set();
2411
+ for (let dom_option of this._dom_control.querySelectorAll("option:checked"))
1019
2412
  {
1020
- if (this.control.required)
1021
- change.errors.push(this.msg_field_required(change.value));
1022
- change.value = null;
2413
+ let value = dom_option.getAttribute("value");
2414
+ if (lookupdata.has(value))
2415
+ selected.add(value);
2416
+ else if (value === this.control.nonekey)
2417
+ none_selected = true;
1023
2418
  }
1024
- else if (change.value instanceof Date)
2419
+
2420
+ let new_children = [];
2421
+ if (this.control.nonekey !== null)
1025
2422
  {
1026
- change.value = this._convert(new Date(change.value.getTime()));
2423
+ new_children.push(
2424
+ this._make_option(
2425
+ none_selected,
2426
+ this.control.nonekey,
2427
+ this.control.nonelabel !== null ? this.control.nonelabel : this.globals.msg_nothing_selected()
2428
+ )
2429
+ );
1027
2430
  }
1028
- else if (typeof(change.value) === "string")
2431
+
2432
+ for (let [key, value] of lookupdata)
1029
2433
  {
1030
- let value = null;
1031
- if (change.value.length === 10)
1032
- value = new Date(change.value + "T00:00:00");
1033
- else if (change.value.length === 16)
1034
- value = new Date(change.value + ":00");
1035
- else if (change.value.length === 19)
1036
- value = new Date(change.value);
1037
-
1038
- if (value === null || Number.isNaN(value.getYear()))
2434
+ new_children.push(
2435
+ this._make_option(
2436
+ selected.has(key),
2437
+ key,
2438
+ this._make_label(value)
2439
+ )
2440
+ );
2441
+ }
2442
+ this._dom_control.replaceChildren(...new_children);
2443
+ }
2444
+
2445
+ _set_dom_lookupdata_input(lookupdata)
2446
+ {
2447
+ if (lookupdata === null)
2448
+ lookupdata = this.control.lookupdata;
2449
+ else if (ul4._isobject(lookupdata))
2450
+ lookupdata = new Map(Object.entries(lookupdata));
2451
+
2452
+ let none_selected = false;
2453
+ let selected = new Set();
2454
+ for (let dom_input of this._dom_controls)
2455
+ {
2456
+ let value = dom_input.getAttribute("value");
2457
+ if (dom_input.checked)
1039
2458
  {
1040
- change.errors.push(this.msg_date_format(change.value));
1041
- // Keep original invalid string
2459
+ if (lookupdata.has(value))
2460
+ selected.add(value);
2461
+ else if (value === this.control.nonekey)
2462
+ none_selected = true;
2463
+
2464
+ }
2465
+ }
2466
+
2467
+ let dom_none_input = this._dom_root.querySelector("input[value=" + this.control.nonekey + "]");
2468
+ if (dom_none_input !== null)
2469
+ dom_none_input.checked = none_selected;
2470
+
2471
+ for (let [key, item] of this.control.lookupdata)
2472
+ {
2473
+ let dom_input = this._dom_root.querySelector("input[value=" + key + "]");
2474
+ let dom_label = this._dom_root.querySelector("label[for=" + dom_input.id + "]")
2475
+
2476
+ if (lookupdata.has(key))
2477
+ {
2478
+ dom_input.style.display = "inline";
2479
+ dom_label.style.display = "inline";
2480
+ dom_label.innerText = this._make_label(lookupdata.get(key));
1042
2481
  }
1043
2482
  else
1044
2483
  {
1045
- change.value = this._convert(value);
2484
+ dom_input.style.display = "none";
2485
+ dom_label.style.display = "none";
2486
+ dom_label.checked = false;
1046
2487
  }
1047
2488
  }
1048
- else
1049
- {
1050
- change.errors.push(this.msg_field_wrong_type(change.value));
1051
- change.value = null;
1052
- }
1053
2489
  }
1054
2490
  };
1055
2491
 
1056
2492
 
1057
- export class DateField extends DateFieldBase
2493
+ class LookupFieldBaseType extends FieldType
1058
2494
  {
1059
- static classdoc = "Holds the value of a date/date field of a record (and related information)";
1060
-
1061
- _convert(date)
2495
+ instancecheck(obj)
1062
2496
  {
1063
- return new ul4.Date_(date.getFullYear(), date.getMonth()+1, date.getDate());
2497
+ return obj instanceof LookupFieldBase;
1064
2498
  }
1065
2499
  };
1066
2500
 
1067
-
1068
- export class DatetimeMinuteField extends DateFieldBase
1069
- {
1070
- static classdoc = "Holds the value of a date/datetimeminute field of a record (and related information)";
1071
-
1072
- _convert(date)
1073
- {
1074
- // Get rid of seconds and milliseconds
1075
- date.setSeconds(0);
1076
- date.setMilliseconds(0);
1077
- return date;
1078
- }
1079
- };
2501
+ let lookupfieldbasetype = new LookupFieldBaseType("la", "LookupFieldBase", "Base type of LookupField and MultipleLookupField");
1080
2502
 
1081
2503
 
1082
- export class DatetimeSecondField extends DateFieldBase
2504
+ export class LookupFieldBase extends ChoiceFieldBase
1083
2505
  {
1084
- static classdoc = "Holds the value of a date/datetimesecond field of a record (and related information)";
1085
-
1086
- _convert(date)
2506
+ [ul4.symbols.type]()
1087
2507
  {
1088
- // Get rid of milliseconds
1089
- date.setMilliseconds(0);
1090
- return date;
2508
+ return lookupfieldbasetype;
1091
2509
  }
1092
- };
1093
-
1094
-
1095
- export class LookupFieldBase extends Field
1096
- {
1097
- static classdoc = "Base type of LookupField and MultipleLookupField";
1098
2510
 
1099
2511
  get lookupdata()
1100
2512
  {
1101
- if (this._lookupdate !== null)
1102
- return this._lookupdate;
2513
+ if (this._lookupdata !== null)
2514
+ return this._lookupdata;
1103
2515
  else
1104
2516
  return this.control.lookupdata;
1105
2517
  }
1106
2518
 
1107
2519
  set lookupdata(value)
1108
2520
  {
1109
- this._lookupdate = value;
2521
+ if (this._in_form())
2522
+ this._set_dom_lookupdata(value);
2523
+ this._lookupdata = value;
2524
+ }
2525
+
2526
+ _set_dom_lookupdata(lookupdata)
2527
+ {
2528
+ }
2529
+
2530
+ _make_label(value)
2531
+ {
2532
+ if (typeof(value) === "string")
2533
+ return value;
2534
+ else if (value instanceof LookupItem)
2535
+ return value.label;
2536
+ else
2537
+ return ul4._str(value);
1110
2538
  }
1111
2539
 
1112
2540
  _find_lookupitem(change)
@@ -1114,12 +2542,12 @@ export class LookupFieldBase extends Field
1114
2542
  let v = change.value;
1115
2543
  if (typeof(v) === "string")
1116
2544
  {
1117
- // If `lookupdata`} is `null`, this is probably an interface,
2545
+ // If `lookupdata` is `null`, this probably an interface,
1118
2546
  // so we can't validate anything (note that interfaces will however go
1119
2547
  // away in the future)
1120
2548
  if (this.lookupdata === null)
1121
2549
  return;
1122
- let lookupitem = this.lookupdata.get(v);
2550
+ let lookupitem = this.control.lookupdata.get(v);
1123
2551
  if (lookupitem === undefined)
1124
2552
  {
1125
2553
  // If the lookup control is auto expandable,
@@ -1166,30 +2594,199 @@ export class LookupFieldBase extends Field
1166
2594
  };
1167
2595
 
1168
2596
 
1169
- export class LookupField extends LookupFieldBase
2597
+ class LookupFieldType extends LookupFieldBaseType
2598
+ {
2599
+ instancecheck(obj)
2600
+ {
2601
+ return obj instanceof LookupField;
2602
+ }
2603
+ };
2604
+
2605
+ let lookupfieldtype = new LookupFieldType("la", "LookupField", "Holds the value of a lookup field of a record (and related information)");
2606
+
2607
+
2608
+ export class LookupField extends LookupFieldBase
2609
+ {
2610
+ [ul4.symbols.type]()
2611
+ {
2612
+ return lookupfieldtype;
2613
+ }
2614
+
2615
+ value_as_text(maxlevel=3)
2616
+ {
2617
+ let value = this.value;
2618
+ if (value === null)
2619
+ return null;
2620
+ return value.label;
2621
+ }
2622
+
2623
+ _validate(change)
2624
+ {
2625
+ let v = change.value;
2626
+ if (v === null || v === "" || this.control.nonekey === v)
2627
+ {
2628
+ if (this.control.required)
2629
+ change.errors.push(this.msg_field_required(v));
2630
+ change.value = null;
2631
+ }
2632
+ else
2633
+ {
2634
+ this._find_lookupitem(change);
2635
+ }
2636
+ }
2637
+ };
2638
+
2639
+
2640
+ class LookupRadioFieldType extends LookupFieldType
2641
+ {
2642
+ instancecheck(obj)
2643
+ {
2644
+ return obj instanceof LookupRadioField;
2645
+ }
2646
+ };
2647
+
2648
+ let lookupradiofieldtype = new LookupRadioFieldType("la", "LookupRadioField", "Holds the value of a lookup/radio field of a record (and related information)");
2649
+
2650
+
2651
+ export class LookupRadioField extends LookupField
2652
+ {
2653
+ [ul4.symbols.type]()
2654
+ {
2655
+ return lookupradiofieldtype;
2656
+ }
2657
+
2658
+ get _sel_label()
2659
+ {
2660
+ return this._sel_root + " label:not([for]) > span";
2661
+ }
2662
+
2663
+ _get_dom_value()
2664
+ {
2665
+ for (let node of this._dom_controls)
2666
+ {
2667
+ if (node.checked)
2668
+ {
2669
+ let key = node.getAttribute("value");
2670
+ return this.control.lookupdata.get(key);
2671
+ }
2672
+
2673
+ }
2674
+ return null;
2675
+ }
2676
+
2677
+ _set_dom_value(value)
2678
+ {
2679
+ if (value instanceof LookupItem)
2680
+ value = value.key;
2681
+ if (value === null)
2682
+ value = this.control.nonekey;
2683
+
2684
+ for (let node of this._dom_controls)
2685
+ node.checked = node.getAttribute("value") === value;
2686
+ }
2687
+
2688
+ _set_dom_lookupdata(lookupdata)
2689
+ {
2690
+ this._set_dom_lookupdata_input(lookupdata);
2691
+ }
2692
+ };
2693
+
2694
+
2695
+ class LookupSelectFieldType extends LookupFieldType
1170
2696
  {
1171
- static classdoc = "Holds the value of a lookup field of a record (and related information)";
2697
+ instancecheck(obj)
2698
+ {
2699
+ return obj instanceof LookupSelectField;
2700
+ }
2701
+ };
1172
2702
 
1173
- _validate(change)
2703
+ let lookupselectfieldtype = new LookupSelectFieldType("la", "LookupSelectField", "Holds the value of a lookup/select field of a record (and related information)");
2704
+
2705
+
2706
+ export class LookupSelectField extends LookupField
2707
+ {
2708
+ [ul4.symbols.type]()
1174
2709
  {
1175
- let v = change.value;
1176
- if (v === null || v === "" || this.control.nonekey === v)
1177
- {
1178
- if (this.control.required)
1179
- change.errors.push(this.msg_field_required(v));
1180
- change.value = null;
1181
- }
1182
- else
2710
+ return lookupselectfieldtype;
2711
+ }
2712
+
2713
+ _get_dom_value()
2714
+ {
2715
+ let value = super._get_dom_value();
2716
+ if (value)
1183
2717
  {
1184
- this._find_lookupitem(change);
2718
+ if (value === this.control.nonekey)
2719
+ value = null;
2720
+ else
2721
+ value = this.control.lookupdata.get(value);
1185
2722
  }
2723
+ return value;
2724
+ }
2725
+
2726
+ _set_dom_value(value)
2727
+ {
2728
+ let change = {value: value, errors: []};
2729
+ this._validate(change);
2730
+ super._set_dom_value(change.value != null ? change.value.key : this.control.nonekey);
2731
+ }
2732
+
2733
+ _set_dom_lookupdata(lookupdata)
2734
+ {
2735
+ this._set_dom_lookupdata_select(lookupdata);
2736
+ }
2737
+ };
2738
+
2739
+
2740
+ class LookupChoiceFieldType extends LookupFieldType
2741
+ {
2742
+ instancecheck(obj)
2743
+ {
2744
+ return obj instanceof LookupChoiceField;
2745
+ }
2746
+ };
2747
+
2748
+ let lookupchoicefieldtype = new LookupChoiceFieldType("la", "LookupChoiceField", "Holds the value of a lookup/choice field of a record (and related information)");
2749
+
2750
+
2751
+ export class LookupChoiceField extends LookupField
2752
+ {
2753
+ [ul4.symbols.type]()
2754
+ {
2755
+ return lookupchoicefieldtype;
2756
+ }
2757
+ };
2758
+
2759
+
2760
+ class MultipleLookupFieldType extends LookupFieldBaseType
2761
+ {
2762
+ instancecheck(obj)
2763
+ {
2764
+ return obj instanceof MultipleLookupField;
1186
2765
  }
1187
2766
  };
1188
2767
 
2768
+ let multiplelookupfieldtype = new MultipleLookupFieldType("la", "MultipleLookupField", "Holds the value of a multiple lookup field of a record (and related information)");
2769
+
1189
2770
 
1190
2771
  export class MultipleLookupField extends LookupFieldBase
1191
2772
  {
1192
- static classdoc = "Holds the value of a multiple lookup field of a record (and related information)";
2773
+ [ul4.symbols.type]()
2774
+ {
2775
+ return multiplelookupfieldtype;
2776
+ }
2777
+
2778
+ is_empty()
2779
+ {
2780
+ return this._value.length === 0;
2781
+ }
2782
+
2783
+ value_as_text(maxlevel=3)
2784
+ {
2785
+ let value = this.value;
2786
+ if (value === null || value.length === 0)
2787
+ return null;
2788
+ return value.map(item => item.label).join(", ");
2789
+ }
1193
2790
 
1194
2791
  _validate(change)
1195
2792
  {
@@ -1228,14 +2825,151 @@ export class MultipleLookupField extends LookupFieldBase
1228
2825
  };
1229
2826
 
1230
2827
 
1231
- export class AppLookupFieldBase extends Field
2828
+ class MultipleLookupCheckboxFieldType extends MultipleLookupFieldType
2829
+ {
2830
+ instancecheck(obj)
2831
+ {
2832
+ return obj instanceof MultipleLookupCheckboxField;
2833
+ }
2834
+ };
2835
+
2836
+ let multiplelookupcheckboxfieldtype = new MultipleLookupCheckboxFieldType("la", "MultipleLookupCheckboxField", "Holds the value of a multiplelookup/radio field of a record (and related information)");
2837
+
2838
+
2839
+ export class MultipleLookupCheckboxField extends MultipleLookupField
2840
+ {
2841
+ [ul4.symbols.type]()
2842
+ {
2843
+ return multiplelookupcheckboxfieldtype;
2844
+ }
2845
+
2846
+ get _sel_label()
2847
+ {
2848
+ return this._sel_root + " label:not([for]) > span";
2849
+ }
2850
+
2851
+ _get_dom_value()
2852
+ {
2853
+ let value = [];
2854
+ for (let node of this._dom_controls)
2855
+ {
2856
+ if (node.checked)
2857
+ {
2858
+ let key = node.getAttribute("value");
2859
+ value.push(this.control.lookupdata.get(key));
2860
+ }
2861
+
2862
+ }
2863
+ return value;
2864
+ }
2865
+
2866
+ _set_dom_value(value)
2867
+ {
2868
+ let change = {value: value, errors: []};
2869
+ this._validate(change);
2870
+ let values = new Set();
2871
+ for (let value of change.value)
2872
+ values.add(value.key);
2873
+
2874
+ for (let node of this._dom_controls)
2875
+ node.checked = values.has(node.getAttribute("value"));
2876
+ }
2877
+
2878
+ _set_dom_lookupdata(lookupdata)
2879
+ {
2880
+ this._set_dom_lookupdata_input(lookupdata);
2881
+ }
2882
+ };
2883
+
2884
+
2885
+ class MultipleLookupSelectFieldType extends MultipleLookupFieldType
2886
+ {
2887
+ instancecheck(obj)
2888
+ {
2889
+ return obj instanceof MultipleLookupSelectField;
2890
+ }
2891
+ };
2892
+
2893
+ let multiplelookupselectfieldtype = new MultipleLookupSelectFieldType("la", "MultipleLookupSelectField", "Holds the value of a multiplelookup/select field of a record (and related information)");
2894
+
2895
+ export class MultipleLookupSelectField extends MultipleLookupField
2896
+ {
2897
+ [ul4.symbols.type]()
2898
+ {
2899
+ return multiplelookupselectfieldtype;
2900
+ }
2901
+
2902
+ _get_dom_value()
2903
+ {
2904
+ let value = [];
2905
+ for (let option of this._dom_control.querySelectorAll("option"))
2906
+ {
2907
+ if (option.selected)
2908
+ value.push(this.control.lookupdata.get(option.getAttribute("value")));
2909
+ }
2910
+ return value;
2911
+ }
2912
+
2913
+ _set_dom_value(value)
2914
+ {
2915
+ let change = {value: value, errors: []};
2916
+ this._validate(change);
2917
+ let values = new Set();
2918
+ for (let value of change.value)
2919
+ values.add(value.key);
2920
+ for (let option of this._dom_control.querySelectorAll("option"))
2921
+ option.selected = values.has(option.getAttribute("value"));
2922
+ }
2923
+
2924
+ _set_dom_lookupdata(lookupdata)
2925
+ {
2926
+ this._set_dom_lookupdata_select(lookupdata);
2927
+ }
2928
+ };
2929
+
2930
+
2931
+ class MultipleLookupChoiceFieldType extends MultipleLookupFieldType
2932
+ {
2933
+ instancecheck(obj)
2934
+ {
2935
+ return obj instanceof MultipleLookupChoiceField;
2936
+ }
2937
+ };
2938
+
2939
+ let multiplelookupchoicefieldtype = new MultipleLookupChoiceFieldType("la", "MultipleLookupChoiceField", "Holds the value of a multiplelookup/choice field of a record (and related information)");
2940
+
2941
+
2942
+ export class MultipleLookupChoiceField extends MultipleLookupField
2943
+ {
2944
+ [ul4.symbols.type]()
2945
+ {
2946
+ return multiplelookupchoicefieldtype;
2947
+ }
2948
+ };
2949
+
2950
+
2951
+ class AppLookupFieldBaseType extends FieldType
2952
+ {
2953
+ instancecheck(obj)
2954
+ {
2955
+ return obj instanceof AppLookupFieldBase;
2956
+ }
2957
+ };
2958
+
2959
+ let applookupfieldbasetype = new AppLookupFieldBaseType("la", "AppLookupFieldBase", "Base type of AppLookupField and MultipleAppLookupField");
2960
+
2961
+
2962
+ export class AppLookupFieldBase extends ChoiceFieldBase
1232
2963
  {
1233
- static classdoc = "Base type of AppLookupField and MultipleAppLookupField";
2964
+ [ul4.symbols.type]()
2965
+ {
2966
+ return applookupfieldbasetype;
2967
+ }
1234
2968
 
1235
2969
  get lookupdata()
1236
2970
  {
1237
- if (this._lookupdate !== null)
1238
- return this._lookupdate;
2971
+ if (this._lookupdata !== null)
2972
+ return this._lookupdata;
1239
2973
  else
1240
2974
  {
1241
2975
  if (this.control.lookup_app.records !== null)
@@ -1246,7 +2980,23 @@ export class AppLookupFieldBase extends Field
1246
2980
 
1247
2981
  set lookupdata(value)
1248
2982
  {
1249
- this._lookupdate = value;
2983
+ if (this._in_form())
2984
+ this._set_dom_lookupdata(value);
2985
+ this._lookupdata = value;
2986
+ }
2987
+
2988
+ _set_dom_lookupdata(lookupdata)
2989
+ {
2990
+ }
2991
+
2992
+ _make_label(value)
2993
+ {
2994
+ if (typeof(value) === "string")
2995
+ return value;
2996
+ else if (value instanceof Record)
2997
+ return value.as_text(this.control.lookup_controls);
2998
+ else
2999
+ return ul4._str(value);
1250
3000
  }
1251
3001
 
1252
3002
  _find_record(change)
@@ -1254,7 +3004,11 @@ export class AppLookupFieldBase extends Field
1254
3004
  let v = change.value;
1255
3005
  if (typeof(v) === "string")
1256
3006
  {
1257
- let record = this.lookupdata.get(v);
3007
+ let record = this.control.lookup_app.records !== null ?
3008
+ this.control.lookup_app.records.get(v) :
3009
+ undefined
3010
+ ;
3011
+
1258
3012
  if (record === undefined)
1259
3013
  {
1260
3014
  change.errors.push(this.msg_applookup_unknownkey(v))
@@ -1279,12 +3033,44 @@ export class AppLookupFieldBase extends Field
1279
3033
  change.value = null;
1280
3034
  }
1281
3035
  }
3036
+
3037
+ [ul4.symbols.setattr](key, value)
3038
+ {
3039
+ if (key === "lookupdata")
3040
+ this.lookupdata = value;
3041
+ else
3042
+ super[ul4.symbols.setattr](key, value);
3043
+ }
3044
+ };
3045
+ AppLookupFieldBase.prototype._ul4attrs = new Set([...Field.prototype._ul4attrs, "lookupdata"]);
3046
+
3047
+
3048
+
3049
+ class AppLookupFieldType extends AppLookupFieldBaseType
3050
+ {
3051
+ instancecheck(obj)
3052
+ {
3053
+ return obj instanceof AppLookupField;
3054
+ }
1282
3055
  };
1283
3056
 
3057
+ let applookupfieldtype = new AppLookupFieldType("la", "AppLookupField", "Holds the value of a applookup field of a record (and related information)");
3058
+
1284
3059
 
1285
3060
  export class AppLookupField extends AppLookupFieldBase
1286
3061
  {
1287
- static classdoc = "Holds the value of a applookup field of a record (and related information)";
3062
+ [ul4.symbols.type]()
3063
+ {
3064
+ return applookupfieldtype;
3065
+ }
3066
+
3067
+ value_as_text(maxlevel=3)
3068
+ {
3069
+ let value = this.value;
3070
+ if (value === null)
3071
+ return null;
3072
+ return "(" + this.value.as_text(maxlevel) + ")";
3073
+ }
1288
3074
 
1289
3075
  _validate(change)
1290
3076
  {
@@ -1293,9 +3079,115 @@ export class AppLookupField extends AppLookupFieldBase
1293
3079
  };
1294
3080
 
1295
3081
 
3082
+ class AppLookupSelectFieldType extends AppLookupFieldType
3083
+ {
3084
+ instancecheck(obj)
3085
+ {
3086
+ return obj instanceof AppLookupSelectField;
3087
+ }
3088
+ };
3089
+
3090
+ let applookupselectfieldtype = new AppLookupSelectFieldType("la", "AppLookupSelectField", "Holds the value of a `applookup`/`select` field of a record (and related information)");
3091
+
3092
+
3093
+ export class AppLookupSelectField extends AppLookupField
3094
+ {
3095
+ [ul4.symbols.type]()
3096
+ {
3097
+ return applookupselectfieldtype;
3098
+ }
3099
+
3100
+ _get_dom_value()
3101
+ {
3102
+ let value = super._get_dom_value();
3103
+
3104
+ if (this.control.lookup_app.records !== null)
3105
+ {
3106
+ value = this.control.lookup_app.records.get(value);
3107
+ if (value === undefined)
3108
+ value = null;
3109
+ }
3110
+ else
3111
+ value = null;
3112
+ return value;
3113
+ }
3114
+
3115
+ _set_dom_value(value)
3116
+ {
3117
+ let change = {value: value, errors: []};
3118
+ this._validate(change);
3119
+ super._set_dom_value(change.value != null ? change.value.id : this.control.nonekey);
3120
+ }
3121
+
3122
+ _set_dom_lookupdata(lookupdata)
3123
+ {
3124
+ this._set_dom_lookupdata_select(lookupdata);
3125
+ }
3126
+ };
3127
+
3128
+
3129
+ class AppLookupRadioFieldType extends AppLookupFieldType
3130
+ {
3131
+ instancecheck(obj)
3132
+ {
3133
+ return obj instanceof AppLookupRadioField;
3134
+ }
3135
+ };
3136
+
3137
+ let applookupradiofieldtype = new AppLookupRadioFieldType("la", "AppLookupRadioField", "Holds the value of a `applookup`/`radio` field of a record (and related information)");
3138
+
3139
+
3140
+ export class AppLookupRadioField extends AppLookupField
3141
+ {
3142
+ [ul4.symbols.type]()
3143
+ {
3144
+ return applookupradiofieldtype;
3145
+ }
3146
+ };
3147
+
3148
+
3149
+ class AppLookupChoiceFieldType extends AppLookupFieldType
3150
+ {
3151
+ instancecheck(obj)
3152
+ {
3153
+ return obj instanceof AppLookupChoiceField;
3154
+ }
3155
+ };
3156
+
3157
+ let applookupchoicefieldtype = new AppLookupChoiceFieldType("la", "AppLookupChoiceField", "Holds the value of a `applookup`/`choice` field of a record (and related information)");
3158
+
3159
+
3160
+ export class AppLookupChoiceField extends AppLookupField
3161
+ {
3162
+ [ul4.symbols.type]()
3163
+ {
3164
+ return applookupchoicefieldtype;
3165
+ }
3166
+ };
3167
+
3168
+
3169
+ class MultipleAppLookupFieldType extends AppLookupFieldBaseType
3170
+ {
3171
+ instancecheck(obj)
3172
+ {
3173
+ return obj instanceof MultipleAppLookupField;
3174
+ }
3175
+ };
3176
+
3177
+ let multipleapplookupfieldtype = new MultipleAppLookupFieldType("la", "MultipleAppLookupField", "Holds the value of a multiple applookup field of a record (and related information)");
3178
+
3179
+
1296
3180
  export class MultipleAppLookupField extends AppLookupFieldBase
1297
3181
  {
1298
- static classdoc = "Holds the value of a multiple applookup field of a record (and related information)";
3182
+ [ul4.symbols.type]()
3183
+ {
3184
+ return multipleapplookupfieldtype;
3185
+ }
3186
+
3187
+ is_empty()
3188
+ {
3189
+ return this._value.length === 0;
3190
+ }
1299
3191
 
1300
3192
  _validate(change)
1301
3193
  {
@@ -1334,8 +3226,89 @@ export class MultipleAppLookupField extends AppLookupFieldBase
1334
3226
  };
1335
3227
 
1336
3228
 
3229
+ class MultipleAppLookupCheckboxFieldType extends MultipleAppLookupFieldType
3230
+ {
3231
+ instancecheck(obj)
3232
+ {
3233
+ return obj instanceof MultipleAppLookupCheckboxField;
3234
+ }
3235
+ };
3236
+
3237
+ let multipleapplookupcheckboxfieldtype = new MultipleAppLookupCheckboxFieldType("la", "MultipleAppLookupCheckboxField", "Holds the value of a `multipleapplookup`/`checkbox` field of a record (and related information)");
3238
+
3239
+
3240
+ export class MultipleAppLookupCheckboxField extends MultipleAppLookupField
3241
+ {
3242
+ [ul4.symbols.type]()
3243
+ {
3244
+ return multipleapplookupcheckboxfieldtype;
3245
+ }
3246
+ };
3247
+
3248
+
3249
+ class MultipleAppLookupSelectFieldType extends MultipleAppLookupFieldType
3250
+ {
3251
+ instancecheck(obj)
3252
+ {
3253
+ return obj instanceof MultipleAppLookupSelectField;
3254
+ }
3255
+ };
3256
+
3257
+ let multipleapplookupselectfieldtype = new MultipleAppLookupSelectFieldType("la", "MultipleAppLookupSelectField", "Holds the value of a `multipleapplookup`/`select` field of a record (and related information)");
3258
+
3259
+
3260
+ export class MultipleAppLookupSelectField extends MultipleAppLookupField
3261
+ {
3262
+ [ul4.symbols.type]()
3263
+ {
3264
+ return multipleapplookupselectfieldtype;
3265
+ }
3266
+
3267
+ _set_dom_lookupdata(lookupdata)
3268
+ {
3269
+ this._set_dom_lookupdata_select(lookupdata);
3270
+ }
3271
+ };
3272
+
3273
+
3274
+ class MultipleAppLookupChoiceFieldType extends MultipleAppLookupFieldType
3275
+ {
3276
+ instancecheck(obj)
3277
+ {
3278
+ return obj instanceof MultipleAppLookupChoiceField;
3279
+ }
3280
+ };
3281
+
3282
+ let multipleapplookupchoicefieldtype = new MultipleAppLookupChoiceFieldType("la", "MultipleAppLookupChoiceField", "Holds the value of a `multipleapplookup`/`choice` field of a record (and related information)");
3283
+
3284
+
3285
+ export class MultipleAppLookupChoiceField extends MultipleAppLookupField
3286
+ {
3287
+ [ul4.symbols.type]()
3288
+ {
3289
+ return multipleapplookupchoicefieldtype;
3290
+ }
3291
+ };
3292
+
3293
+
3294
+ class ControlType extends ul4.Type
3295
+ {
3296
+ instancecheck(obj)
3297
+ {
3298
+ return obj instanceof Control;
3299
+ }
3300
+ };
3301
+
3302
+ let controltype = new ControlType("la", "Control", "Metainformation about a field in a LivingApps application");
3303
+
3304
+
1337
3305
  export class Control extends Base
1338
3306
  {
3307
+ [ul4.symbols.type]()
3308
+ {
3309
+ return controltype;
3310
+ }
3311
+
1339
3312
  [ul4.symbols.repr]()
1340
3313
  {
1341
3314
  return "<" + this.constructor.name + " id=" + ul4._repr(this.id) + " identifier=" + ul4._repr(this.identifier) + ">";
@@ -1417,6 +3390,10 @@ export class Control extends Base
1417
3390
  get mode()
1418
3391
  {
1419
3392
  let view_control = this._view_control();
3393
+ if (this.app._active_view !== null && view_control === null)
3394
+ return null;
3395
+ if (this.app.globals.mode === null)
3396
+ return "display";
1420
3397
  return view_control !== null ? view_control.mode : "edit";
1421
3398
  }
1422
3399
 
@@ -1471,11 +3448,27 @@ Control.prototype.type = null;
1471
3448
  Control.prototype.subtype = null;
1472
3449
  Control.prototype._ul4onattrs = ["identifier", "fieldname", "app", "_label", "priority", "order", "ininsertprocedure", "inupdateprocedure"];
1473
3450
  Control.prototype._ul4attrs = new Set(["id", "identifier", "fieldname", "app", "priority", "order", "ininsertprocedure", "inupdateprocedure", "fulltype", "label", "top", "left", "width", "height", "liveupdate", "tabindex", "required", "mode", "labelpos", "autoalign", "in_active_view"]);
3451
+ Control.prototype._cssclass_root = "llft-control";
3452
+ Control.prototype._cssclass_control = "input";
3453
+
3454
+
3455
+ class BoolControlType extends ControlType
3456
+ {
3457
+ instancecheck(obj)
3458
+ {
3459
+ return obj instanceof BoolControl;
3460
+ }
3461
+ };
3462
+
3463
+ let boolcontroltype = new BoolControlType("la", "BoolControl", "A LivingApps boolean field (type 'bool')");
1474
3464
 
1475
3465
 
1476
3466
  export class BoolControl extends Control
1477
3467
  {
1478
- static classdoc = "A LivingApps boolean field (type 'bool')";
3468
+ [ul4.symbols.type]()
3469
+ {
3470
+ return boolcontroltype;
3471
+ }
1479
3472
 
1480
3473
  // ``search`` must by ``null``, ``false`` or ``true``
1481
3474
  search(value, search)
@@ -1492,9 +3485,23 @@ BoolControl.prototype.type = "bool";
1492
3485
  BoolControl.prototype.fieldtype = BoolField;
1493
3486
 
1494
3487
 
3488
+ class IntControlType extends ControlType
3489
+ {
3490
+ instancecheck(obj)
3491
+ {
3492
+ return obj instanceof IntControl;
3493
+ }
3494
+ };
3495
+
3496
+ let intcontroltype = new IntControlType("la", "IntControl", "A LivingApps integer field (type 'int')");
3497
+
3498
+
1495
3499
  export class IntControl extends Control
1496
3500
  {
1497
- static classdoc = "A LivingApps integer field (type 'int')";
3501
+ [ul4.symbols.type]()
3502
+ {
3503
+ return intcontroltype;
3504
+ }
1498
3505
 
1499
3506
  // ``search.value`` must by ``null`` or an integer
1500
3507
  search(value, search)
@@ -1511,9 +3518,23 @@ IntControl.prototype.type = "int";
1511
3518
  IntControl.prototype.fieldtype = IntField;
1512
3519
 
1513
3520
 
3521
+ class PlaceholderControlType extends ControlType
3522
+ {
3523
+ instancecheck(obj)
3524
+ {
3525
+ return obj instanceof PlaceholderControld;
3526
+ }
3527
+ };
3528
+
3529
+ let placeholdercontroltype = new PlaceholderControlType("la", "PlaceholderControl", "A LivingApps field that has a placeholder");
3530
+
3531
+
1514
3532
  class PlaceholderControl extends Control
1515
3533
  {
1516
- static classdoc = "A LivingApps multiplelookup field (type 'multiplelookup/select')";
3534
+ [ul4.symbols.type]()
3535
+ {
3536
+ return placeholdercontroltype;
3537
+ }
1517
3538
 
1518
3539
  get placeholder()
1519
3540
  {
@@ -1527,9 +3548,23 @@ class PlaceholderControl extends Control
1527
3548
  PlaceholderControl.prototype._ul4attrs = new Set([...Control.prototype._ul4attrs, "placeholder"]);
1528
3549
 
1529
3550
 
3551
+ class NumberControlType extends PlaceholderControlType
3552
+ {
3553
+ instancecheck(obj)
3554
+ {
3555
+ return obj instanceof NumberControl;
3556
+ }
3557
+ };
3558
+
3559
+ let numbercontroltype = new NumberControlType("la", "NumberControl", "A LivingApps number field (type 'number')");
3560
+
3561
+
1530
3562
  export class NumberControl extends PlaceholderControl
1531
3563
  {
1532
- static classdoc = "A LivingApps number field (type 'number')";
3564
+ [ul4.symbols.type]()
3565
+ {
3566
+ return numbercontroltype;
3567
+ }
1533
3568
 
1534
3569
  // ``search.value`` must by ``null`` or an integer
1535
3570
  search(value, search)
@@ -1550,10 +3585,28 @@ export class NumberControl extends PlaceholderControl
1550
3585
 
1551
3586
  NumberControl.prototype.type = "number";
1552
3587
  NumberControl.prototype.fieldtype = NumberField;
3588
+ NumberControl.prototype._ul4onattrs = [...Control.prototype._ul4onattrs, "precision", "minimum", "maximum"];
3589
+ NumberControl.prototype._ul4attrs = new Set([...Control.prototype._ul4attrs, "precision", "minimum", "maximum"]);
3590
+
3591
+
3592
+ class StringControlType extends PlaceholderControlType
3593
+ {
3594
+ instancecheck(obj)
3595
+ {
3596
+ return obj instanceof StringControl;
3597
+ }
3598
+ };
3599
+
3600
+ let stringcontroltype = new StringControlType("la", "StringControl", "A LivingApps number field (type 'string')");
1553
3601
 
1554
3602
 
1555
3603
  export class StringControl extends PlaceholderControl
1556
3604
  {
3605
+ [ul4.symbols.type]()
3606
+ {
3607
+ return stringcontroltype;
3608
+ }
3609
+
1557
3610
  _user_placeholder(user, placeholder)
1558
3611
  {
1559
3612
  if (placeholder === null)
@@ -1664,45 +3717,138 @@ export class StringControl extends PlaceholderControl
1664
3717
  StringControl.prototype.type = "string";
1665
3718
 
1666
3719
 
3720
+ class TextControlType extends StringControlType
3721
+ {
3722
+ instancecheck(obj)
3723
+ {
3724
+ return obj instanceof TextControl;
3725
+ }
3726
+ };
3727
+
3728
+ let textcontroltype = new TextControlType("la", "TextControl", "A LivingApps text field (type 'string/text')");
3729
+
3730
+
1667
3731
  export class TextControl extends StringControl
1668
3732
  {
1669
- static classdoc = "A LivingApps text field (type 'string/text')";
3733
+ [ul4.symbols.type]()
3734
+ {
3735
+ return textcontroltype;
3736
+ }
1670
3737
  };
1671
3738
 
1672
3739
  TextControl.prototype.subtype = "text";
1673
3740
  TextControl.prototype.fieldtype = StringField;
1674
3741
 
1675
3742
 
3743
+ class PasswordControlType extends StringControlType
3744
+ {
3745
+ instancecheck(obj)
3746
+ {
3747
+ return obj instanceof PasswordControl;
3748
+ }
3749
+ };
3750
+
3751
+ let passwordcontroltype = new PasswordControlType("la", "PasswordControl", "A LivingApps password field (type 'string/password')");
3752
+
3753
+
3754
+ export class PasswordControl extends StringControl
3755
+ {
3756
+ [ul4.symbols.type]()
3757
+ {
3758
+ return passwordcontroltype;
3759
+ }
3760
+ };
3761
+
3762
+ PasswordControl.prototype.subtype = "password";
3763
+ PasswordControl.prototype.fieldtype = PasswordField;
3764
+
3765
+
3766
+ class EmailControlType extends StringControlType
3767
+ {
3768
+ instancecheck(obj)
3769
+ {
3770
+ return obj instanceof EmailControl;
3771
+ }
3772
+ };
3773
+
3774
+ let emailcontroltype = new EmailControlType("la", "EmailControl", "A LivingApps email field (type 'string/email')");
3775
+
3776
+
1676
3777
  export class EmailControl extends StringControl
1677
3778
  {
1678
- static classdoc = "A LivingApps email field (type 'string/email')";
3779
+ [ul4.symbols.type]()
3780
+ {
3781
+ return emailcontroltype;
3782
+ }
1679
3783
  };
1680
3784
 
1681
3785
  EmailControl.prototype.subtype = "email";
1682
3786
  EmailControl.prototype.fieldtype = EmailField;
1683
3787
 
1684
3788
 
3789
+ class URLControlType extends StringControlType
3790
+ {
3791
+ instancecheck(obj)
3792
+ {
3793
+ return obj instanceof URLControl;
3794
+ }
3795
+ };
3796
+
3797
+ let urlcontroltype = new URLControlType("la", "URLControl", "A LivingApps URL field (type 'string/url')");
3798
+
3799
+
1685
3800
  export class URLControl extends StringControl
1686
3801
  {
1687
- static classdoc = "A LivingApps URL field (type 'string/url')";
3802
+ [ul4.symbols.type]()
3803
+ {
3804
+ return urlcontroltype;
3805
+ }
1688
3806
  };
1689
3807
 
1690
3808
  URLControl.prototype.subtype = "url";
1691
3809
  URLControl.prototype.fieldtype = URLField;
1692
3810
 
1693
3811
 
3812
+ class TelControlType extends StringControlType
3813
+ {
3814
+ instancecheck(obj)
3815
+ {
3816
+ return obj instanceof TelControl;
3817
+ }
3818
+ };
3819
+
3820
+ let telcontroltype = new TelControlType("la", "TelControl", "A LivingApps phone number field (type 'string/tel')");
3821
+
3822
+
1694
3823
  export class TelControl extends StringControl
1695
3824
  {
1696
- static classdoc = "A LivingApps phone number field (type 'string/tel')";
3825
+ [ul4.symbols.type]()
3826
+ {
3827
+ return telcontroltype;
3828
+ }
1697
3829
  };
1698
3830
 
1699
3831
  TelControl.prototype.subtype = "tel";
1700
3832
  TelControl.prototype.fieldtype = TelField;
1701
3833
 
1702
3834
 
3835
+ class TextAreaControlType extends StringControlType
3836
+ {
3837
+ instancecheck(obj)
3838
+ {
3839
+ return obj instanceof TextAreaControl;
3840
+ }
3841
+ };
3842
+
3843
+ let textareacontroltype = new TextAreaControlType("la", "TextAreaControl", "A LivingApps textarea field (type 'string/textarea')");
3844
+
3845
+
1703
3846
  export class TextAreaControl extends StringControl
1704
3847
  {
1705
- static classdoc = "A LivingApps textarea field (type 'string/textarea')";
3848
+ [ul4.symbols.type]()
3849
+ {
3850
+ return textareacontroltype;
3851
+ }
1706
3852
 
1707
3853
  get maxlength()
1708
3854
  {
@@ -1724,20 +3870,49 @@ TextAreaControl.prototype.subtype = "textarea";
1724
3870
  TextAreaControl.prototype.fieldtype = TextAreaField;
1725
3871
  TextAreaControl.prototype._ul4onattrs = [...StringControl.prototype._ul4onattrs, "encrypted"];
1726
3872
  TextAreaControl.prototype._ul4attrs = new Set([...StringControl.prototype._ul4attrs, "encrypted"]);
3873
+ TextAreaControl.prototype._cssclass_control = "textarea";
3874
+
3875
+
3876
+ class HTMLControlType extends StringControlType
3877
+ {
3878
+ instancecheck(obj)
3879
+ {
3880
+ return obj instanceof HTMLControl;
3881
+ }
3882
+ };
3883
+
3884
+ let htmlcontroltype = new HTMLControlType("la", "HTMLControl", "A LivingApps HTML field (type 'string/html')");
1727
3885
 
1728
3886
 
1729
3887
  export class HTMLControl extends StringControl
1730
3888
  {
1731
- static classdoc = "A LivingApps HTML field (type 'string/html')";
3889
+ [ul4.symbols.type]()
3890
+ {
3891
+ return htmlcontroltype;
3892
+ }
1732
3893
  };
1733
3894
 
1734
3895
  HTMLControl.prototype.subtype = "html";
1735
3896
  HTMLControl.prototype.fieldtype = HTMLField;
1736
3897
 
1737
3898
 
3899
+ class DateControlType extends PlaceholderControlType
3900
+ {
3901
+ instancecheck(obj)
3902
+ {
3903
+ return obj instanceof DateControl;
3904
+ }
3905
+ };
3906
+
3907
+ let datecontroltype = new DateControlType("la", "DateControl", "A LivingApps date field (type 'date/date')");
3908
+
3909
+
1738
3910
  export class DateControl extends PlaceholderControl
1739
3911
  {
1740
- static classdoc = "A LivingApps date field (type 'date/date')";
3912
+ [ul4.symbols.type]()
3913
+ {
3914
+ return datecontroltype;
3915
+ }
1741
3916
 
1742
3917
  get default()
1743
3918
  {
@@ -1749,14 +3924,25 @@ export class DateControl extends PlaceholderControl
1749
3924
  return view_control.default === "{today}" ? ul4.today() : null;
1750
3925
  }
1751
3926
 
1752
- formatstring(language)
3927
+ formatstring(lang)
1753
3928
  {
1754
- language = language || this.app.language;
3929
+ lang = lang || this.globals.lang;
1755
3930
 
1756
- if (language === "de")
1757
- return "%d.%m.%Y";
1758
- else
1759
- return "%m/%d/%Y";
3931
+ if (lang !== "de" && lang !== "fr" && lang !== "it")
3932
+ lang = "en";
3933
+ return this._formatstrings[lang];
3934
+ }
3935
+
3936
+ formatstrings_parse(lang)
3937
+ {
3938
+ lang = lang || this.globals.lang;
3939
+ if (lang !== "de" && lang !== "fr" && lang !== "it")
3940
+ lang = "en";
3941
+
3942
+ return [
3943
+ ...this._formatstrings_parse[lang],
3944
+ ...this._formatstrings_parse["intl"]
3945
+ ];
1760
3946
  }
1761
3947
 
1762
3948
  // searchvalue must be ``null``, a ``Date`` object or a string
@@ -1787,11 +3973,62 @@ export class DateControl extends PlaceholderControl
1787
3973
  DateControl.prototype.type = "date";
1788
3974
  DateControl.prototype.subtype = "date";
1789
3975
  DateControl.prototype.fieldtype = DateField;
3976
+ DateControl.prototype._formatstrings = {
3977
+ "de": "%d.%m.%Y",
3978
+ "fr": "%d.%m.%Y",
3979
+ "it": "%d.%m.%Y",
3980
+ "en": "%m/%d/%Y",
3981
+ "intl": "%Y-%m-%d"
3982
+ };
3983
+
3984
+ let _suffixes = [
3985
+ "",
3986
+ " %H:%M",
3987
+ "T%H:%M",
3988
+ " %H:%M:%S",
3989
+ "T%H:%M:%S",
3990
+ " %H:%M:%S.%f",
3991
+ "T%H:%M:%S.%f",
3992
+ " %H:%M%z",
3993
+ "T%H:%M%z",
3994
+ " %H:%M:%S%z",
3995
+ "T%H:%M:%S%z",
3996
+ " %H:%M:%S.%f%z",
3997
+ "T%H:%M:%S.%f%z",
3998
+ " %H:%M %z",
3999
+ "T%H:%M %z",
4000
+ " %H:%M:%S %z",
4001
+ "T%H:%M:%S %z",
4002
+ " %H:%M:%S.%f %z",
4003
+ "T%H:%M:%S.%f %z"
4004
+ ]
4005
+
4006
+ DateControl.prototype._formatstrings_parse = {
4007
+ "en": _suffixes.map(s => "%m/%d/%Y" + s),
4008
+ "de": _suffixes.map(s => "%d.%m.%Y" + s),
4009
+ "fr": _suffixes.map(s => "%d.%m.%Y" + s),
4010
+ "it": _suffixes.map(s => "%d.%m.%Y" + s),
4011
+ "intl": _suffixes.map(s => "%Y-%m-%d" + s)
4012
+ };
4013
+
4014
+
4015
+ class DatetimeMinuteControlType extends DateControlType
4016
+ {
4017
+ instancecheck(obj)
4018
+ {
4019
+ return obj instanceof DatetimeMinuteControl;
4020
+ }
4021
+ };
4022
+
4023
+ let datetimeminutecontroltype = new DatetimeMinuteControlType("la", "DatetimeMinuteControl", "A LivingApps date field (type 'date/datetimeminute')");
1790
4024
 
1791
4025
 
1792
4026
  export class DatetimeMinuteControl extends DateControl
1793
4027
  {
1794
- static classdoc = "A LivingApps date field (type 'date/datetimeminute')";
4028
+ [ul4.symbols.type]()
4029
+ {
4030
+ return datetimeminutecontroltype;
4031
+ }
1795
4032
 
1796
4033
  get default()
1797
4034
  {
@@ -1810,25 +4047,36 @@ export class DatetimeMinuteControl extends DateControl
1810
4047
  else
1811
4048
  return null;
1812
4049
  }
4050
+ };
1813
4051
 
1814
- formatstring(language)
1815
- {
1816
- language = language || this.app.language;
4052
+ DatetimeMinuteControl.prototype.subtype = "datetimeminute";
4053
+ DatetimeMinuteControl.prototype.fieldtype = DatetimeMinuteField;
4054
+ DatetimeMinuteControl.prototype._formatstrings = {
4055
+ "de": "%d.%m.%Y %H:%M",
4056
+ "fr": "%d.%m.%Y %H:%M",
4057
+ "it": "%d.%m.%Y %H:%M",
4058
+ "en": "%m/%d/%Y %H:%M",
4059
+ "intl": "%Y-%m-%d %H:%M"
4060
+ };
1817
4061
 
1818
- if (language === "de")
1819
- return "%d.%m.%Y %H:%M";
1820
- else
1821
- return "%m/%d/%Y %H:%M";
4062
+
4063
+ class DatetimeSecondControlType extends DateControlType
4064
+ {
4065
+ instancecheck(obj)
4066
+ {
4067
+ return obj instanceof DatetimeSecondControl;
1822
4068
  }
1823
4069
  };
1824
4070
 
1825
- DatetimeMinuteControl.prototype.subtype = "datetimeminute";
1826
- DatetimeMinuteControl.prototype.fieldtype = DatetimeMinuteField;
4071
+ let datetimesecondcontroltype = new DatetimeSecondControlType("la", "DatetimeSecondControl", "A LivingApps date field (type 'date/datetimesecond')");
1827
4072
 
1828
4073
 
1829
4074
  export class DatetimeSecondControl extends DateControl
1830
4075
  {
1831
- static classdoc = "A LivingApps date field (type 'date/datetimesecond')";
4076
+ [ul4.symbols.type]()
4077
+ {
4078
+ return datetimesecondcontroltype;
4079
+ }
1832
4080
 
1833
4081
  get default()
1834
4082
  {
@@ -1846,24 +4094,37 @@ export class DatetimeSecondControl extends DateControl
1846
4094
  else
1847
4095
  return null;
1848
4096
  }
4097
+ };
1849
4098
 
1850
- formatstring(language)
1851
- {
1852
- language = language || this.app.language;
4099
+ DatetimeSecondControl.prototype.subtype = "datetimesecond";
4100
+ DatetimeSecondControl.prototype.fieldtype = DatetimeSecondField;
4101
+ DatetimeSecondControl.prototype._formatstrings = {
4102
+ "de": "%d.%m.%Y %H:%M:%S",
4103
+ "fr": "%d.%m.%Y %H:%M:%S",
4104
+ "it": "%d.%m.%Y %H:%M:%S",
4105
+ "en": "%m/%d/%Y %H:%M:%S",
4106
+ "intl": "%Y-%m-%d %H:%M:%S"
4107
+ };
1853
4108
 
1854
- if (language === "de")
1855
- return "%d.%m.%Y %H:%M:%S";
1856
- else
1857
- return "%m/%d/%Y %H:%M:%S";
4109
+
4110
+ class LookupControlType extends ControlType
4111
+ {
4112
+ instancecheck(obj)
4113
+ {
4114
+ return obj instanceof LookupControl;
1858
4115
  }
1859
4116
  };
1860
4117
 
1861
- DatetimeSecondControl.prototype.subtype = "datetimesecond";
1862
- DatetimeSecondControl.prototype.fieldtype = DatetimeSecondField;
4118
+ let lookupcontroltype = new LookupControlType("la", "LookupControl", "A LivingApps date field (type 'lookup')");
1863
4119
 
1864
4120
 
1865
4121
  export class LookupControl extends Control
1866
4122
  {
4123
+ [ul4.symbols.type]()
4124
+ {
4125
+ return lookupcontroltype;
4126
+ }
4127
+
1867
4128
  get default()
1868
4129
  {
1869
4130
  let view_control = this._view_control();
@@ -1919,35 +4180,119 @@ LookupControl.prototype._ul4onattrs = [...Control.prototype._ul4onattrs, "lookup
1919
4180
  LookupControl.prototype._ul4attrs = new Set([...Control.prototype._ul4attrs, "lookupdata"]);
1920
4181
 
1921
4182
 
1922
- export class LookupSelectControl extends LookupControl
4183
+ class LookupSelectControlType extends LookupControlType
1923
4184
  {
1924
- static classdoc = "A LivingApps lookup field (type 'lookup/select')";
4185
+ instancecheck(obj)
4186
+ {
4187
+ return obj instanceof LookupSelectControl;
4188
+ }
4189
+ };
4190
+
4191
+ let lookupselectcontroltype = new LookupSelectControlType("la", "LookupSelectControl", "A LivingApps lookup field (type 'lookup/select')");
1925
4192
 
4193
+
4194
+ export class LookupSelectControl extends LookupControl
4195
+ {
4196
+ [ul4.symbols.type]()
4197
+ {
4198
+ return lookupselectcontroltype;
4199
+ }
1926
4200
  };
1927
4201
 
1928
4202
  LookupSelectControl.prototype.subtype = "select";
4203
+ LookupSelectControl.prototype.fieldtype = LookupSelectField;
4204
+ LookupSelectControl.prototype._cssclass_control = "select";
1929
4205
 
1930
4206
 
1931
- export class LookupRadioControl extends LookupControl
4207
+ class LookupRadioControlType extends LookupControlType
1932
4208
  {
1933
- static classdoc = "A LivingApps lookup field (type 'lookup/radio')";
4209
+ instancecheck(obj)
4210
+ {
4211
+ return obj instanceof LookupRadioControl;
4212
+ }
4213
+ };
4214
+
4215
+ let lookupradiocontroltype = new LookupRadioControlType("la", "LookupRadioControl", "A LivingApps lookup field (type 'lookup/radio')");
1934
4216
 
4217
+
4218
+ export class LookupRadioControl extends LookupControl
4219
+ {
4220
+ [ul4.symbols.type]()
4221
+ {
4222
+ return lookupradiocontroltype;
4223
+ }
1935
4224
  };
1936
4225
 
1937
4226
  LookupRadioControl.prototype.subtype = "radio";
4227
+ LookupRadioControl.prototype.fieldtype = LookupRadioField;
4228
+ LookupRadioControl.prototype._cssclass_root = "llft-element";
1938
4229
 
1939
4230
 
1940
- export class LookupChoiceControl extends LookupControl
4231
+ class LookupChoiceControlType extends LookupControlType
1941
4232
  {
1942
- static classdoc = "A LivingApps lookup field (type 'lookup/choice')";
4233
+ instancecheck(obj)
4234
+ {
4235
+ return obj instanceof LookupChoiceControl;
4236
+ }
4237
+ };
4238
+
4239
+ let lookupchoicecontroltype = new LookupChoiceControlType("la", "LookupChoiceControl", "A LivingApps lookup field (type 'lookup/choice')");
1943
4240
 
4241
+
4242
+ export class LookupChoiceControl extends LookupControl
4243
+ {
4244
+ [ul4.symbols.type]()
4245
+ {
4246
+ return lookupchoicecontroltype;
4247
+ }
1944
4248
  };
1945
4249
 
1946
4250
  LookupChoiceControl.prototype.subtype = "choice";
4251
+ LookupChoiceControl.prototype.fieldtype = LookupChoiceField;
4252
+
4253
+
4254
+ class AppLookupControlType extends ControlType
4255
+ {
4256
+ instancecheck(obj)
4257
+ {
4258
+ return obj instanceof AppLookupControl;
4259
+ }
4260
+ };
4261
+
4262
+ let applookupcontroltype = new AppLookupControlType("la", "AppLookupControl", "A LivingApps lookup field (type 'applookup')");
4263
+
4264
+
4265
+ export class AppLookupControl extends Control
4266
+ {
4267
+ [ul4.symbols.type]()
4268
+ {
4269
+ return applookupcontroltype;
4270
+ }
4271
+
4272
+ get lookupdata()
4273
+ {
4274
+ if (this.lookup_app !== null && this.lookup_app.records !== null)
4275
+ return this.lookup_app.records;
4276
+ else
4277
+ return new Map();
4278
+ }
4279
+
4280
+ get nonekey()
4281
+ {
4282
+ let view_control = this._view_control();
4283
+ if (view_control === null)
4284
+ return null;
4285
+ return view_control.lookupnonekey;
4286
+ }
1947
4287
 
4288
+ get nonelabel()
4289
+ {
4290
+ let view_control = this._view_control();
4291
+ if (view_control === null)
4292
+ return null;
4293
+ return view_control.lookupnonelabel;
4294
+ }
1948
4295
 
1949
- export class AppLookupControl extends Control
1950
- {
1951
4296
  // ``search.value`` must be an object containing the search criteria for the referenced record
1952
4297
  search(value, search)
1953
4298
  {
@@ -1964,35 +4309,94 @@ AppLookupControl.prototype._ul4onattrs = [...Control.prototype._ul4onattrs, "loo
1964
4309
  AppLookupControl.prototype._ul4attrs = new Set([...Control.prototype._ul4attrs, "lookup_app", "lookup_controls", "local_master_control", "local_detail_controls", "remote_master_control"]);
1965
4310
 
1966
4311
 
1967
- export class AppLookupSelectControl extends AppLookupControl
4312
+ class AppLookupSelectControlType extends AppLookupControlType
1968
4313
  {
1969
- static classdoc = "A LivingApps applookup field (type 'applookup/select')";
4314
+ instancecheck(obj)
4315
+ {
4316
+ return obj instanceof AppLookupSelectControl;
4317
+ }
4318
+ };
4319
+
4320
+ let applookupselectcontroltype = new AppLookupSelectControlType("la", "AppLookupSelectControl", "A LivingApps applookup field (type 'applookup/select')");
1970
4321
 
4322
+
4323
+ export class AppLookupSelectControl extends AppLookupControl
4324
+ {
4325
+ [ul4.symbols.type]()
4326
+ {
4327
+ return applookupselectcontroltype;
4328
+ }
1971
4329
  };
1972
4330
 
1973
4331
  AppLookupSelectControl.prototype.subtype = "select";
4332
+ AppLookupSelectControl.prototype.fieldtype = AppLookupSelectField;
4333
+ AppLookupSelectControl.prototype._cssclass_control = "select";
1974
4334
 
1975
4335
 
1976
- export class AppLookupRadioControl extends AppLookupControl
4336
+ class AppLookupRadioControlType extends AppLookupControlType
1977
4337
  {
1978
- static classdoc = "A LivingApps applookup field (type 'applookup/radio')";
4338
+ instancecheck(obj)
4339
+ {
4340
+ return obj instanceof AppLookupRadioControl;
4341
+ }
4342
+ };
4343
+
4344
+ let applookupradiocontroltype = new AppLookupRadioControlType("la", "AppLookupRadioControl", "A LivingApps applookup field (type 'applookup/radio')");
1979
4345
 
4346
+
4347
+ export class AppLookupRadioControl extends AppLookupControl
4348
+ {
4349
+ [ul4.symbols.type]()
4350
+ {
4351
+ return applookupradiocontroltype;
4352
+ }
1980
4353
  };
1981
4354
 
1982
4355
  AppLookupRadioControl.prototype.subtype = "radio";
4356
+ AppLookupRadioControl.prototype.fieldtype = AppLookupRadioField;
1983
4357
 
1984
4358
 
1985
- export class AppLookupChoiceControl extends AppLookupControl
4359
+ class AppLookupChoiceControlType extends AppLookupControlType
1986
4360
  {
1987
- static classdoc = "A LivingApps applookup field (type 'applookup/choice')";
4361
+ instancecheck(obj)
4362
+ {
4363
+ return obj instanceof AppLookupChoiceControl;
4364
+ }
4365
+ };
4366
+
4367
+ let applookupchoicecontroltype = new AppLookupChoiceControlType("la", "AppLookupChoiceControl", "A LivingApps applookup field (type 'applookup/choice')");
1988
4368
 
4369
+
4370
+ export class AppLookupChoiceControl extends AppLookupControl
4371
+ {
4372
+ [ul4.symbols.type]()
4373
+ {
4374
+ return applookupchoicecontroltype;
4375
+ }
1989
4376
  };
1990
4377
 
1991
4378
  AppLookupChoiceControl.prototype.subtype = "choice";
4379
+ AppLookupChoiceControl.prototype.fieldtype = AppLookupChoiceField;
4380
+
4381
+
4382
+ class MultipleLookupControlType extends LookupControlType
4383
+ {
4384
+ instancecheck(obj)
4385
+ {
4386
+ return obj instanceof MultipleLookupControl;
4387
+ }
4388
+ };
4389
+
4390
+ let multiplelookupcontroltype = new MultipleLookupControlType("la", "MultipleLookupControl", "A LivingApps multiple applookup field (type 'multipleapplookup')");
1992
4391
 
1993
4392
 
1994
4393
  export class MultipleLookupControl extends LookupControl
1995
4394
  {
4395
+ [ul4.symbols.type]()
4396
+ {
4397
+ return multiplelookupcontroltype;
4398
+ }
4399
+
1996
4400
  get default()
1997
4401
  {
1998
4402
  let view_control = this._view_control();
@@ -2022,39 +4426,104 @@ export class MultipleLookupControl extends LookupControl
2022
4426
  }
2023
4427
  };
2024
4428
 
2025
- MultipleLookupControl.prototype.subtype = "multiplelookup";
4429
+ MultipleLookupControl.prototype.type = "multiplelookup";
2026
4430
  MultipleLookupControl.prototype.fieldtype = MultipleLookupField;
2027
4431
 
2028
4432
 
2029
- export class MultipleLookupSelectControl extends MultipleLookupControl
4433
+ class MultipleLookupCheckboxControlType extends MultipleLookupControlType
2030
4434
  {
2031
- static classdoc = "A LivingApps multiplelookup field (type 'multiplelookup/select')";
2032
-
4435
+ instancecheck(obj)
4436
+ {
4437
+ return obj instanceof MultipleLookupCheckboxControl;
4438
+ }
2033
4439
  };
2034
4440
 
2035
- MultipleLookupSelectControl.prototype.subtype = "select";
4441
+ let multiplelookupcheckboxcontroltype = new MultipleLookupCheckboxControlType("la", "MultipleLookupCheckboxControl", "A LivingApps multiplelookup field (type 'multiplelookup/checkbox')");
2036
4442
 
2037
4443
 
2038
4444
  export class MultipleLookupCheckboxControl extends MultipleLookupControl
2039
4445
  {
2040
- static classdoc = "A LivingApps multiplelookup field (type 'multiplelookup/checkbox')";
4446
+ [ul4.symbols.type]()
4447
+ {
4448
+ return multiplelookupcheckboxcontroltype;
4449
+ }
2041
4450
 
4451
+ get _sel_label()
4452
+ {
4453
+ return this._sel_root + " label:not([for]) > span";
4454
+ }
2042
4455
  };
2043
4456
 
2044
4457
  MultipleLookupCheckboxControl.prototype.subtype = "checkbox";
4458
+ MultipleLookupCheckboxControl.prototype.fieldtype = MultipleLookupCheckboxField;
4459
+ MultipleLookupCheckboxControl.prototype._cssclass_root = "llft-element";
2045
4460
 
2046
4461
 
2047
- export class MultipleLookupChoiceControl extends MultipleLookupControl
4462
+ class MultipleLookupSelectControlType extends MultipleLookupControlType
4463
+ {
4464
+ instancecheck(obj)
4465
+ {
4466
+ return obj instanceof MultipleLookupSelectControl;
4467
+ }
4468
+ };
4469
+
4470
+ let multiplelookupselectcontroltype = new MultipleLookupSelectControlType("la", "MultipleLookupSelectControl", "A LivingApps multiplelookup field (type 'multiplelookup/select')");
4471
+
4472
+
4473
+ export class MultipleLookupSelectControl extends MultipleLookupControl
4474
+ {
4475
+ [ul4.symbols.type]()
4476
+ {
4477
+ return multiplelookupselectcontroltype;
4478
+ }
4479
+ };
4480
+
4481
+ MultipleLookupSelectControl.prototype.subtype = "select";
4482
+ MultipleLookupSelectControl.prototype.fieldtype = MultipleLookupSelectField;
4483
+ MultipleLookupSelectControl.prototype._cssclass_control = "select";
4484
+
4485
+
4486
+ class MultipleLookupChoiceControlType extends MultipleLookupControlType
2048
4487
  {
2049
- static classdoc = "A LivingApps multiplelookup field (type 'multiplelookup/choice')";
4488
+ instancecheck(obj)
4489
+ {
4490
+ return obj instanceof MultipleLookupChoiceControl;
4491
+ }
4492
+ };
4493
+
4494
+ let multiplelookupchoicecontroltype = new MultipleLookupChoiceControlType("la", "MultipleLookupChoiceControl", "A LivingApps multiplelookup field (type 'multiplelookup/choice')");
4495
+
2050
4496
 
4497
+ export class MultipleLookupChoiceControl extends MultipleLookupControl
4498
+ {
4499
+ [ul4.symbols.type]()
4500
+ {
4501
+ return multiplelookupchoicecontroltype;
4502
+ }
2051
4503
  };
2052
4504
 
2053
4505
  MultipleLookupChoiceControl.prototype.subtype = "choice";
4506
+ MultipleLookupChoiceControl.prototype.fieldtype = MultipleLookupChoiceField;
4507
+
4508
+
4509
+ class MultipleAppLookupControlType extends AppLookupControlType
4510
+ {
4511
+ instancecheck(obj)
4512
+ {
4513
+ return obj instanceof MultipleAppLookupControl;
4514
+ }
4515
+ };
4516
+
4517
+ let multipleapplookupcontroltype = new MultipleAppLookupControlType("la", "MultipleAppLookupControl", "A LivingApps multiple applookup field (type 'multipleapplookup')");
2054
4518
 
2055
4519
 
2056
4520
  export class MultipleAppLookupControl extends AppLookupControl
2057
4521
  {
4522
+ [ul4.symbols.type]()
4523
+ {
4524
+ return multipleapplookupcontroltype;
4525
+ }
4526
+
2058
4527
  // ``search.value`` must be an object containing the search criteria for the referenced record
2059
4528
  search(value, search)
2060
4529
  {
@@ -2081,69 +4550,186 @@ MultipleAppLookupControl.prototype.type = "multipleapplookup";
2081
4550
  MultipleAppLookupControl.prototype.fieldtype = MultipleAppLookupField;
2082
4551
 
2083
4552
 
2084
- export class MultipleAppLookupSelectControl extends MultipleAppLookupControl
4553
+ class MultipleAppLookupSelectControlType extends MultipleAppLookupControlType
2085
4554
  {
2086
- static classdoc = "A LivingApps multiple applookup field (type 'multipleapplookup/select')";
4555
+ instancecheck(obj)
4556
+ {
4557
+ return obj instanceof MultipleAppLookupSelectControl;
4558
+ }
4559
+ };
4560
+
4561
+ let multipleapplookupselectcontroltype = new MultipleAppLookupSelectControlType("la", "MultipleAppLookupSelectControl", "A LivingApps multiple applookup field (type 'multipleapplookup/select')");
4562
+
2087
4563
 
4564
+ export class MultipleAppLookupSelectControl extends MultipleAppLookupControl
4565
+ {
4566
+ [ul4.symbols.type]()
4567
+ {
4568
+ return multipleapplookupselectcontroltype;
4569
+ }
2088
4570
  };
2089
4571
 
2090
4572
  MultipleAppLookupSelectControl.prototype.subtype = "select";
4573
+ MultipleAppLookupSelectControl.prototype.fieldtype = MultipleAppLookupSelectField;
4574
+ MultipleAppLookupSelectControl.prototype._cssclass_control = "select";
2091
4575
 
2092
4576
 
2093
- export class MultipleAppLookupCheckboxControl extends MultipleAppLookupControl
4577
+ class MultipleAppLookupCheckboxControlType extends MultipleAppLookupControlType
2094
4578
  {
2095
- static classdoc = "A LivingApps multiple applookup field (type 'multipleapplookup/checkbox')";
4579
+ instancecheck(obj)
4580
+ {
4581
+ return obj instanceof MultipleAppLookupCheckboxControl;
4582
+ }
4583
+ };
2096
4584
 
4585
+ let multipleapplookupcheckboxcontroltype = new MultipleAppLookupCheckboxControlType("la", "MultipleAppLookupCheckboxControl", "A LivingApps multiple applookup field (type 'multipleapplookup/checkbox')");
4586
+
4587
+
4588
+ export class MultipleAppLookupCheckboxControl extends MultipleAppLookupControl
4589
+ {
4590
+ [ul4.symbols.type]()
4591
+ {
4592
+ return multipleapplookupcheckboxcontroltype;
4593
+ }
2097
4594
  };
2098
4595
 
2099
4596
  MultipleAppLookupCheckboxControl.prototype.subtype = "checkbox";
4597
+ MultipleAppLookupCheckboxControl.prototype.fieldtype = MultipleAppLookupCheckboxField;
4598
+
4599
+
4600
+ class MultipleAppLookupChoiceControlType extends MultipleAppLookupControlType
4601
+ {
4602
+ instancecheck(obj)
4603
+ {
4604
+ return obj instanceof MultipleAppLookupChoiceControl;
4605
+ }
4606
+ };
4607
+
4608
+ let multipleapplookupchoicecontroltype = new MultipleAppLookupChoiceControlType("la", "MultipleAppLookupChoiceControl", "A LivingApps multiple applookup field (type 'multipleapplookup/choice')");
2100
4609
 
2101
4610
 
2102
4611
  export class MultipleAppLookupChoiceControl extends MultipleAppLookupControl
2103
4612
  {
2104
- static classdoc = "A LivingApps multiple applookup field (type 'multipleapplookup/choice')";
4613
+ [ul4.symbols.type]()
4614
+ {
4615
+ return multipleapplookupchoicecontroltype;
4616
+ }
2105
4617
  };
2106
4618
 
2107
4619
  MultipleAppLookupChoiceControl.prototype.subtype = "choice";
4620
+ MultipleAppLookupChoiceControl.prototype.fieldtype = MultipleAppLookupChoiceField;
4621
+
4622
+
4623
+ class GeoControlType extends ControlType
4624
+ {
4625
+ instancecheck(obj)
4626
+ {
4627
+ return obj instanceof GeoControl;
4628
+ }
4629
+ };
4630
+
4631
+ let geocontroltype = new GeoControlType("la", "GeoControl", "A LivingApps geo field (type 'geo')");
2108
4632
 
2109
4633
 
2110
4634
  export class GeoControl extends Control
2111
4635
  {
2112
- static classdoc = "A LivingApps geo field (type 'geo')";
4636
+ [ul4.symbols.type]()
4637
+ {
4638
+ return geocontroltype;
4639
+ }
2113
4640
  };
2114
4641
 
2115
4642
  GeoControl.prototype.type = "geo";
2116
4643
  GeoControl.prototype.fieldtype = GeoField;
4644
+ GeoControl.prototype._cssclass_root = "llft-element";
4645
+
4646
+
4647
+ class FileControlType extends ControlType
4648
+ {
4649
+ instancecheck(obj)
4650
+ {
4651
+ return obj instanceof FileControl;
4652
+ }
4653
+ };
4654
+
4655
+ let filecontroltype = new FileControlType("la", "FileControl", "A LivingApps upload field (type 'file')");
2117
4656
 
2118
4657
 
2119
4658
  export class FileControl extends Control
2120
4659
  {
2121
- static classdoc = "A LivingApps upload field (type 'file')";
4660
+ [ul4.symbols.type]()
4661
+ {
4662
+ return filecontroltype;
4663
+ }
2122
4664
  };
2123
4665
 
2124
4666
  FileControl.prototype.type = "file";
2125
4667
  FileControl.prototype.fieldtype = FileField;
4668
+ FileControl.prototype._cssclass_root = "llft-element";
4669
+
4670
+
4671
+ class FileSignatureControlType extends FileControlType
4672
+ {
4673
+ instancecheck(obj)
4674
+ {
4675
+ return obj instanceof FileSignatureControl;
4676
+ }
4677
+ };
4678
+
4679
+ let filesignaturecontroltype = new FileSignatureControlType("la", "FileSignatureControl", "A LivingApps signature image field (type 'file/signature')");
2126
4680
 
2127
4681
 
2128
4682
  export class FileSignatureControl extends FileControl
2129
4683
  {
2130
- static classdoc = "A LivingApps signature image field (type 'file/signature')";
4684
+ [ul4.symbols.type]()
4685
+ {
4686
+ return filesignaturecontroltype;
4687
+ }
2131
4688
  };
2132
4689
 
2133
4690
  FileSignatureControl.prototype.subtype = "signature";
2134
4691
  FileSignatureControl.prototype.fieldtype = FileSignatureField;
2135
4692
 
2136
4693
 
4694
+ class ButtonControlType extends ControlType
4695
+ {
4696
+ instancecheck(obj)
4697
+ {
4698
+ return obj instanceof ButtonControl;
4699
+ }
4700
+ };
4701
+
4702
+ let buttoncontroltype = new ButtonControlType("la", "ButtonControl", "A submit button");
4703
+
4704
+
2137
4705
  export class ButtonControl extends Control
2138
4706
  {
4707
+ [ul4.symbols.type]()
4708
+ {
4709
+ return buttoncontroltype;
4710
+ }
2139
4711
  };
2140
4712
 
2141
4713
  ButtonControl.prototype.type = "button";
2142
4714
 
2143
4715
 
4716
+ class LookupItemType extends ul4.Type
4717
+ {
4718
+ instancecheck(obj)
4719
+ {
4720
+ return obj instanceof LookupItem;
4721
+ }
4722
+ };
4723
+
4724
+ let lookupitemtype = new LookupItemType("la", "LookupItem", "An option in a lookup control/field");
4725
+
4726
+
2144
4727
  export class LookupItem extends Base
2145
4728
  {
2146
- static classdoc = "An option in a lookup control/field";
4729
+ [ul4.symbols.type]()
4730
+ {
4731
+ return lookupitemtype;
4732
+ }
2147
4733
 
2148
4734
  get label()
2149
4735
  {
@@ -2185,71 +4771,201 @@ export class LookupItem extends Base
2185
4771
  return null;
2186
4772
  }
2187
4773
 
2188
- [ul4.symbols.repr]()
4774
+ [ul4.symbols.repr]()
4775
+ {
4776
+ let repr = "<LookupItem key=" + ul4._repr(this.key) + " label=" + ul4._repr(this.label);
4777
+ if (!this.visible)
4778
+ repr += "visible=False"
4779
+ return repr + ">";
4780
+ }
4781
+ };
4782
+
4783
+ LookupItem.prototype._ul4onattrs = ["control", "key", "_label"];
4784
+ LookupItem.prototype._ul4attrs = new Set(["id", "control", "key", "label"]);
4785
+
4786
+
4787
+ class ViewLookupItemType extends ul4.Type
4788
+ {
4789
+ instancecheck(obj)
4790
+ {
4791
+ return obj instanceof ViewLookupItem;
4792
+ }
4793
+ };
4794
+
4795
+ let viewlookupitemtype = new ViewLookupItemType("la", "ViewLookupItem", "View specific information about a lookup item");
4796
+
4797
+
4798
+ export class ViewLookupItem extends Base
4799
+ {
4800
+ [ul4.symbols.type]()
4801
+ {
4802
+ return viewlookupitemtype;
4803
+ }
4804
+
4805
+ [ul4.symbols.repr]()
4806
+ {
4807
+ let repr = "<ViewLookupItem key=" + ul4._repr(this.key) + " label=" + ul4._repr(this.label);
4808
+ if (!this.visible)
4809
+ repr += " visible=False"
4810
+ return repr + ">";
4811
+ }
4812
+ };
4813
+
4814
+ ViewLookupItem.prototype._ul4onattrs = ["key", "label", "visible"];
4815
+ ViewLookupItem.prototype._ul4attrs = new Set(["key", "label", "visible"]);
4816
+
4817
+
4818
+ class LayoutControlType extends ul4.Type
4819
+ {
4820
+ instancecheck(obj)
4821
+ {
4822
+ return obj instanceof LayoutControl;
4823
+ }
4824
+ };
4825
+
4826
+ let layoutcontroltype = new LayoutControlType("la", "LayoutControl", "A decoration in an input form");
4827
+
4828
+
4829
+ export class LayoutControl extends Base
4830
+ {
4831
+ [ul4.symbols.type]()
4832
+ {
4833
+ return layoutcontroltype;
4834
+ }
4835
+
4836
+ [ul4.symbols.repr]()
4837
+ {
4838
+ return "<" + this.constructor.name + " id=" + ul4._repr(this.id) + " identifier=" + ul4._repr(this.identifier) + ">";
4839
+ }
4840
+
4841
+ get globals()
4842
+ {
4843
+ return this.view.app.globals;
4844
+ }
4845
+
4846
+ get _sel_root()
4847
+ {
4848
+ return "#livingapps-form .llft-element.llft-id-" + this.identifier;
4849
+ }
4850
+
4851
+ get _dom_root()
4852
+ {
4853
+ return document.querySelector(this._sel_root);
4854
+ }
4855
+ };
4856
+
4857
+ LayoutControl.prototype._ul4onattrs = ["label", "identifier", "view", "top", "left", "width", "height"];
4858
+ LayoutControl.prototype._ul4attrs = new Set(["id", "label", "identifier", "view", "top", "left", "width", "height"]);
4859
+
4860
+
4861
+ class HTMLLayoutControlType extends LayoutControlType
4862
+ {
4863
+ instancecheck(obj)
4864
+ {
4865
+ return obj instanceof HTMLLayoutControl;
4866
+ }
4867
+ };
4868
+
4869
+ let htmllayoutcontroltype = new HTMLLayoutControlType("la", "HTMLLayoutControl", "HTML decoration in an input form");
4870
+
4871
+
4872
+ export class HTMLLayoutControl extends LayoutControl
4873
+ {
4874
+ [ul4.symbols.type]()
4875
+ {
4876
+ return htmllayoutcontroltype;
4877
+ }
4878
+
4879
+ get value()
4880
+ {
4881
+ return this._value;
4882
+ }
4883
+
4884
+ set value(value)
4885
+ {
4886
+ this._value = value;
4887
+ if (this.globals._in_form())
4888
+ this._set_dom_value(this._value);
4889
+ }
4890
+
4891
+ _set_dom_value(value)
2189
4892
  {
2190
- let repr = "<LookupItem key=" + ul4._repr(this.key) + " label=" + ul4._repr(this.label);
2191
- if (!this.visible)
2192
- repr += "visible=False"
2193
- return repr + ">";
4893
+ this._dom_root.innerHTML = value;
4894
+ }
4895
+
4896
+ [ul4.symbols.setattr](name, value)
4897
+ {
4898
+ if (name === "value")
4899
+ this.value = value;
4900
+ else
4901
+ return super[ul4.symbols.getattr](name);
2194
4902
  }
2195
4903
  };
2196
4904
 
2197
- LookupItem.prototype._ul4onattrs = ["control", "key", "_label"];
2198
- LookupItem.prototype._ul4attrs = new Set(["id", "control", "key", "label"]);
4905
+ HTMLLayoutControl.prototype._ul4onattrs = [...LayoutControl.prototype._ul4onattrs, "_value"];
4906
+ HTMLLayoutControl.prototype._ul4attrs = new Set([...LayoutControl.prototype._ul4attrs, "value"]);
2199
4907
 
2200
4908
 
2201
- export class ViewLookupItem extends Base
4909
+ class ImageLayoutControlType extends LayoutControlType
2202
4910
  {
2203
- static classdoc = "View specific information about a lookup item";
2204
-
2205
- [ul4.symbols.repr]()
4911
+ instancecheck(obj)
2206
4912
  {
2207
- let repr = "<ViewLookupItem key=" + ul4._repr(this.key) + " label=" + ul4._repr(this.label);
2208
- if (!this.visible)
2209
- repr += " visible=False"
2210
- return repr + ">";
4913
+ return obj instanceof ImageLayoutControl;
2211
4914
  }
2212
4915
  };
2213
4916
 
2214
- ViewLookupItem.prototype._ul4onattrs = ["key", "label", "visible"];
2215
- ViewLookupItem.prototype._ul4attrs = new Set(["key", "label", "visible"]);
4917
+ let imagelayoutcontroltype = new ImageLayoutControlType("la", "ImageLayoutControl", "An image decoration in an input form");
2216
4918
 
2217
4919
 
2218
- export class LayoutControl extends Base
4920
+ export class ImageLayoutControl extends LayoutControl
2219
4921
  {
2220
- static classdoc = "A decoration in an input form";
2221
-
2222
- [ul4.symbols.repr]()
4922
+ [ul4.symbols.type]()
2223
4923
  {
2224
- return "<" + this.constructor.name + " id=" + ul4._repr(this.id) + " identifier=" + ul4._repr(this.identifier) + ">";
4924
+ return imagelayoutcontroltype;
2225
4925
  }
2226
4926
  };
2227
4927
 
2228
- LayoutControl.prototype._ul4onattrs = ["label", "identifier", "view", "top", "left", "width", "height"];
2229
- LayoutControl.prototype._ul4attrs = new Set(["id", "label", "identifier", "view", "top", "left", "width", "height"]);
4928
+ ImageLayoutControl.prototype._ul4onattrs = [...LayoutControl.prototype._ul4onattrs, "original", "scaled"];
4929
+ ImageLayoutControl.prototype._ul4attrs = new Set([...LayoutControl.prototype._ul4attrs, "original", "scaled"]);
2230
4930
 
2231
4931
 
2232
- export class HTMLLayoutControl extends LayoutControl
4932
+ class ButtonLayoutControlType extends LayoutControlType
2233
4933
  {
2234
- static classdoc = "An HTML decoration in an input form";
4934
+ instancecheck(obj)
4935
+ {
4936
+ return obj instanceof ButtonLayoutControl;
4937
+ }
2235
4938
  };
2236
4939
 
2237
- HTMLLayoutControl.prototype._ul4onattrs = [...LayoutControl.prototype._ul4onattrs, "value"];
2238
- HTMLLayoutControl.prototype._ul4attrs = new Set([LayoutControl.prototype._ul4attrs, "value"]);
4940
+ let buttonlayoutcontroltype = new ButtonLayoutControlType("la", "ButtonLayoutControl", "A submit button in an input form");
2239
4941
 
2240
4942
 
2241
- export class ImageLayoutControl extends LayoutControl
4943
+ export class ButtonLayoutControl extends LayoutControl
4944
+ {
4945
+ [ul4.symbols.type]()
4946
+ {
4947
+ return buttonlayoutcontroltype;
4948
+ }
4949
+ };
4950
+
4951
+
4952
+ class ViewControlType extends ul4.Type
2242
4953
  {
2243
- static classdoc = "An image decoration in an input form";
4954
+ instancecheck(obj)
4955
+ {
4956
+ return obj instanceof ViewControl;
4957
+ }
2244
4958
  };
2245
4959
 
2246
- ImageLayoutControl.prototype._ul4onattrs = [...LayoutControl.prototype._ul4onattrs, "original", "scaled"];
2247
- ImageLayoutControl.prototype._ul4attrs = new Set([LayoutControl.prototype._ul4attrs, "original", "scaled"]);
4960
+ let viewcontroltype = new ViewControlType("la", "ViewControl", "Contains view specific information about a control");
2248
4961
 
2249
4962
 
2250
4963
  export class ViewControl extends Base
2251
4964
  {
2252
- static classdoc = "Contains view specific information aboutn a control";
4965
+ [ul4.symbols.type]()
4966
+ {
4967
+ return viewcontroltype;
4968
+ }
2253
4969
 
2254
4970
  get mode()
2255
4971
  {
@@ -2261,9 +4977,23 @@ ViewControl.prototype._ul4onattrs = ["view", "control", "top", "left", "width",
2261
4977
  ViewControl.prototype._ul4attrs = new Set(["id", "view", "control", "top", "left", "width", "height", "liveupdate", "default", "tabindex", "minlength", "maxlength", "required", "placeholder", "mode", "labelpos", "lookupnonekey", "lookupnonelabel", "label", "autoalign", "labelwidth", "lookupdata", "autoexpandable"]);
2262
4978
 
2263
4979
 
4980
+ class UserType extends ul4.Type
4981
+ {
4982
+ instancecheck(obj)
4983
+ {
4984
+ return obj instanceof User;
4985
+ }
4986
+ };
4987
+
4988
+ let usertype = new UserType("la", "User", "A LivingApps user/account");
4989
+
4990
+
2264
4991
  export class User extends Base
2265
4992
  {
2266
- static classdoc = "A LivingApps user/account";
4993
+ [ul4.symbols.type]()
4994
+ {
4995
+ return usertype;
4996
+ }
2267
4997
 
2268
4998
  [ul4.symbols.repr]()
2269
4999
  {
@@ -2275,25 +5005,60 @@ User.prototype._ul4onattrs = ["_id", "gender", "title", "firstname", "surname",
2275
5005
  User.prototype._ul4attrs = new Set(["id", "_id", "gender", "title", "firstname", "surname", "initials", "email", "streetname", "streetnumber", "zip", "city", "phone", "fax", "lang", "avatarsmall", "avatarlarge", "summary", "interests", "personalwebsite", "companywebsite", "company", "position", "department", "keyviews"]);
2276
5006
 
2277
5007
 
5008
+ class FileType extends ul4.Type
5009
+ {
5010
+ instancecheck(obj)
5011
+ {
5012
+ return obj instanceof File;
5013
+ }
5014
+ };
5015
+
5016
+ let filetype = new FileType("la", "File", "An uploaded file");
5017
+
5018
+
2278
5019
  export class File extends Base
2279
5020
  {
2280
- static classdoc = "An uploaded file";
5021
+ [ul4.symbols.type]()
5022
+ {
5023
+ return filetype;
5024
+ }
2281
5025
 
2282
5026
  [ul4.symbols.repr]()
2283
5027
  {
2284
5028
  return "<File id=" + ul4._repr(this.id) + " url=" + ul4._repr(this.url) + " filename=" + ul4._repr(this.filename) + ">";
2285
5029
  }
5030
+
5031
+ get url()
5032
+ {
5033
+ return "/gateway/files/" + this.id;
5034
+ }
5035
+
5036
+ get archive_url()
5037
+ {
5038
+ if (this.archive === null)
5039
+ return this.url;
5040
+ return this.archive.url + "/" + this.filename;
5041
+ }
2286
5042
  };
2287
5043
 
2288
- File.prototype._ul4onattrs = ["url", "filename", "mimetype", "width", "height", "internalid", "createdat", "size"];
2289
- File.prototype._ul4attrs = new Set(["id", "url", "filename", "mimetype", "width", "height", "size", "createdat"]);
5044
+ File.prototype._ul4onattrs = ["filename", "mimetype", "width", "height", "internalid", "createdat", "size", "duration", "geo", "storagefilename", "archive"];
5045
+ File.prototype._ul4attrs = new Set(["id", "url", "archive_url", "filename", "mimetype", "width", "height", "size", "duration", "geo", "archive", "createdat"]);
2290
5046
 
2291
5047
 
2292
- export class Geo extends Base
5048
+ class GeoType extends ul4.Type
2293
5049
  {
2294
- static classdoc = "Geographical coordinates and location information";
5050
+ instancecheck(obj)
5051
+ {
5052
+ return obj instanceof Geo;
5053
+ }
5054
+ };
5055
+
5056
+ let geotype = new GeoType("la", "Geo", "Geographical coordinates and location information");
5057
+
2295
5058
 
2296
- constructor(lat, long, info)
5059
+ export class Geo extends Base
5060
+ {
5061
+ constructor(lat, long, info=null)
2297
5062
  {
2298
5063
  super(null);
2299
5064
  this.lat = lat;
@@ -2301,6 +5066,11 @@ export class Geo extends Base
2301
5066
  this.info = info;
2302
5067
  }
2303
5068
 
5069
+ [ul4.symbols.type]()
5070
+ {
5071
+ return geotype;
5072
+ }
5073
+
2304
5074
  [ul4.symbols.repr]()
2305
5075
  {
2306
5076
  return "<Geo lat=" + ul4._repr(this.lat) + " long=" + ul4._repr(this.long) + " info=" + ul4._repr(this.info) + ">";
@@ -2311,8 +5081,24 @@ Geo.prototype._ul4onattrs = ["lat", "long", "info"];
2311
5081
  Geo.prototype._ul4attrs = new Set(["lat", "long", "info"]);
2312
5082
 
2313
5083
 
5084
+ class AttachmentType extends ul4.Type
5085
+ {
5086
+ instancecheck(obj)
5087
+ {
5088
+ return obj instanceof Attachment;
5089
+ }
5090
+ };
5091
+
5092
+ let attachmenttype = new AttachmentType("la", "Attachment", "An attachment of a record");
5093
+
5094
+
2314
5095
  export class Attachment extends Base
2315
5096
  {
5097
+ [ul4.symbols.type]()
5098
+ {
5099
+ return attachmenttype;
5100
+ }
5101
+
2316
5102
  [ul4.symbols.repr]()
2317
5103
  {
2318
5104
  return "<" + this.constructor.name + " id=" + ul4._repr(this.id) + " label=" + ul4._repr(this.label) + ">";
@@ -2323,10 +5109,23 @@ Attachment.prototype._ul4onattrs = ["record", "label", "active"];
2323
5109
  Attachment.prototype._ul4attrs = new Set(["id", "record", "label", "active"]);
2324
5110
 
2325
5111
 
2326
- export class NoteAttachment extends Attachment
5112
+ class NoteAttachmentType extends AttachmentType
2327
5113
  {
2328
- static classdoc = "A note attachment of a record";
5114
+ instancecheck(obj)
5115
+ {
5116
+ return obj instanceof NoteAttachment;
5117
+ }
5118
+ };
5119
+
5120
+ let noteattachmenttype = new NoteAttachmentType("la", "NoteAttachment", "A note attachment of a record");
2329
5121
 
5122
+
5123
+ export class NoteAttachment extends Attachment
5124
+ {
5125
+ [ul4.symbols.type]()
5126
+ {
5127
+ return noteattachmenttype;
5128
+ }
2330
5129
  };
2331
5130
 
2332
5131
  NoteAttachment.prototype.type = "noteattachment";
@@ -2334,10 +5133,23 @@ NoteAttachment.prototype._ul4onattrs = [...Attachment.prototype._ul4onattrs, "va
2334
5133
  NoteAttachment.prototype._ul4attrs = new Set([...Attachment.prototype._ul4onattrs, "value"]);
2335
5134
 
2336
5135
 
2337
- export class URLAttachment extends Attachment
5136
+ class URLAttachmentType extends AttachmentType
2338
5137
  {
2339
- static classdoc = "A URL attachment of a record";
5138
+ instancecheck(obj)
5139
+ {
5140
+ return obj instanceof URLAttachment;
5141
+ }
5142
+ };
5143
+
5144
+ let urlattachmenttype = new URLAttachmentType("la", "URLAttachment", "A URL attachment of a record");
2340
5145
 
5146
+
5147
+ export class URLAttachment extends Attachment
5148
+ {
5149
+ [ul4.symbols.type]()
5150
+ {
5151
+ return urlattachmenttype;
5152
+ }
2341
5153
  };
2342
5154
 
2343
5155
  URLAttachment.prototype.type = "urlattachment";
@@ -2345,10 +5157,23 @@ URLAttachment.prototype._ul4onattrs = [...Attachment.prototype._ul4onattrs, "val
2345
5157
  URLAttachment.prototype._ul4attrs = new Set([...Attachment.prototype._ul4onattrs, "value"]);
2346
5158
 
2347
5159
 
2348
- export class FileAttachment extends Attachment
5160
+ class FileAttachmentType extends AttachmentType
2349
5161
  {
2350
- static classdoc = "A file attachment of a record";
5162
+ instancecheck(obj)
5163
+ {
5164
+ return obj instanceof FileAttachment;
5165
+ }
5166
+ };
5167
+
5168
+ let fileattachmenttype = new FileAttachmentType("la", "FileAttachment", "A file attachment of a record");
2351
5169
 
5170
+
5171
+ export class FileAttachment extends Attachment
5172
+ {
5173
+ [ul4.symbols.type]()
5174
+ {
5175
+ return fileattachmenttype;
5176
+ }
2352
5177
  };
2353
5178
 
2354
5179
  FileAttachment.prototype.type = "fileattachment";
@@ -2356,10 +5181,23 @@ FileAttachment.prototype._ul4onattrs = [...Attachment.prototype._ul4onattrs, "va
2356
5181
  FileAttachment.prototype._ul4attrs = new Set([...Attachment.prototype._ul4onattrs, "value"]);
2357
5182
 
2358
5183
 
2359
- export class ImageAttachment extends Attachment
5184
+ class ImageAttachmentType extends AttachmentType
2360
5185
  {
2361
- static classdoc = "An image attachment of a record";
5186
+ instancecheck(obj)
5187
+ {
5188
+ return obj instanceof ImageAttachment;
5189
+ }
5190
+ };
5191
+
5192
+ let imageattachmenttype = new ImageAttachmentType("la", "ImageAttachment", "An image attachment of a record");
2362
5193
 
5194
+
5195
+ export class ImageAttachment extends Attachment
5196
+ {
5197
+ [ul4.symbols.type]()
5198
+ {
5199
+ return imageattachmenttype;
5200
+ }
2363
5201
  };
2364
5202
 
2365
5203
  ImageAttachment.prototype.type = "imageattachment";
@@ -2367,9 +5205,23 @@ ImageAttachment.prototype._ul4onattrs = [...Attachment.prototype._ul4onattrs, "o
2367
5205
  ImageAttachment.prototype._ul4attrs = new Set([...Attachment.prototype._ul4onattrs, "original", "thumb", "small", "medium", "large"]);
2368
5206
 
2369
5207
 
5208
+ class JSONAttachmentType extends AttachmentType
5209
+ {
5210
+ instancecheck(obj)
5211
+ {
5212
+ return obj instanceof JSONAttachment;
5213
+ }
5214
+ };
5215
+
5216
+ let jsonattachmenttype = new JSONAttachmentType("la", "JSONAttachment", "A JSON attachment of a record");
5217
+
5218
+
2370
5219
  export class JSONAttachment extends Attachment
2371
5220
  {
2372
- static classdoc = "A JSON attachment of a record";
5221
+ [ul4.symbols.type]()
5222
+ {
5223
+ return jsonattachmenttype;
5224
+ }
2373
5225
 
2374
5226
  _dumpUL4ONAttr(name)
2375
5227
  {
@@ -2393,9 +5245,23 @@ JSONAttachment.prototype._ul4onattrs = [...Attachment.prototype._ul4onattrs, "va
2393
5245
  JSONAttachment.prototype._ul4attrs = new Set([...Attachment.prototype._ul4onattrs, "value"]);
2394
5246
 
2395
5247
 
5248
+ class InstallationType extends ul4.Type
5249
+ {
5250
+ instancecheck(obj)
5251
+ {
5252
+ return obj instanceof Installation;
5253
+ }
5254
+ };
5255
+
5256
+ let installationtype = new InstallationType("la", "Installation", "The installation that created an app");
5257
+
5258
+
2396
5259
  export class Installation extends Base
2397
5260
  {
2398
- static classdoc = "The installation that created an app";
5261
+ [ul4.symbols.type]()
5262
+ {
5263
+ return installationtype;
5264
+ }
2399
5265
 
2400
5266
  [ul4.symbols.repr]()
2401
5267
  {
@@ -2407,9 +5273,23 @@ Installation.prototype._ul4onattrs = ["name"];
2407
5273
  Installation.prototype._ul4attrs = new Set(["id", "name"]);
2408
5274
 
2409
5275
 
5276
+ class CategoryType extends ul4.Type
5277
+ {
5278
+ instancecheck(obj)
5279
+ {
5280
+ return obj instanceof Category;
5281
+ }
5282
+ };
5283
+
5284
+ let categorytype = new CategoryType("la", "Category", "A navigation category");
5285
+
5286
+
2410
5287
  export class Category extends Base
2411
5288
  {
2412
- static classdoc = "A navigation category";
5289
+ [ul4.symbols.type]()
5290
+ {
5291
+ return categorytype;
5292
+ }
2413
5293
 
2414
5294
  [ul4.symbols.repr]()
2415
5295
  {
@@ -2428,9 +5308,23 @@ Category.prototype._ul4onattrs = ["identifier", "name", "order", "parent", "chil
2428
5308
  Category.prototype._ul4attrs = new Set(["id", "identifier", "name", "order", "parent", "children", "apps"]);
2429
5309
 
2430
5310
 
5311
+ class KeyViewType extends ul4.Type
5312
+ {
5313
+ instancecheck(obj)
5314
+ {
5315
+ return obj instanceof KeyView;
5316
+ }
5317
+ };
5318
+
5319
+ let keyviewtype = new KeyViewType("la", "KeyView", "Object granting access to a view template");
5320
+
5321
+
2431
5322
  export class KeyView extends Base
2432
5323
  {
2433
- static classdoc = "Object granting access to a view template";
5324
+ [ul4.symbols.type]()
5325
+ {
5326
+ return keyviewtype;
5327
+ }
2434
5328
 
2435
5329
  [ul4.symbols.repr]()
2436
5330
  {
@@ -2442,9 +5336,23 @@ KeyView.prototype._ul4onattrs = ["identifier", "name", "key", "user"];
2442
5336
  KeyView.prototype._ul4attrs = new Set(["id", "identifier", "name", "key", "user"]);
2443
5337
 
2444
5338
 
5339
+ class AppParameterType extends ul4.Type
5340
+ {
5341
+ instancecheck(obj)
5342
+ {
5343
+ return obj instanceof AppParameter;
5344
+ }
5345
+ };
5346
+
5347
+ let appparametertype = new AppParameterType("la", "AppParameter", "A parameter of a LivingApps application");
5348
+
5349
+
2445
5350
  export class AppParameter extends Base
2446
5351
  {
2447
- static classdoc = "A parameter of a LivingApps application";
5352
+ [ul4.symbols.type]()
5353
+ {
5354
+ return appparametertype;
5355
+ }
2448
5356
 
2449
5357
  [ul4.symbols.repr]()
2450
5358
  {
@@ -2456,12 +5364,175 @@ AppParameter.prototype._ul4onattrs = ["app", "identifier", "description", "value
2456
5364
  AppParameter.prototype._ul4attrs = new Set(["id", "app", "identifier", "description", "value"]);
2457
5365
 
2458
5366
 
5367
+ class FormType extends ul4.Type
5368
+ {
5369
+ instancecheck(obj)
5370
+ {
5371
+ return obj instanceof Form;
5372
+ }
5373
+ };
5374
+
5375
+ let formtype = new FormType("la", "Form", "The input form.");
5376
+
5377
+ export class Form extends ul4.Proto
5378
+ {
5379
+ constructor(globals, template)
5380
+ {
5381
+ super();
5382
+ this.globals = globals;
5383
+ this.template = template;
5384
+ this._geo_wired = false;
5385
+
5386
+ for (let field of globals.record.fields.values())
5387
+ this.wire_field(field);
5388
+ this.render_template(null);
5389
+ }
5390
+
5391
+ [ul4.symbols.type]()
5392
+ {
5393
+ return formtype;
5394
+ }
5395
+
5396
+ get _dom_button()
5397
+ {
5398
+ return document.querySelector(this._sel_form + " " + this._sel_button);
5399
+ }
5400
+
5401
+ get enabled()
5402
+ {
5403
+ return !this._dom_button.disabled;
5404
+ }
5405
+
5406
+ set enabled(value)
5407
+ {
5408
+ this._dom_button.disabled = !value;
5409
+ }
5410
+
5411
+ [ul4.symbols.getattr](key)
5412
+ {
5413
+ if (key === "enabled")
5414
+ return this.enabled;
5415
+ else
5416
+ throw new ul4.AttributeError(this, key);
5417
+ }
5418
+
5419
+ [ul4.symbols.setattr](key, value)
5420
+ {
5421
+ if (key === "enabled")
5422
+ this.enabled = ul4._bool(value);
5423
+ else
5424
+ throw new ul4.AttributeError(this, key);
5425
+ }
5426
+
5427
+ [ul4.symbols.repr]()
5428
+ {
5429
+ return "<" + this.constructor.name + " enabled=" + ul4._repr(this.enabled) + ">";
5430
+ }
5431
+
5432
+ toString()
5433
+ {
5434
+ return this[ul4.symbols.repr]();
5435
+ }
5436
+
5437
+ render_template(identifier)
5438
+ {
5439
+ let vars = {
5440
+ "record": this.globals.record,
5441
+ "fields": this.globals.record.fields,
5442
+ "identifier": identifier
5443
+ };
5444
+
5445
+ let globalVars = {
5446
+ "globals": this.globals,
5447
+ "form": this,
5448
+ "la": module
5449
+ };
5450
+
5451
+ let msg = "LivingApps update template: ";
5452
+ if (identifier === null)
5453
+ msg += "Initialization";
5454
+ else
5455
+ msg += "Value change in " + ul4._repr(identifier);
5456
+
5457
+ this.globals.group_logging(msg, () => {
5458
+ try
5459
+ {
5460
+ this.template.renders(vars, globalVars);
5461
+ }
5462
+ catch (exc)
5463
+ {
5464
+ if (console && console.error)
5465
+ {
5466
+ this.globals._start_log_message();
5467
+ if (console.group)
5468
+ console.group("UL4 stacktrace");
5469
+ ul4.report_exc(exc);
5470
+ if (console.groupEnd)
5471
+ console.groupEnd();
5472
+
5473
+ if (console.groupCollapsed)
5474
+ console.groupCollapsed("Javascript stacktrace");
5475
+ console.error(exc);
5476
+ if (console.groupEnd)
5477
+ console.groupEnd();
5478
+ }
5479
+ }
5480
+ });
5481
+ }
5482
+
5483
+ wire_geo()
5484
+ {
5485
+ if (this._geo_wired)
5486
+ return;
5487
+
5488
+ if (this.globals.app.active_view !== null && navigator.geolocation)
5489
+ {
5490
+ let use_geo = this.globals.app.active_view.use_geo;
5491
+ if (use_geo === "once" || use_geo === "watch")
5492
+ {
5493
+ navigator.geolocation.getCurrentPosition((position) => {
5494
+ this.globals.mode = this.globals.mode.substring(0, this.globals.mode.lastIndexOf("/") + 1) + "geo";
5495
+ this.globals.set_current_geo(position);
5496
+ this.render_template(null);
5497
+ });
5498
+ }
5499
+
5500
+ if (use_geo === "watch")
5501
+ {
5502
+ navigator.geolocation.watchPosition((position) => {
5503
+ this.globals.mode = this.globals.mode.substring(0, this.globals.mode.lastIndexOf("/") + 1) + "geo";
5504
+ this.globals.set_current_geo(position);
5505
+ this.render_template(null);
5506
+ });
5507
+ }
5508
+ }
5509
+ this._geo_wired = true;
5510
+ }
5511
+
5512
+ wire_field(field)
5513
+ {
5514
+ for (let dom_node of field._dom_controls)
5515
+ {
5516
+ dom_node.addEventListener(field._inputevent, (event) => {
5517
+ this.wire_geo();
5518
+ this.globals.mode = this.globals.mode.substring(0, this.globals.mode.lastIndexOf("/") + 1) + "input";
5519
+ this.render_template(field.control.identifier);
5520
+ });
5521
+ }
5522
+ }
5523
+ };
5524
+
5525
+ Form.prototype._ul4attrs = new Set(["enabled"]);
5526
+ Form.prototype._sel_form = "#livingapps-form form";
5527
+ Form.prototype._sel_button = "[type=submit]";
5528
+
5529
+
2459
5530
  let classes = [
2460
5531
  Globals,
2461
5532
  FlashMessage,
2462
5533
  App,
2463
5534
  View,
2464
- DataSourceData,
5535
+ DataSource,
2465
5536
  Record,
2466
5537
  BoolControl,
2467
5538
  IntControl,
@@ -2522,6 +5593,7 @@ let classes = [
2522
5593
  LayoutControl,
2523
5594
  HTMLLayoutControl,
2524
5595
  ImageLayoutControl,
5596
+ ButtonLayoutControl,
2525
5597
  ViewControl,
2526
5598
  User,
2527
5599
  File,
@@ -2541,3 +5613,62 @@ for (let constructor of classes)
2541
5613
  {
2542
5614
  ul4.register("de.livinglogic.livingapi." + constructor.name.toLowerCase(), constructor);
2543
5615
  }
5616
+
5617
+ export const module = new ul4.Module(
5618
+ "la",
5619
+ "LivingAPI types",
5620
+ {
5621
+ FlashMessage: FlashMessage,
5622
+ File: File,
5623
+ Geo: Geo,
5624
+ User: User,
5625
+ KeyView: KeyView,
5626
+ Globals: Globals,
5627
+ App: App,
5628
+ TextControl: TextControl,
5629
+ URLControl: URLControl,
5630
+ EmailControl: EmailControl,
5631
+ PasswordControl: PasswordControl,
5632
+ TelControl: TelControl,
5633
+ TextAreaControl: TextAreaControl,
5634
+ HTMLControl: HTMLControl,
5635
+ IntControl: IntControl,
5636
+ NumberControl: NumberControl,
5637
+ DateControl: DateControl,
5638
+ DatetimeMinuteControl: DatetimeMinuteControl,
5639
+ DatetimeSecondControl: DatetimeSecondControl,
5640
+ BoolControl: BoolControl,
5641
+ LookupSelectControl: LookupSelectControl,
5642
+ LookupRadioControl: LookupRadioControl,
5643
+ LookupChoiceControl: LookupChoiceControl,
5644
+ AppLookupSelectControl: AppLookupSelectControl,
5645
+ AppLookupRadioControl: AppLookupRadioControl,
5646
+ AppLookupChoiceControl: AppLookupChoiceControl,
5647
+ MultipleLookupSelectControl: MultipleLookupSelectControl,
5648
+ MultipleLookupCheckboxControl: MultipleLookupCheckboxControl,
5649
+ MultipleLookupChoiceControl: MultipleLookupChoiceControl,
5650
+ MultipleAppLookupSelectControl: MultipleAppLookupSelectControl,
5651
+ MultipleAppLookupCheckboxControl: MultipleAppLookupCheckboxControl,
5652
+ MultipleAppLookupChoiceControl: MultipleAppLookupChoiceControl,
5653
+ FileControl: FileControl,
5654
+ FileSignatureControl: FileSignatureControl,
5655
+ GeoControl: GeoControl,
5656
+ ViewControl: ViewControl,
5657
+ Record: Record,
5658
+ ImageAttachment: ImageAttachment,
5659
+ FileAttachment: FileAttachment,
5660
+ URLAttachment: URLAttachment,
5661
+ NoteAttachment: NoteAttachment,
5662
+ JSONAttachment: JSONAttachment,
5663
+ Installation: Installation,
5664
+ HTMLLayoutControl: HTMLLayoutControl,
5665
+ ImageLayoutControl: ImageLayoutControl,
5666
+ ButtonLayoutControl: ButtonLayoutControl,
5667
+ View: View,
5668
+ DataSource: DataSource,
5669
+ LookupItem: LookupItem,
5670
+ ViewLookupItem: ViewLookupItem,
5671
+ Category: Category,
5672
+ AppParameter: AppParameter,
5673
+ }
5674
+ );