implement web application JavaScript and TypeScript classes

kwebapp-javascript [
] [

The kwebapp-javascript utility accepts a kwebapp(5) config (defaulting to standard input) and creates JavaScript or TypeScript classes formatting the JSON produced by kwebapp-c-header(1) and kwebapp-c-source(1). The configuration may be broken apart into several files. Its arguments are as follows:
Emits Typescript instead of JavaScript.
Configuration file in kwebapp(5) syntax.
Both output formats consist of a set of classes within the “kwebapp” namespace describing structures, enumerations, and bitfields. The method for acquiring the JSON is not managed by kwebapp-javascript, but is usually provided by a CGI interfacing with kwebapp-c-header(1) and kwebapp-c-source(1).
To use the interface, simply include the generated file as a script, create objects from the JSON exported by kwebapp-c-source(1), and invoke the applicable object's fill(), fillByClass(), fillInner(), fillInnerByClass(), fillArray(), fillArrayOrHide(), and fillArrayOrShow(), methods with a DOM tree node.
These methods operate on elements with certain classes beneath a given element root as follows:
Sets or unsets the checked attribute depending upon whether the input's value attribute is covered by the object's bitmask. Only applicable to bit types.
Replaces the contents of the element with the ISO 8601 date of the object's value. Only applicable to date and epoch types.
Sets the value attribute to the ISO 8601 date of the object's value. Only applicable to date and epoch types.
All <option> descendents of the element are marked as “selected” or not depending upon whether their value matches the field value.
For structures, creates and invokes the fillInner() method on the nested structure at the given element and its descendents. This is only applicable for structure types.
Replaces the contents of the element with the field value. This is not applicable to blob native types.
Sets the value attribute (as in a form submission) with the field value. This is not applicable to blob native types.
Sets or unsets the checked attribute depending upon whether the input's value attribute matches the objects. This is not applicable to blob or structure types.
Remove the “hide” class if the object is null, otherwise add the “hide” class.
Add the “hide” class if the object is null, otherwise remove the “hide” class.
The fillInner() and fillInnerByClass() methods may be used to exclude the passed-in root element, while fill() and fillByClass() include this element.
The fillArray(), fillArrayOrHide(), and fillArrayOrShow() methods invoke fill() repeatedly over an array of objects by removing, then subsequently cloning and appending, the first element of the give DOM root. The show and hide variants perform additional labour, usually to show a message that elements have not or (more rarely) have been found.
Enumeration and bitfield classes are also generated from the input file. These are appended to the namespace as a series of classes consisting of static variables assigned the enumeration value.
All output objects are fully documented in the jsdoc(1) format.

All functions accept an optional argument for providing custom per-field or per-structure callbacks. Keys in the object must consist of the structure name, followed by a dash, followed by the field name. For example, assuming a structure “client” with a field “dob” consisting of a UNIX epoch:
var custom = { 'client-dob': formatDate }; 
new kwebapp.client(obj).fillInner(document.body, custom);
And letting a formatting function be:
function formatDate(e, name, value) { 
  var list, i; 
  list = e.getElementsByClassName('client-dob-date-moment'); 
  for (i = 0; i < list.length; i++) 
    list[i].innerHTML = 
This invokes the “moment.js” formatter to create dates.
The same can be applied to structures instead of to fields within structures. The keys for these are simply the structure name.
var custom = { 'client': formatClient }; 
new kwebapp.client(obj).fillInner(document.body, custom);
The callback will then be provided the full client object.
In either case, the value for the custom key may also be an array of functions just as above. Each will be invoked in the order given, in the same way.
var custom = { 'client': [ format1, format2 ] };
The callback function (or functions) will be invoked regardless of whether the value has been set. In the event of an unset field value, the function is passed null.
When using TypeScript, the values of the format function are typed according to the structure or field passed. For example, if the “dob” field of structure “client” is a UNIX epoch, the format function accepts a number or null.
function formatDate(e: HTMLElement, 
  name: string, v: number|null): void { 
	/* Do something... */ 
The dictionary object is defined as follows:
let custom: DataCallbacks = { 'client-dob': formatDate }; 
new kwebapp.client(obj).fillInner(document.body, custom);

Enumerations and bitfields in kwebapp(5) are translated into classes with a static format() function that may be passed as a custom handler for corresponding fields. These fill in the kwebapp(5) jslabel of the corresponding values. If a language is specified in the root of the HTML or XML document, it is first matched to the language of the label. If there is no language, or none for that label, the default label is used. If there is no default label, an empty string is used instead.
In the event of unset bitfields, the corresponding kwebapp(5) isunset value is used, and the kwbp-unset class set on the element. For null values, isnull is used and kwbp-null set on the element.
For example, to fill in the label of an enumeration enum someenum on a field named val, provide a custom callback.
var obj = JSON.parse(response); 
var e = document.getElementById('foo'); 
var custom = { 
  'foo-val': kwebapp.someenum.format 
new, custom);

The kwebapp-javascript utility exits 0 on success, and >0 if an error occurs.

Given a kwebapp(5) structure “foo” with a single field “bar” and an AJAX response “response”, an example invocation may be as follows:
var obj = JSON.parse(response); 
This will fill in all classes under e (if found) named foo-bar-value, foo-bar-text, foo-has-bar, foo-no-bar, and foo-enum-select.
The TypeScript interface would instead look as follows, assuming that the JSON parse returns the “foo” JSON object.
let obj: kwebapp.fooData = 

jsdoc(1), kwebapp-c-header(1), kwebapp-c-source(1), tsc(1), kwebapp(5)
November 23, 2018 OpenBSD 6.4