1 namespace ort {
    2 	/**
    3 	 * Facilities to manipulate 64-bit numbers encoded as strings.
    4 	 * The JavaScript implementation of openradtool uses strings for numbers
    5 	 * because of the 64-bit problem: internally, openradtool uses 64-bit
    6 	 * integer numbers, but JavaScript has only 53 bits of precision for
    7 	 * integers, and 32 for bit-wise operations.
    8 	 * This class is a modified version of long.js fixed to base 10 and
    9 	 * converted to TypeScript.
   10 	 *
   11 	 * Original source: https://github.com/dcodeIO/long.js
   12 	 *
   13 	 * @license
   14 	 * Copyright 2009 The Closure Library Authors.
   15 	 * Copyright 2020 Daniel Wirtz / The long.js Contributors.
   16 	 * Copyright 2021 Kristaps Dzonsons
   17 	 * SPDX-License-Identifier: Apache-2.0
   18 	 */
   19 	export class Long {
   20 		private readonly __isLong__: boolean = true;
   21 		private readonly low: number;
   22 		private readonly high: number;
   23 		private readonly unsigned: boolean;
   24 
   25 		private constructor(low: number,
   26 			high?: number, unsigned?: boolean)
   27 		{
   28 			this.low = low | 0;
   29 			this.high = 
   30 				(typeof high === 'undefined') ?
   31 				0 : (high | 0);
   32 			this.unsigned = 
   33 				(typeof unsigned === 'undefined') ?
   34 				false: unsigned;
   35 		}
   36 
   37 		static readonly ZERO: Long = new Long(0, 0);
   38 		static readonly ONE: Long = new Long(1, 0);
   39 		static readonly UZERO: Long = new Long(0, 0, true);
   40 		static readonly TEN_TO_EIGHT: Long = new Long(100000000, 0);
   41 
   42 		static readonly MIN_VALUE: Long = 
   43 			new Long(0, 0x80000000|0, false);
   44 		static readonly MAX_UNSIGNED_VALUE: Long = 
   45 			new Long(0xFFFFFFFF|0, 0xFFFFFFFF|0, true);
   46 		static readonly  MAX_VALUE: Long = 
   47 			new Long(0xFFFFFFFF|0, 0x7FFFFFFF|0, false);
   48 
   49 		/* Constant numbers used in the code. */
   50 
   51 		private static readonly TWO_PWR_16_DBL: number = 
   52 			(1 << 16);
   53 		private static readonly TWO_PWR_32_DBL: number = 
   54 			Long.TWO_PWR_16_DBL *
   55 			Long.TWO_PWR_16_DBL;
   56 		private static readonly TWO_PWR_64_DBL: number =
   57 			Long.TWO_PWR_32_DBL *
   58 			Long.TWO_PWR_32_DBL;
   59 		private static readonly TWO_PWR_63_DBL: number = 
   60 			Long.TWO_PWR_64_DBL / 2;
   61 
   62 		/**
   63 		 * @return Whether this is a ortns.Long object.
   64 		 */
   65 		static isLong(obj: any): boolean 
   66 		{
   67 			/* 
   68 			 * Complex to silence a typescript warning about
   69 			 * __isLong__ being an unused local otherwise.
   70 			 */
   71 
   72 			return typeof obj === 'object' &&
   73 		 	       obj !== null && 
   74 			       '__isLong__' in obj &&
   75 			       (<Long>obj).__isLong__ === true;
   76 		}
   77 
   78 		/**
   79 		 * Convert to a JavaScript number, losing precision
   80 		 * (from 64 to 53 bits) and thus possibly truncating
   81 		 * with larger or smaller numbers.
   82 		 * @return The Long converted to a number.
   83 		 */
   84 		toNumber(): number
   85 		{
   86 			if (this.unsigned)
   87 				return ((this.high >>> 0) * 
   88 					Long.TWO_PWR_32_DBL) + 
   89 				       (this.low >>> 0);
   90 			return this.high * Long.TWO_PWR_32_DBL + 
   91 				(this.low >>> 0);
   92 		};
   93 
   94 		/**
   95 		 * Similar to toNumber() except further reducing the
   96 		 * number to 32 bits of precision.
   97 		 * @return The Long converted to a number.
   98 		 */
   99 		toInt(): number
  100 		{
  101 			return this.unsigned ? this.low >>> 0 : this.low;
  102 		}
  103 
  104 		/**
  105 		 * Test whether the value is strictly <0.  For unsigned
  106 		 * values, this is always false.
  107 		 * @return Whether the value is strictly <0.
  108 		 */
  109 		isNegative(): boolean
  110 		{
  111 			return !this.unsigned && this.high < 0;
  112 		}
  113 
  114 		/**
  115 		 * Test whether the value is zero, regardless of sign.
  116 		 * @return Whether the value is zero.
  117 		 */
  118 		isZero(): boolean
  119 		{
  120 			return this.high === 0 && this.low === 0;
  121 		}
  122 
  123 		/**
  124 		 * Test whether the value is an odd number, regardless
  125 		 * of sign.
  126 		 * @return Whether the value is an odd number.
  127 		 */
  128 		isOdd(): boolean
  129 		{
  130 			return (this.low & 1) === 1;
  131 		}
  132 
  133 		/**
  134 		 * Test whether the value equals the given value.  This
  135 		 * is according to the numerical value, not the bit
  136 		 * pattern, so a negative signed value and a positive
  137 		 * signed value will be the same even if having the same
  138 		 * bit pattern.  The exception here is zero, which is
  139 		 * the same whether signed or not.
  140 		 * @return Whether the values are equal.
  141 		 */
  142 		eq(other: Long|number): boolean
  143 		{
  144 			const v: Long = !Long.isLong(other) ?
  145 				Long.fromNumber(<number>other) : <Long>other;
  146 
  147 			if (this.unsigned !== v.unsigned && 
  148 			    (this.high >>> 31) === 1 && 
  149 				    (v.high >>> 31) === 1)
  150 				return false;
  151 			return this.high === v.high && 
  152 				this.low === v.low;
  153 		}
  154 
  155 		/**
  156 		 * Negate a number (make it negative if positive,
  157 		 * positive if negative).  If zero, this converts to
  158 		 * zero of the other sign.
  159 		 * @return The negated value.
  160 		 */
  161 		neg(): Long
  162 		{
  163 			if (!this.unsigned && this.eq(Long.MIN_VALUE))
  164 				return Long.MIN_VALUE;
  165 			return this.not().add(Long.ONE);
  166 		}
  167 
  168 		/**
  169 		 * The bit-wise NOT of the value.  This retains the sign
  170 		 * of the original.
  171 		 * @return The bit-wise NOT of the value.
  172 		 */
  173 		not(): Long
  174 		{
  175 			return new Long(~this.low, 
  176 				~this.high, this.unsigned);
  177 		}
  178 
  179 		/**
  180 		 * The bit-wise AND of the value with the argument.
  181 		 * This retains the sign of the original.
  182 		 * @return The bit-wise AND of the value and argument.
  183 		 */
  184 		and(other: Long|number): Long
  185 		{
  186 			const v: Long = !Long.isLong(other) ?
  187 				Long.fromNumber(<number>other) : <Long>other;
  188 			return new Long(this.low & v.low, 
  189 					this.high & v.high, 
  190 					this.unsigned);
  191 		}
  192 
  193 		/**
  194 		 * The bit-wise OR of the value with the argument.
  195 		 * Sign is inherited from the source value.
  196 		 * @return The bit-wise OR of the value and argument.
  197 		 */
  198 		or(other: Long|number): Long 
  199 		{
  200 			const v: Long = !Long.isLong(other) ?
  201 				Long.fromNumber(<number>other) : <Long>other;
  202 			return new Long(this.low | v.low, 
  203 					this.high | v.high, 
  204 					this.unsigned);
  205 		}
  206 
  207 		/**
  208 		 * Compare the value with the argument and return their
  209 		 * sign comparison: 1 if the value is greater, -1 if
  210 		 * less, 0 if the same.  Zero is always the same as
  211 		 * zero, regardless the sign.
  212 		 * @return 0 if they are the same, 1 if the value is
  213 		 * greater, and -1 if the value is less.
  214 		 */
  215 		compare(other: Long|number): number
  216 		{
  217 			const v: Long = !Long.isLong(other) ?
  218 				Long.fromNumber(<number>other) : <Long>other;
  219 
  220 			if (this.eq(v))
  221 				return 0;
  222 
  223 			const thisNeg: boolean = this.isNegative();
  224 			const otherNeg: boolean = v.isNegative();
  225 
  226 			if (thisNeg && !otherNeg)
  227 				return -1;
  228 			if (!thisNeg && otherNeg)
  229 				return 1;
  230 
  231 			// At this point the sign bits are the same
  232 
  233 			if (!this.unsigned)
  234 				return this.sub(v).isNegative() ? -1 : 1;
  235 
  236 			// Both are positive if at least one is unsigned
  237 
  238 			return (v.high >>> 0) > (this.high >>> 0) || 
  239 				(v.high === this.high && 
  240 				 (v.low >>> 0) > (this.low >>> 0)) ?  -1 : 1;
  241 		};
  242 
  243 		/**
  244 		 * Left-shift the value by the given number of bits
  245 		 * (modulo 64).  Sign is inherited from the source
  246 		 * value.  The module means that shifting by 64 bits is
  247 		 * the same as zero, 65 the same as one, etc.  Shifting
  248 		 * by a negative number has undefined behaviour.
  249 		 * @return The left-shifted value.
  250 		 */
  251 		shl(numBits: Long|number): Long
  252 		{
  253 			let v: number = Long.isLong(numBits) ?
  254 				(<Long>numBits).toInt() : <number>numBits;
  255 
  256 			if ((v &= 63) === 0)
  257 				return this;
  258 			else if (v < 32)
  259 				return new Long
  260 					(this.low << v, 
  261 					 (this.high << v) | 
  262 					 (this.low >>> (32 - v)), 
  263 					 this.unsigned);
  264 			else
  265 				return new Long
  266 					(0, this.low << (v - 32), 
  267 					 this.unsigned);
  268 		}
  269 
  270 		/**
  271 		 * Arithmetic multiplication of the value to the argument.
  272 		 * Wrapping behaviour, including the identity at MAX_VALUE or
  273 		 * MIN_VALUE, is undefined.
  274 		 * @return The multiplied value.
  275 		 */
  276 		mul(tomul: Long|number): Long
  277 		{
  278 			const v: Long = !Long.isLong(tomul) ?
  279 				Long.fromNumber(<number>tomul) : <Long>tomul;
  280 
  281 			if (this.isZero() || v.isZero())
  282 				return Long.ZERO;
  283 			if (this.eq(Long.MIN_VALUE))
  284 				return v.isOdd() ? Long.MIN_VALUE : Long.ZERO;
  285 			if (v.eq(Long.MIN_VALUE))
  286 				return this.isOdd() ? Long.MIN_VALUE : Long.ZERO;
  287 
  288 			if (this.isNegative()) {
  289 				if (v.isNegative())
  290 					return this.neg().mul(v.neg());
  291 				else
  292 					return this.neg().mul(v).neg();
  293 			} else if (v.isNegative())
  294 				return this.mul(v.neg()).neg();
  295 
  296 			// Divide each long into 4 chunks of 16 bits,
  297 			// and then add up 4x4 products.  We can skip
  298 			// products that would overflow.
  299 
  300 			const a48: number = this.high >>> 16;
  301 			const a32: number = this.high & 0xFFFF;
  302 			const a16: number = this.low >>> 16;
  303 			const a00: number = this.low & 0xFFFF;
  304 
  305 			const b48: number = v.high >>> 16;
  306 			const b32: number = v.high & 0xFFFF;
  307 			const b16: number = v.low >>> 16;
  308 			const b00: number = v.low & 0xFFFF;
  309 
  310 			let c48: number = 0;
  311 			let c32: number = 0;
  312 			let c16: number = 0;
  313 			let c00: number = 0;
  314 
  315 			c00 += a00 * b00;
  316 			c16 += c00 >>> 16;
  317 			c00 &= 0xFFFF;
  318 			c16 += a16 * b00;
  319 			c32 += c16 >>> 16;
  320 			c16 &= 0xFFFF;
  321 			c16 += a00 * b16;
  322 			c32 += c16 >>> 16;
  323 			c16 &= 0xFFFF;
  324 			c32 += a32 * b00;
  325 			c48 += c32 >>> 16;
  326 			c32 &= 0xFFFF;
  327 			c32 += a16 * b16;
  328 			c48 += c32 >>> 16;
  329 			c32 &= 0xFFFF;
  330 			c32 += a00 * b32;
  331 			c48 += c32 >>> 16;
  332 			c32 &= 0xFFFF;
  333 			c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
  334 			c48 &= 0xFFFF;
  335 
  336 			return new Long
  337 				((c16 << 16) | c00, (c48 << 16) | c32,
  338 				 this.unsigned);
  339 		}
  340 
  341 		/**
  342 		 * Alias for adding the negative of the argument to the
  343 		 * value.
  344 		 * @return The difference of the values.
  345 		 */
  346 		sub(tosub: Long|number): Long
  347 		{
  348 			const v: Long = !Long.isLong(tosub) ?
  349 				Long.fromNumber(<number>tosub) : <Long>tosub;
  350 			return this.add(v.neg());
  351 		};
  352 
  353 		/**
  354 		 * Add the argument to the value.
  355 		 * @return The addition of the values.
  356 		 */
  357 		add(toadd: Long|number): Long
  358 		{
  359 			const v: Long = !Long.isLong(toadd) ?
  360 				Long.fromNumber(<number>toadd) : 
  361 				<Long>toadd;
  362 
  363 			// Divide each number into 4 chunks of 16 bits,
  364 			// and then sum the chunks.
  365 
  366 			const a48: number = this.high >>> 16;
  367 			const a32: number = this.high & 0xFFFF;
  368 			const a16: number = this.low >>> 16;
  369 			const a00: number = this.low & 0xFFFF;
  370 
  371 			const b48: number = v.high >>> 16;
  372 			const b32: number = v.high & 0xFFFF;
  373 			const b16: number = v.low >>> 16;
  374 			const b00: number = v.low & 0xFFFF;
  375 
  376 			let c48: number = 0;
  377 			let c32: number = 0;
  378 			let c16: number = 0;
  379 			let c00: number = 0;
  380 
  381 			c00 += a00 + b00;
  382 			c16 += c00 >>> 16;
  383 			c00 &= 0xFFFF;
  384 			c16 += a16 + b16;
  385 			c32 += c16 >>> 16;
  386 			c16 &= 0xFFFF;
  387 			c32 += a32 + b32;
  388 			c48 += c32 >>> 16;
  389 			c32 &= 0xFFFF;
  390 			c48 += a48 + b48;
  391 			c48 &= 0xFFFF;
  392 
  393 			return new Long
  394 				((c16 << 16) | c00, (c48 << 16) | c32,
  395 				 this.unsigned);
  396 		}
  397 
  398 		/**
  399 		 * Attempt to convert from a Long, number, or string.  Failure
  400 		 * to convert, whether by syntax, not being defined, or null,
  401 		 * will return null.
  402 		 * @return The value or null on failure.
  403 		 */
  404 		static fromValue(val: any, unsigned?: boolean): Long|null
  405 		{
  406 			if (typeof val === 'undefined')
  407 				return null;
  408 			if (typeof val === 'number')
  409 				return Long.fromNumber
  410 					(<number>val, unsigned);
  411 			if (typeof val === 'string')
  412 				return Long.fromString
  413 					(<string>val, unsigned);
  414 			if (Long.isLong(val))
  415 				return <Long>val;
  416 			return null;
  417 		}
  418 
  419 		/**
  420 		 * Like fromValue(), except passing through on undefined values.
  421 		 * @return The value, null on failure, or undefined if not
  422 		 * defined.
  423 		 */
  424 		static fromValueUndef(val: any, unsigned?: boolean): Long|null|undefined
  425 		{
  426 			if (typeof val === 'undefined')
  427 				return undefined;
  428 			return Long.fromValue(val);
  429 		}
  430 
  431 		/**
  432 		 * Convert from a number to the Long representation of the
  433 		 * value.  If NaN, returns zero or unsigned zero as applicable.
  434 		 * If negative and wanting unsigned, bound at zero.  Otherwise
  435 		 * bound to a 64-bit integer size.
  436 		 * @return The value.
  437 		 */
  438 		static fromNumber(value: number, unsigned?: boolean): Long
  439 		{
  440 			const usgn: boolean =
  441 				(typeof unsigned === 'undefined') ?
  442 				false : unsigned;
  443 
  444 			if (isNaN(value))
  445 				return usgn ? Long.UZERO : Long.ZERO;
  446 
  447 			if (usgn) {
  448 				if (value < 0)
  449 					return Long.UZERO;
  450 				if (value >= Long.TWO_PWR_64_DBL)
  451 					return Long.MAX_UNSIGNED_VALUE;
  452 			} else {
  453 				if (value <= -Long.TWO_PWR_63_DBL)
  454 					return Long.MIN_VALUE;
  455 				if (value + 1 >= Long.TWO_PWR_63_DBL)
  456 					return Long.MAX_VALUE;
  457 			}
  458 
  459 			if (value < 0)
  460 				return Long.fromNumber
  461 					(-value, unsigned).neg();
  462 
  463 			return new Long
  464 				((value % Long.TWO_PWR_32_DBL) | 0, 
  465 				 (value / Long.TWO_PWR_32_DBL) | 0, 
  466 				 unsigned);
  467 		}
  468 
  469 		/**
  470 		 * Like fromString(), except returning failed conversions as a
  471 		 * zero value.
  472 		 * @return The value.
  473 		 */
  474 		static fromStringZero(str: string, unsigned?: boolean): Long
  475 		{
  476 			const val: Long|null = Long.fromString(str, unsigned);
  477 			return val === null ? Long.ZERO : val;
  478 		}
  479 
  480 		/**
  481 		 * Convert from a string representation of a number to a Long.
  482 		 * The string may have an optional leading "-" followed by
  483 		 * digits.  This does not accept NaN, Infinity, or other
  484 		 * symbols.
  485 		 * @return The value or null on failure.
  486 		 */
  487 		static fromString(str: string, unsigned?: boolean): Long | null
  488 		{
  489 			const usgn: boolean =
  490 				(typeof unsigned === 'undefined') ?
  491 				false : unsigned;
  492 			const hyph: number = str.indexOf('-');
  493 			const radixToPower: Long = Long.TEN_TO_EIGHT;
  494 			let result: Long = Long.ZERO;
  495 
  496 			if (str.length === 0 || hyph > 0 ||
  497 			    str === 'NaN' || str === 'Infinity' || 
  498 			    str === '+Infinity' || str === '-Infinity')
  499 				return null;
  500 
  501 			if (hyph === 0) {
  502 				const nresult: Long|null = 
  503 					Long.fromString
  504 					(str.substring(1), usgn);
  505 				if (nresult === null)
  506 					return null;
  507 				return nresult.neg();
  508 			}
  509 
  510 			if (!str.match(/^[0-9]+$/))
  511 				return null;
  512 
  513 			// Do several (8) digits each time through the
  514 			// loop, so as to  minimize the calls to the
  515 			// very expensive emulated div.
  516 
  517 			for (let i: number = 0; i < str.length; i += 8) {
  518 				const size: number = 
  519 					Math.min(8, str.length - i);
  520 				const value: number = 
  521 					parseInt(str.substring(i, i + size), 10);
  522 				if (isNaN(value))
  523 					return null;
  524 				if (size < 8) {
  525 					const power: Long = 
  526 						Long.fromNumber
  527 						(Math.pow(10, size));
  528 					result = result.mul(power).add
  529 						(Long.fromNumber(value));
  530 				} else {
  531 					result = result.mul
  532 						(radixToPower);
  533 					result = result.add
  534 						(Long.fromNumber(value));
  535 				}
  536 			}
  537 			return new Long(result.low, result.high, usgn);
  538 		}
  539 	}
  540 
  541 	/**
  542 	 * Labels ("jslabel" in ort(5)) may have multiple languages.
  543 	 * This maps a language name to a translated string.
  544 	 */
  545 	interface langmap { [lang: string]: string };
  546 
  547 	/**
  548 	 * Resolve a set of translated strings into a single one
  549 	 * depending upon the current language.
  550 	 * @param vals All translations of a given word.
  551 	 * @return The word in the current language (or the default)
  552 	 * or an empty string on failure.
  553 	 * @internal
  554 	 */
  555 	function _strlang(vals: langmap): string
  556 	{
  557 		const lang: string|null = 
  558 			document.documentElement.lang;
  559 
  560 		if (lang !== null && lang in vals)
  561 			return vals[lang];
  562 		else if ('_default' in vals)
  563 			return vals['_default'];
  564 		else
  565 			return '';
  566 	}
  567 
  568 	/**
  569 	 * Language replacement conditional upon the label (**jslabel**
  570 	 * in the configuration).  Like {@link _replcl} with inclusion
  571 	 * set to false.
  572 	 * @param e The root of the DOM tree in which we query for 
  573 	 * elements to fill into.
  574 	 * @param name The class name we search for within the root (not 
  575 	 * inclusive).
  576 	 * @param vals All possible translations.
  577 	 * @internal
  578 	 */
  579 	function _replcllang(e: HTMLElement, name:string,
  580 		vals: langmap): void
  581 	{
  582 		_replcl(e, name, _strlang(vals), false);
  583 	}
  584 
  585 	/**
  586 	 * Language replacement conditional upon the label (**jslabel**
  587 	 * in the configuration). Like {@link _repl}.
  588 	 * @param e The root of the DOM tree in which we query for 
  589 	 * elements to fill into.
  590 	 * @param vals All possible translations.
  591 	 * @internal
  592 	 */
  593 	function _repllang(e: HTMLElement, vals: langmap): void
  594 	{
  595 		_repl(e, _strlang(vals));
  596 	}
  597 
  598 	/**
  599 	 * Set the attribute of an element.
  600 	 * @param e The element whose attribute to set.
  601 	 * @param attr The attribute name.
  602 	 * @param text The attribute value.
  603 	 * @internal
  604 	 */
  605 	function _attr(e: HTMLElement, attr: string, text: string): void
  606 	{
  607 		e.setAttribute(attr, text);
  608 	}
  609 
  610 	/**
  611 	 * Set attributes for all elements matching a class.
  612 	 * @internal
  613 	 */
  614 	function _attrcl(e: HTMLElement, attr: string,
  615 		name: string, text: string, inc: boolean): void
  616 	{
  617 		let i: number;
  618 		const list: HTMLElement[] =
  619 			_elemList(e, name, inc);
  620 
  621 		for (i = 0; i < list.length; i++)
  622 			_attr(list[i], attr, text);
  623 	}
  624 
  625 	/**
  626 	 * Get all elements beneath (possibly including) a root matching
  627 	 * the given class.
  628 	 * @internal
  629 	 */
  630 	function _elemList(e: HTMLElement|null,
  631 		cls: string, inc: boolean): HTMLElement[]
  632 	{
  633 		let list: HTMLCollectionOf<Element>;
  634 		let i: number;
  635 		const a: HTMLElement[] = [];
  636 
  637 		if (e === null)
  638 			return a;
  639 		list = e.getElementsByClassName(cls);
  640 		for (i = 0; i < list.length; i++)
  641 			a.push(<HTMLElement>list[i]);
  642 		if (inc && e.classList.contains(cls))
  643 			a.push(e);
  644 		return a;
  645 	}
  646 
  647 	/**
  648 	 * Replace all children of an element with text.
  649 	 * @internal
  650 	 */
  651 	function _repl(e: HTMLElement, text: string): void
  652 	{
  653 		while (e.firstChild)
  654 			e.removeChild(e.firstChild);
  655 		e.appendChild(document.createTextNode(text));
  656 	}
  657 
  658 	/**
  659 	 * Replace children of elements matching class with text.
  660 	 * @internal
  661 	 */
  662 	function _replcl(e: HTMLElement, name: string,
  663 		text: string, inc: boolean): void
  664 	{
  665 		let i: number;
  666 		const list: HTMLElement[] = _elemList(e, name, inc);
  667 
  668 		for (i = 0; i < list.length; i++)
  669 			_repl(list[i], text);
  670 	}
  671 
  672 	/**
  673 	 * Add class to class list if it doesn't exist.
  674 	 * @internal
  675 	 */
  676 	function _classadd(e: HTMLElement, name: string): HTMLElement
  677 	{
  678 		if (!e.classList.contains(name))
  679 			e.classList.add(name);
  680 		return(e);
  681 	}
  682 
  683 	/**
  684 	 * Add class if doesn't exist to all elements with class name.
  685 	 * @internal
  686 	 */
  687 	function _classaddcl(e: HTMLElement, name: string,
  688 		cls: string, inc: boolean): void
  689 	{
  690 		let i: number;
  691 		const list: HTMLElement[] = _elemList(e, name, inc);
  692 
  693 		for (i = 0; i < list.length; i++)
  694 			_classadd(list[i], cls);
  695 	}
  696 
  697 	/**
  698 	 * "Hide" element by adding *hide* class.
  699 	 * @internal
  700 	 */
  701 	function _hide(e: HTMLElement): HTMLElement
  702 	{
  703 		if (!e.classList.contains('hide'))
  704 			e.classList.add('hide');
  705 		return e;
  706 	}
  707 
  708 	/**
  709 	 * "Hide" all elements matching class by adding *hide* class.
  710 	 * @internal
  711 	 */
  712 	function _hidecl(e: HTMLElement, name: string, inc: boolean): void
  713 	{
  714 		let i: number;
  715 		const list: HTMLElement[] = _elemList(e, name, inc);
  716 
  717 		for (i = 0; i < list.length; i++)
  718 			_hide(list[i]);
  719 	}
  720 
  721 	/**
  722 	 * "Show" element by removing *hide* class.
  723 	 * @internal
  724 	 */
  725 	function _show(e: HTMLElement): HTMLElement
  726 	{
  727 		if (e.classList.contains('hide'))
  728 			e.classList.remove('hide');
  729 		return e;
  730 	}
  731 
  732 	/**
  733 	 * "Show" all elements matching class by removing *hide* class.
  734 	 * @internal
  735 	 */
  736 	function _showcl(e: HTMLElement, name: string, inc: boolean): void
  737 	{
  738 		let i: number;
  739 		const list: HTMLElement[] = _elemList(e, name, inc);
  740 
  741 		for (i = 0; i < list.length; i++)
  742 			_show(list[i]);
  743 	}
  744 
  745 	/**
  746 	 * Check input elements (that is, set the attribute `checked` to
  747 	 * the value `checked`) for all elements of class
  748 	 * `fname-value-checked` whose value matches the given.  The
  749 	 * checked status is removed for each item scanned.
  750 	 * A null value never matches.
  751 	 * @param e Root of tree scanned for elements.
  752 	 * @param fname Structure name, '-', field name.
  753 	 * @param val The value to test for.
  754 	 * @param inc Include root in scanning for elements.
  755 	 * @internal
  756 	 */
  757 	function _fillValueChecked(e: HTMLElement, fname: string,
  758 		val: number|string|null, inc: boolean): void
  759 	{
  760 		let i: number;
  761 		const list: HTMLElement[] = _elemList
  762 			(e, fname + '-value-checked', inc);
  763 
  764 		for (i = 0; i < list.length; i++) {
  765 			const elem: HTMLInputElement =
  766 				<HTMLInputElement>list[i];
  767 			const attrval: string|null = elem.value;
  768 			elem.removeAttribute('checked');
  769 			if (val === null || attrval === null)
  770 				continue;
  771 			if (val.toString() === attrval)
  772 				elem.setAttribute('checked', 'checked');
  773 		}
  774 	}
  775 
  776 	/**
  777 	 * Take all `<option>` elements under the root (non-inclusive)
  778 	 * and sets or unsets the `selected` attribute depending upon
  779 	 * whether it matches the object's value.
  780 	 * A null value never matches.
  781 	 * @param e Root of tree scanned for elements.
  782 	 * @param val The value to test for.
  783 	 * @internal
  784 	 */
  785 	function _fillValueSelect(e: HTMLElement,
  786 		val: number|string|null): void
  787 	{
  788 		let i: number;
  789 		const list: HTMLCollectionOf<HTMLElement> = 
  790 			e.getElementsByTagName('option');
  791 
  792 		for (i = 0; i < list.length; i++) {
  793 			const elem: HTMLOptionElement =
  794 				<HTMLOptionElement>list[i];
  795 			const attrval: string|null = elem.value;
  796 			elem.removeAttribute('selected');
  797 			if (val === null || attrval === null)
  798 				continue;
  799 			if (val.toString() === attrval)
  800 				elem.setAttribute('selected', 'selected');
  801 		}
  802 	}
  803 
  804 	/**
  805 	 * Fill in ISO-8601 dates.
  806 	 * Does nothing for null or unexported date.
  807 	 * @param e Root of tree scanned for elements.
  808 	 * @param fname Structure name, '-', field name.
  809 	 * @param val Epoch date itself.
  810 	 * @param inc Include root in scanning for elements.
  811 	 * @internal
  812 	 */
  813 	function _fillDateValue(e: HTMLElement, fname: string,
  814 		val: string|number|null|undefined, inc: boolean): void
  815 	{
  816 		const v: Long|null = Long.fromValue(val);
  817 		const d: Date = new Date();
  818 
  819 		if (v === null)
  820 			return;
  821 
  822 		d.setTime(v.toNumber() * 1000);
  823 
  824 		/* Make sure to zero-pad the digits. */
  825 
  826 		const year: number = d.getFullYear();
  827 		const mo: number = d.getMonth() + 1;
  828 		const day: number = d.getDate();
  829 		const full: string = year + '-' +
  830 			(mo < 10 ? '0' : '') + mo + '-' +
  831 			(day < 10 ? '0' : '') + day;
  832 
  833 		_attrcl(e, 'value', fname + '-date-value', full, inc);
  834 		_replcl(e, fname + '-date-text', full, inc);
  835 	}
  836 
  837 	/**
  838 	 * Check input elements (that is, set the attribute `checked` to
  839 	 * the value `checked`) for elements with class 
  840 	 * `fname-value-checked` whose non-null, numeric value as a bit index
  841 	 * is set in the bit-field given as input.
  842 	 * A null value never matches.
  843 	 * @param e Root of tree scanned for elements.
  844 	 * @param fname Structure name, '-', field name.
  845 	 * @param val Bit-field to test for.
  846 	 * @param inc Include root in scanning for elements.
  847 	 * @internal
  848 	 */
  849 	function _fillBitsChecked(e: HTMLElement, fname: string,
  850 		 val: string|number|null|undefined, inc: boolean): void
  851 	{
  852 		let i: number;
  853 		let v: number;
  854 		const lval: Long|null|undefined = 
  855 			Long.fromValueUndef(val);
  856 		const list: HTMLElement[] = _elemList
  857 			(e, fname + '-bits-checked', inc);
  858 
  859 		if (typeof lval === 'undefined')
  860 			return;
  861 
  862 		for (i = 0; i < list.length; i++) {
  863 			const elem: HTMLInputElement =
  864 				<HTMLInputElement>list[i];
  865 			const attrval: string|null = elem.value;
  866 			elem.removeAttribute('checked');
  867 			if (lval === null || attrval === null)
  868 				continue;
  869 
  870 			/*
  871 			 * This would be better served with
  872 			 * Number.isInteger(), but we don't want to
  873 			 * assume ES6.
  874 			 */
  875 
  876 			v = Number(attrval);
  877 			if (isNaN(v))
  878 				continue;
  879 			if (!(isFinite(v) && Math.floor(v) === v))
  880 				continue;
  881 			if (v < 0 || v > 64)
  882 				continue;
  883 
  884 			if ((v === 0 && lval.isZero()) ||
  885 			    !Long.ONE.shl(v - 1).and(lval).isZero()) {
  886 				elem.setAttribute('checked', 'checked');
  887 			}
  888 		}
  889 	}
  890 
  891 	/**
  892 	 * Fill a structure field.  This first does the has/no class
  893 	 * setting for null values, then optionally returns if null
  894 	 * (running the custom fields first), otherwise the generic
  895 	 * text/value/etc fields, then finally the custom fields.
  896 	 * @param e Root of the DOM tree filled into.
  897 	 * @param strct Name of the structure filling in.
  898 	 * @param name The name of the field.
  899 	 * @param custom Custom callback functions.
  900 	 * @param obj The data itself.
  901 	 * @param inc Whether to include the root element in looking
  902 	 * for elements to fill. Nested structures are always filled 
  903 	 * non-inclusively.
  904 	 * @param cannull Whether the data may be null.
  905 	 * @param sub If the data object is a nested structure
  906 	 * interface, the allocated class of that interface.
  907 	 * @internal
  908 	 */
  909 	function _fillField(e: HTMLElement, strct: string, name: string,
  910 		custom: DataCallbacks|null, obj: any, inc: boolean,
  911 		cannull: boolean, sub: any): void
  912 	{
  913 		let i: number;
  914 		const fname: string = strct + '-' + name;
  915 
  916 		/* Don't do anything if we're not defined. */
  917 
  918 		if (typeof obj === 'undefined')
  919 			return;
  920 
  921 		/* First handle our has/no null situation. */
  922 
  923 		if (cannull) {
  924 			if (obj === null) {
  925 				_hidecl(e, strct + '-has-' + name, inc);
  926 				_showcl(e, strct + '-no-' + name, inc);
  927 			} else {
  928 				_showcl(e, strct + '-has-' + name, inc);
  929 				_hidecl(e, strct + '-no-' + name, inc);
  930 			}
  931 		}
  932 
  933 		/* Don't process null values that can be null. */
  934 
  935 		if (cannull && obj === null) {
  936 			if (custom !== null && fname in custom) {
  937 				if (custom[fname] instanceof Array) {
  938 					for (i = 0; i < custom[fname].length; i++)
  939 						custom[fname][i](e, fname, null);
  940 				} else
  941 					custom[fname](e, fname, null);
  942 			}
  943 			return;
  944 		}
  945 
  946 		/* 
  947 		 * Non-null non-structs.
  948 		 * Note that "sub" is never undefined because that would
  949 		 * otherwise be caught in the "typeof obj" guard above.
  950 		 */
  951 
  952 		if (sub !== null) {
  953 			const list: HTMLElement[] = 
  954 				_elemList(e, fname + '-obj', inc);
  955 			for (i = 0; i < list.length; i++)
  956 				sub.fillInner(list[i], custom);
  957 		} else {
  958 			const list: HTMLElement[] = 
  959 				_elemList(e, fname + '-enum-select', inc);
  960 			for (i = 0; i < list.length; i++)
  961 				_fillValueSelect(list[i], obj);
  962 			_replcl(e, fname + '-text', obj, inc);
  963 			_attrcl(e, 'value', fname + '-value', obj, inc);
  964 			_fillValueChecked(e, fname, obj, inc);
  965 		}
  966 
  967 		/* Lastly, handle the custom callback. */
  968 
  969 		if (custom !== null &&
  970 		    typeof custom[fname] !== 'undefined') {
  971 			if (custom[fname] instanceof Array) {
  972 				for (i = 0; i < custom[fname].length; i++)
  973 					custom[fname][i](e, fname, obj);
  974 			} else
  975 				custom[fname](e, fname, obj);
  976 		}
  977 	}
  978 
  979 	export type DCbstring = (e: HTMLElement,
  980 		name: string, val: string) => void;
  981 	export type DCbstringNull = (e: HTMLElement,
  982 		name: string, val: string|null) => void;
  983 	export type DCbinteger = (e: HTMLElement,
  984 		name: string, val: string|number) => void;
  985 	export type DCbintegerNull = (e: HTMLElement,
  986 		name: string, val: string|number|null) => void;
  987 	export type DCbnumber = (e: HTMLElement,
  988 		name: string, val: number) => void;
  989 	export type DCbnumberNull = (e: HTMLElement,
  990 		name: string, val: number|null) => void;
  991 	export type DCbStructcompany = (e: HTMLElement,
  992 		name: string, val: companyData|null) => void;
  993 	export type DCbStructuser = (e: HTMLElement,
  994 		name: string, val: userData|null) => void;
  995 	export type DCbStructsession = (e: HTMLElement,
  996 		name: string, val: sessionData|null) => void;
  997 
  998 	/**
  999 	 * All possible custom callbacks for this ort configuration.
 1000 	 */
 1001 	export interface DataCallbacks
 1002 	{
 1003 		[key: string]: any;
 1004 		'company'?: DCbStructcompany|DCbStructcompany[];
 1005 		'company-name'?: DCbstring|DCbstring[];
 1006 		'company-id'?: DCbinteger|DCbinteger[];
 1007 		'company-somenum'?: DCbintegerNull|DCbintegerNull[];
 1008 		'user'?: DCbStructuser|DCbStructuser[];
 1009 		'user-company'?: DCbStructcompany|DCbStructcompany[];
 1010 		'user-cid'?: DCbinteger|DCbinteger[];
 1011 		'user-sex'?: DCbinteger|DCbinteger[];
 1012 		'user-email'?: DCbstring|DCbstring[];
 1013 		'user-image'?: DCbstringNull|DCbstringNull[];
 1014 		'user-name'?: DCbstring|DCbstring[];
 1015 		'user-uid'?: DCbinteger|DCbinteger[];
 1016 		'session'?: DCbStructsession|DCbStructsession[];
 1017 		'session-user'?: DCbStructuser|DCbStructuser[];
 1018 		'session-userid'?: DCbinteger|DCbinteger[];
 1019 		'session-token'?: DCbinteger|DCbinteger[];
 1020 		'session-mtime'?: DCbinteger|DCbinteger[];
 1021 		'session-id'?: DCbinteger|DCbinteger[];
 1022 	}
 1023 
 1024 	/**
 1025 	 * Controlling organisation.
 1026 	 */
 1027 	export interface companyData
 1028 	{
 1029 		/**
 1030 		 * Name of the organisation.
 1031 		 */
 1032 		name: string;
 1033 		id: string|number;
 1034 		/**
 1035 		 * Simply a check for null values.
 1036 		 */
 1037 		somenum: string|number;
 1038 	}
 1039 
 1040 	/**
 1041 	 * A regular user.
 1042 	 */
 1043 	export interface userData
 1044 	{
 1045 		/**
 1046 		 * This struct will be filled in from an inner join
 1047 		 *     on the "cid" variable.
 1048 		 */
 1049 		company: companyData;
 1050 		/**
 1051 		 * A foreign key reference.
 1052 		 */
 1053 		cid: string|number;
 1054 		/**
 1055 		 * User's birth sex.
 1056 		 */
 1057 		sex: string|number;
 1058 		/**
 1059 		 * Unique e-mail address.
 1060 		 */
 1061 		email: string;
 1062 		/**
 1063 		 * A PNG image or something.
 1064 		 */
 1065 		image: string;
 1066 		/**
 1067 		 * User's full name.
 1068 		 */
 1069 		name: string;
 1070 		uid: string|number;
 1071 	}
 1072 
 1073 	/**
 1074 	 * Authenticated session.
 1075 	 */
 1076 	export interface sessionData
 1077 	{
 1078 		user: userData;
 1079 		/**
 1080 		 * Associated user.
 1081 		 */
 1082 		userid: string|number;
 1083 		/**
 1084 		 * Random cookie.
 1085 		 */
 1086 		token: string|number;
 1087 		mtime: string|number;
 1088 		id: string|number;
 1089 	}
 1090 
 1091 	/**
 1092 	 * Writes {@link companyData} into a DOM tree.
 1093 	 */
 1094 	export class company {
 1095 		readonly obj: companyData|companyData[];
 1096 		/**
 1097 		 * @param obj The object(s) to write.
 1098 		 */
 1099 		constructor(o: companyData|companyData[])
 1100 		{
 1101 			this.obj = o;
 1102 		}
 1103 
 1104 		/**
 1105 		 * Writes {@link companyData} into the given element. If 
 1106 		 * constructed with an array, the first element is used.  
 1107 		 * Elements within (and including) the element having the 
 1108 		 * following classes are manipulated as follows:
 1109 		 * 
 1110 		 * - `company-name-enum-select`: sets or unsets the `selected` 
 1111 		 * attribute for non-inclusive descendent `<option>` elements 
 1112 		 * depending on whether the value matches
 1113 		 * - `company-name-value-checked`: sets or unsets the `checked` 
 1114 		 * attribute depending on whether the value matches
 1115 		 * - `company-name-text`: replace contents with **name** data
 1116 		 * - `company-name-value`: replace `value` attribute with 
 1117 		 * **name** data
 1118 		 * - `company-id-enum-select`: sets or unsets the `selected` 
 1119 		 * attribute for non-inclusive descendent `<option>` elements 
 1120 		 * depending on whether the value matches
 1121 		 * - `company-id-value-checked`: sets or unsets the `checked` 
 1122 		 * attribute depending on whether the value matches
 1123 		 * - `company-id-text`: replace contents with **id** data
 1124 		 * - `company-id-value`: replace `value` attribute with **id** 
 1125 		 * data
 1126 		 * - `company-has-somenum`: *hide* class removed if value is not 
 1127 		 * null, otherwise it is added
 1128 		 * - `company-no-somenum`: *hide* class added if value is not 
 1129 		 * null, otherwise it is removed
 1130 		 * - `company-somenum-enum-select`: sets or unsets the `selected` 
 1131 		 * attribute for non-inclusive descendent `<option>` elements 
 1132 		 * depending on whether the value matches (if non-null)
 1133 		 * - `company-somenum-value-checked`: sets or unsets the 
 1134 		 * `checked` attribute depending on whether the value matches (if 
 1135 		 * non-null)
 1136 		 * - `company-somenum-text`: replace contents with **somenum** 
 1137 		 * data (if non-null)
 1138 		 * - `company-somenum-value`: replace `value` attribute with 
 1139 		 * **somenum** data (if non-null)
 1140 		 * 
 1141 		 * @param e The DOM element.
 1142 		 * @param custom The dictionary of functions keyed by structure 
 1143 		 * and field name (e.g., *foo** structure, **bar** field would be 
 1144 		 * `foo-bar`). The value is a function for custom handling that 
 1145 		 * accepts the 'e' value, the name of the structure-field, and 
 1146 		 * the value of the structure and field. You may also specify an 
 1147 		 * array of functions instead of a singleton. These callbacks are 
 1148 		 * invoked *after* the generic classes are filled.
 1149 		 */
 1150 		fill(e: HTMLElement|null, custom?: DataCallbacks|null): void
 1151 		{
 1152 			if (e !== null)
 1153 				this._fill(e, this.obj, true, custom);
 1154 		}
 1155 
 1156 		/**
 1157 		 * Like {@link fill} but not including the passed-in element.
 1158 		 * @param e The DOM element.
 1159 		 * @param custom Custom handler dictionary (see {@link fill} for 
 1160 		 * details).
 1161 		 */
 1162 		fillInner(e: HTMLElement|null, custom?: DataCallbacks|null): 
 1163 			void
 1164 		{
 1165 			if (e !== null)
 1166 				this._fill(e, this.obj, false, custom);
 1167 		}
 1168 
 1169 		/**
 1170 		 * Like {@link fill} but instead of accepting a single element to 
 1171 		 * fill, filling into all elements (inclusive) matching the given 
 1172 		 * class name beneath (inclusive) the element.
 1173 		 * @param e The DOM element.
 1174 		 * @param name Name of the class to fill.
 1175 		 * @param custom Custom handler dictionary (see {@link fill} for 
 1176 		 * details).
 1177 		 */
 1178 		fillByClass(e: HTMLElement|null, name: string, 
 1179 			custom?: DataCallbacks|null): void
 1180 		{
 1181 			if (e !== null)
 1182 				this._fillByClass(e, name, true, custom);
 1183 		}
 1184 
 1185 		/**
 1186 		 * Like {@link fillByClass} but not inclusive the root element 
 1187 		 * and class matches.
 1188 		 * @param e The DOM element.
 1189 		 * @param name Name of the class to fill.
 1190 		 * @param custom Custom handler dictionary (see {@link fill} for 
 1191 		 * details).
 1192 		 */
 1193 		fillInnerByClass(e: HTMLElement|null, name: string, 
 1194 			custom?: DataCallbacks|null): void
 1195 		{
 1196 			if (e !== null)
 1197 				this._fillByClass(e, name, false, custom);
 1198 		}
 1199 
 1200 		private _fill(e: HTMLElement, obj: companyData|companyData[], 
 1201 			inc: boolean, custom?: DataCallbacks|null): 
 1202 			void
 1203 		{
 1204 			if (obj instanceof Array && obj.length === 0)
 1205 				return;
 1206 			const o: companyData =
 1207 				(obj instanceof Array) ? obj[0] : obj;
 1208 			if (typeof custom === 'undefined')
 1209 				custom = null;
 1210 			_fillField(e, 'company', 'name', custom,
 1211 				o.name, inc, false,null);
 1212 			_fillField(e, 'company', 'id', custom, o.id, inc,
 1213 				false,null);
 1214 			_fillField(e, 'company', 'somenum', custom,
 1215 				o.somenum, inc, true,null);
 1216 			if (custom !== null &&
 1217 			    typeof custom['company'] !== 'undefined') {
 1218 				if (custom['company'] instanceof Array) {
 1219 					let i: number;
 1220 					for (i = 0; i < custom['company'].length; i++)
 1221 						custom['company'][i](e, 'company', o);
 1222 				} else
 1223 					custom['company'](e, 'company', o);
 1224 			}
 1225 		}
 1226 
 1227 		private _fillByClass(e: HTMLElement, name: string, inc: boolean, 
 1228 			custom?: DataCallbacks|null): void
 1229 		{
 1230 			let i: number;
 1231 			const list: HTMLElement[] = 
 1232 				_elemList(e, name, inc);
 1233 			for (i = 0; i < list.length; i++)
 1234 				this._fill(list[i], this.obj, inc, custom);
 1235 		}
 1236 
 1237 		/**
 1238 		 * Like {@link fillArray}, but hiding an element if the array is 
 1239 		 * empty or null.
 1240 		 * @param e The DOM element.
 1241 		 * @param tohide DOM element to hide.
 1242 		 * @param o The array (or object) to fill.
 1243 		 * @param custom Custom handler dictionary (see {@link fill}).
 1244 		 */
 1245 		fillArrayOrHide(e: HTMLElement|null, tohide: HTMLElement|null, 
 1246 			custom?: DataCallbacks|null): void
 1247 		{
 1248 			let len: number;
 1249 			if (null === this.obj)
 1250 				len = 0;
 1251 			else if (this.obj instanceof Array)
 1252 				len = this.obj.length;
 1253 			else
 1254 				len = 1;
 1255 			if (null !== e)
 1256 				_hide(e);
 1257 			if (null !== tohide)
 1258 				_show(tohide);
 1259 			this.fillArray(e, custom);
 1260 			if (null !== tohide && 0 === len)
 1261 				_hide(tohide);
 1262 		}
 1263 
 1264 		/**
 1265 		 * Like {@link fillArray}, but showing an element if the array is 
 1266 		 * empty or null.
 1267 		 * @param e The DOM element.
 1268 		 * @param toshow The DOM element to show.
 1269 		 * @param o The array or object to fill.
 1270 		 * @param custom Custom handler dictionary (see {@link fill}).
 1271 		 */
 1272 		fillArrayOrShow(e: HTMLElement|null, toshow: HTMLElement|null, 
 1273 			custom?: DataCallbacks|null): void
 1274 		{
 1275 			let len: number;
 1276 			if (null === this.obj)
 1277 				len = 0;
 1278 			else if (this.obj instanceof Array)
 1279 				len = this.obj.length;
 1280 			else
 1281 				len = 1;
 1282 			if (null !== e)
 1283 				_hide(e);
 1284 			if (null !== toshow)
 1285 				_hide(toshow);
 1286 			this.fillArray(e, custom);
 1287 			if (null !== toshow && 0 === len)
 1288 				_show(toshow);
 1289 		}
 1290 
 1291 		/**
 1292 		 * Like {@link fill} but for an array. If the data is not an 
 1293 		 * array, it is remapped as an array of one. This will save the 
 1294 		 * first element within 'e', remove all children of 'e', then 
 1295 		 * repeatedly clone the saved element and re-append it, filling 
 1296 		 * in the cloned subtree with the array (inclusive of the subtree 
 1297 		 * root). If the input array is empty or null, 'e' is hidden by 
 1298 		 * using the *hide* class. Otherwise, the *hide* class is 
 1299 		 * removed.
 1300 		 * @param e The DOM element.
 1301 		 * @param custom Custom handler dictionary (see {@link fill}).
 1302 		 */
 1303 		fillArray(e: HTMLElement|null, custom?: DataCallbacks|null): 
 1304 			void
 1305 		{
 1306 			let i: number;
 1307 			const o: companyData[] =
 1308 				(this.obj instanceof Array) ?
 1309 				 this.obj : [this.obj];
 1310 
 1311 			if (e === null || e.children.length === 0)
 1312 				return;
 1313 			_hide(e);
 1314 			if (o.length === 0 || this.obj === null)
 1315 				return;
 1316 			_show(e);
 1317 
 1318 			const row: HTMLElement =
 1319 				<HTMLElement>e.children[0];
 1320 			while (e.firstChild !== null)
 1321 				e.removeChild(e.firstChild)
 1322 			for (i = 0; i < o.length; i++) {
 1323 				const cln: HTMLElement =
 1324 					<HTMLElement>row.cloneNode(true);
 1325 				e.appendChild(cln);
 1326 				this._fill(cln, o[i], true, custom);
 1327 			}
 1328 		}
 1329 
 1330 		/**
 1331 		 * Like {@link fillArray} but instead of accepting a single 
 1332 		 * element to fill, filling all elements by class name beneath 
 1333 		 * the given root (non-inclusive).
 1334 		 * @param e The DOM element.
 1335 		 * @param name Name of the class to fill.
 1336 		 * @param custom Custom handler dictionary (see {@link fill} for 
 1337 		 * details).
 1338 		 */
 1339 		fillArrayByClass(e: HTMLElement|null, name: string, 
 1340 			custom?: DataCallbacks|null): void
 1341 		{
 1342 			let i: number;
 1343 			const list: HTMLElement[] =
 1344 				_elemList(e, name, false);
 1345 			for (i = 0; i < list.length; i++)
 1346 				this.fillArray(list[i], custom);
 1347 		}
 1348 
 1349 	}
 1350 
 1351 	/**
 1352 	 * Writes {@link userData} into a DOM tree.
 1353 	 */
 1354 	export class user {
 1355 		readonly obj: userData|userData[];
 1356 		/**
 1357 		 * @param obj The object(s) to write.
 1358 		 */
 1359 		constructor(o: userData|userData[])
 1360 		{
 1361 			this.obj = o;
 1362 		}
 1363 
 1364 		/**
 1365 		 * Writes {@link userData} into the given element. If constructed 
 1366 		 * with an array, the first element is used.  Elements within 
 1367 		 * (and including) the element having the following classes are 
 1368 		 * manipulated as follows:
 1369 		 * 
 1370 		 * - `user-company-obj`: invoke {@link company#fillInner} with 
 1371 		 * **company** data
 1372 		 * - `user-cid-enum-select`: sets or unsets the `selected` 
 1373 		 * attribute for non-inclusive descendent `<option>` elements 
 1374 		 * depending on whether the value matches
 1375 		 * - `user-cid-value-checked`: sets or unsets the `checked` 
 1376 		 * attribute depending on whether the value matches
 1377 		 * - `user-cid-text`: replace contents with **cid** data
 1378 		 * - `user-cid-value`: replace `value` attribute with **cid** 
 1379 		 * data
 1380 		 * - `user-sex-enum-select`: sets or unsets the `selected` 
 1381 		 * attribute for non-inclusive descendent `<option>` elements 
 1382 		 * depending on whether the value matches
 1383 		 * - `user-sex-value-checked`: sets or unsets the `checked` 
 1384 		 * attribute depending on whether the value matches
 1385 		 * - `user-sex-text`: replace contents with **sex** data
 1386 		 * - `user-sex-value`: replace `value` attribute with **sex** 
 1387 		 * data
 1388 		 * - `user-email-enum-select`: sets or unsets the `selected` 
 1389 		 * attribute for non-inclusive descendent `<option>` elements 
 1390 		 * depending on whether the value matches
 1391 		 * - `user-email-value-checked`: sets or unsets the `checked` 
 1392 		 * attribute depending on whether the value matches
 1393 		 * - `user-email-text`: replace contents with **email** data
 1394 		 * - `user-email-value`: replace `value` attribute with **email** 
 1395 		 * data
 1396 		 * - `user-has-image`: *hide* class removed if value is not null, 
 1397 		 * otherwise it is added
 1398 		 * - `user-no-image`: *hide* class added if value is not null, 
 1399 		 * otherwise it is removed
 1400 		 * - `user-image-enum-select`: sets or unsets the `selected` 
 1401 		 * attribute for non-inclusive descendent `<option>` elements 
 1402 		 * depending on whether the value matches (if non-null) (the 
 1403 		 * base64 encoded value)
 1404 		 * - `user-image-value-checked`: sets or unsets the `checked` 
 1405 		 * attribute depending on whether the value matches (if non-null) 
 1406 		 * (the base64 encoded value)
 1407 		 * - `user-image-text`: replace contents with **image** data (if 
 1408 		 * non-null) (the base64 encoded value)
 1409 		 * - `user-image-value`: replace `value` attribute with **image** 
 1410 		 * data (if non-null) (the base64 encoded value)
 1411 		 * - `user-name-enum-select`: sets or unsets the `selected` 
 1412 		 * attribute for non-inclusive descendent `<option>` elements 
 1413 		 * depending on whether the value matches
 1414 		 * - `user-name-value-checked`: sets or unsets the `checked` 
 1415 		 * attribute depending on whether the value matches
 1416 		 * - `user-name-text`: replace contents with **name** data
 1417 		 * - `user-name-value`: replace `value` attribute with **name** 
 1418 		 * data
 1419 		 * - `user-uid-enum-select`: sets or unsets the `selected` 
 1420 		 * attribute for non-inclusive descendent `<option>` elements 
 1421 		 * depending on whether the value matches
 1422 		 * - `user-uid-value-checked`: sets or unsets the `checked` 
 1423 		 * attribute depending on whether the value matches
 1424 		 * - `user-uid-text`: replace contents with **uid** data
 1425 		 * - `user-uid-value`: replace `value` attribute with **uid** 
 1426 		 * data
 1427 		 * 
 1428 		 * @param e The DOM element.
 1429 		 * @param custom The dictionary of functions keyed by structure 
 1430 		 * and field name (e.g., *foo** structure, **bar** field would be 
 1431 		 * `foo-bar`). The value is a function for custom handling that 
 1432 		 * accepts the 'e' value, the name of the structure-field, and 
 1433 		 * the value of the structure and field. You may also specify an 
 1434 		 * array of functions instead of a singleton. These callbacks are 
 1435 		 * invoked *after* the generic classes are filled.
 1436 		 */
 1437 		fill(e: HTMLElement|null, custom?: DataCallbacks|null): void
 1438 		{
 1439 			if (e !== null)
 1440 				this._fill(e, this.obj, true, custom);
 1441 		}
 1442 
 1443 		/**
 1444 		 * Like {@link fill} but not including the passed-in element.
 1445 		 * @param e The DOM element.
 1446 		 * @param custom Custom handler dictionary (see {@link fill} for 
 1447 		 * details).
 1448 		 */
 1449 		fillInner(e: HTMLElement|null, custom?: DataCallbacks|null): 
 1450 			void
 1451 		{
 1452 			if (e !== null)
 1453 				this._fill(e, this.obj, false, custom);
 1454 		}
 1455 
 1456 		/**
 1457 		 * Like {@link fill} but instead of accepting a single element to 
 1458 		 * fill, filling into all elements (inclusive) matching the given 
 1459 		 * class name beneath (inclusive) the element.
 1460 		 * @param e The DOM element.
 1461 		 * @param name Name of the class to fill.
 1462 		 * @param custom Custom handler dictionary (see {@link fill} for 
 1463 		 * details).
 1464 		 */
 1465 		fillByClass(e: HTMLElement|null, name: string, 
 1466 			custom?: DataCallbacks|null): void
 1467 		{
 1468 			if (e !== null)
 1469 				this._fillByClass(e, name, true, custom);
 1470 		}
 1471 
 1472 		/**
 1473 		 * Like {@link fillByClass} but not inclusive the root element 
 1474 		 * and class matches.
 1475 		 * @param e The DOM element.
 1476 		 * @param name Name of the class to fill.
 1477 		 * @param custom Custom handler dictionary (see {@link fill} for 
 1478 		 * details).
 1479 		 */
 1480 		fillInnerByClass(e: HTMLElement|null, name: string, 
 1481 			custom?: DataCallbacks|null): void
 1482 		{
 1483 			if (e !== null)
 1484 				this._fillByClass(e, name, false, custom);
 1485 		}
 1486 
 1487 		private _fill(e: HTMLElement, obj: userData|userData[], 
 1488 			inc: boolean, custom?: DataCallbacks|null): 
 1489 			void
 1490 		{
 1491 			if (obj instanceof Array && obj.length === 0)
 1492 				return;
 1493 			const o: userData =
 1494 				(obj instanceof Array) ? obj[0] : obj;
 1495 			if (typeof custom === 'undefined')
 1496 				custom = null;
 1497 			_fillField(e, 'user', 'company', custom,
 1498 				o.company, inc, false,
 1499 				new company(o.company));
 1500 			_fillField(e, 'user', 'cid', custom, o.cid, inc,
 1501 				false,null);
 1502 			_fillField(e, 'user', 'sex', custom, o.sex, inc,
 1503 				false,null);
 1504 			_fillField(e, 'user', 'email', custom,
 1505 				o.email, inc, false,null);
 1506 			_fillField(e, 'user', 'image', custom,
 1507 				o.image, inc, true,null);
 1508 			_fillField(e, 'user', 'name', custom,
 1509 				o.name, inc, false,null);
 1510 			_fillField(e, 'user', 'uid', custom, o.uid, inc,
 1511 				false,null);
 1512 			if (custom !== null &&
 1513 			    typeof custom['user'] !== 'undefined') {
 1514 				if (custom['user'] instanceof Array) {
 1515 					let i: number;
 1516 					for (i = 0; i < custom['user'].length; i++)
 1517 						custom['user'][i](e, 'user', o);
 1518 				} else
 1519 					custom['user'](e, 'user', o);
 1520 			}
 1521 		}
 1522 
 1523 		private _fillByClass(e: HTMLElement, name: string, inc: boolean, 
 1524 			custom?: DataCallbacks|null): void
 1525 		{
 1526 			let i: number;
 1527 			const list: HTMLElement[] = 
 1528 				_elemList(e, name, inc);
 1529 			for (i = 0; i < list.length; i++)
 1530 				this._fill(list[i], this.obj, inc, custom);
 1531 		}
 1532 
 1533 		/**
 1534 		 * Like {@link fillArray}, but hiding an element if the array is 
 1535 		 * empty or null.
 1536 		 * @param e The DOM element.
 1537 		 * @param tohide DOM element to hide.
 1538 		 * @param o The array (or object) to fill.
 1539 		 * @param custom Custom handler dictionary (see {@link fill}).
 1540 		 */
 1541 		fillArrayOrHide(e: HTMLElement|null, tohide: HTMLElement|null, 
 1542 			custom?: DataCallbacks|null): void
 1543 		{
 1544 			let len: number;
 1545 			if (null === this.obj)
 1546 				len = 0;
 1547 			else if (this.obj instanceof Array)
 1548 				len = this.obj.length;
 1549 			else
 1550 				len = 1;
 1551 			if (null !== e)
 1552 				_hide(e);
 1553 			if (null !== tohide)
 1554 				_show(tohide);
 1555 			this.fillArray(e, custom);
 1556 			if (null !== tohide && 0 === len)
 1557 				_hide(tohide);
 1558 		}
 1559 
 1560 		/**
 1561 		 * Like {@link fillArray}, but showing an element if the array is 
 1562 		 * empty or null.
 1563 		 * @param e The DOM element.
 1564 		 * @param toshow The DOM element to show.
 1565 		 * @param o The array or object to fill.
 1566 		 * @param custom Custom handler dictionary (see {@link fill}).
 1567 		 */
 1568 		fillArrayOrShow(e: HTMLElement|null, toshow: HTMLElement|null, 
 1569 			custom?: DataCallbacks|null): void
 1570 		{
 1571 			let len: number;
 1572 			if (null === this.obj)
 1573 				len = 0;
 1574 			else if (this.obj instanceof Array)
 1575 				len = this.obj.length;
 1576 			else
 1577 				len = 1;
 1578 			if (null !== e)
 1579 				_hide(e);
 1580 			if (null !== toshow)
 1581 				_hide(toshow);
 1582 			this.fillArray(e, custom);
 1583 			if (null !== toshow && 0 === len)
 1584 				_show(toshow);
 1585 		}
 1586 
 1587 		/**
 1588 		 * Like {@link fill} but for an array. If the data is not an 
 1589 		 * array, it is remapped as an array of one. This will save the 
 1590 		 * first element within 'e', remove all children of 'e', then 
 1591 		 * repeatedly clone the saved element and re-append it, filling 
 1592 		 * in the cloned subtree with the array (inclusive of the subtree 
 1593 		 * root). If the input array is empty or null, 'e' is hidden by 
 1594 		 * using the *hide* class. Otherwise, the *hide* class is 
 1595 		 * removed.
 1596 		 * @param e The DOM element.
 1597 		 * @param custom Custom handler dictionary (see {@link fill}).
 1598 		 */
 1599 		fillArray(e: HTMLElement|null, custom?: DataCallbacks|null): 
 1600 			void
 1601 		{
 1602 			let i: number;
 1603 			const o: userData[] =
 1604 				(this.obj instanceof Array) ?
 1605 				 this.obj : [this.obj];
 1606 
 1607 			if (e === null || e.children.length === 0)
 1608 				return;
 1609 			_hide(e);
 1610 			if (o.length === 0 || this.obj === null)
 1611 				return;
 1612 			_show(e);
 1613 
 1614 			const row: HTMLElement =
 1615 				<HTMLElement>e.children[0];
 1616 			while (e.firstChild !== null)
 1617 				e.removeChild(e.firstChild)
 1618 			for (i = 0; i < o.length; i++) {
 1619 				const cln: HTMLElement =
 1620 					<HTMLElement>row.cloneNode(true);
 1621 				e.appendChild(cln);
 1622 				this._fill(cln, o[i], true, custom);
 1623 			}
 1624 		}
 1625 
 1626 		/**
 1627 		 * Like {@link fillArray} but instead of accepting a single 
 1628 		 * element to fill, filling all elements by class name beneath 
 1629 		 * the given root (non-inclusive).
 1630 		 * @param e The DOM element.
 1631 		 * @param name Name of the class to fill.
 1632 		 * @param custom Custom handler dictionary (see {@link fill} for 
 1633 		 * details).
 1634 		 */
 1635 		fillArrayByClass(e: HTMLElement|null, name: string, 
 1636 			custom?: DataCallbacks|null): void
 1637 		{
 1638 			let i: number;
 1639 			const list: HTMLElement[] =
 1640 				_elemList(e, name, false);
 1641 			for (i = 0; i < list.length; i++)
 1642 				this.fillArray(list[i], custom);
 1643 		}
 1644 
 1645 	}
 1646 
 1647 	/**
 1648 	 * Writes {@link sessionData} into a DOM tree.
 1649 	 */
 1650 	export class session {
 1651 		readonly obj: sessionData|sessionData[];
 1652 		/**
 1653 		 * @param obj The object(s) to write.
 1654 		 */
 1655 		constructor(o: sessionData|sessionData[])
 1656 		{
 1657 			this.obj = o;
 1658 		}
 1659 
 1660 		/**
 1661 		 * Writes {@link sessionData} into the given element. If 
 1662 		 * constructed with an array, the first element is used.  
 1663 		 * Elements within (and including) the element having the 
 1664 		 * following classes are manipulated as follows:
 1665 		 * 
 1666 		 * - `session-user-obj`: invoke {@link user#fillInner} with 
 1667 		 * **user** data
 1668 		 * - `session-userid-enum-select`: sets or unsets the `selected` 
 1669 		 * attribute for non-inclusive descendent `<option>` elements 
 1670 		 * depending on whether the value matches
 1671 		 * - `session-userid-value-checked`: sets or unsets the `checked` 
 1672 		 * attribute depending on whether the value matches
 1673 		 * - `session-userid-text`: replace contents with **userid** data
 1674 		 * - `session-userid-value`: replace `value` attribute with 
 1675 		 * **userid** data
 1676 		 * - `session-token-enum-select`: sets or unsets the `selected` 
 1677 		 * attribute for non-inclusive descendent `<option>` elements 
 1678 		 * depending on whether the value matches
 1679 		 * - `session-token-value-checked`: sets or unsets the `checked` 
 1680 		 * attribute depending on whether the value matches
 1681 		 * - `session-token-text`: replace contents with **token** data
 1682 		 * - `session-token-value`: replace `value` attribute with 
 1683 		 * **token** data
 1684 		 * - `session-mtime-enum-select`: sets or unsets the `selected` 
 1685 		 * attribute for non-inclusive descendent `<option>` elements 
 1686 		 * depending on whether the value matches
 1687 		 * - `session-mtime-value-checked`: sets or unsets the `checked` 
 1688 		 * attribute depending on whether the value matches
 1689 		 * - `session-mtime-text`: replace contents with **mtime** data
 1690 		 * - `session-mtime-value`: replace `value` attribute with 
 1691 		 * **mtime** data
 1692 		 * - `session-mtime-date-value`: set the element's `value` to the 
 1693 		 * ISO-8601 date format of the data
 1694 		 * - `session-mtime-date-text`: like `session-mtime-date-value`, 
 1695 		 * but replacing textual content
 1696 		 * - `session-id-enum-select`: sets or unsets the `selected` 
 1697 		 * attribute for non-inclusive descendent `<option>` elements 
 1698 		 * depending on whether the value matches
 1699 		 * - `session-id-value-checked`: sets or unsets the `checked` 
 1700 		 * attribute depending on whether the value matches
 1701 		 * - `session-id-text`: replace contents with **id** data
 1702 		 * - `session-id-value`: replace `value` attribute with **id** 
 1703 		 * data
 1704 		 * 
 1705 		 * @param e The DOM element.
 1706 		 * @param custom The dictionary of functions keyed by structure 
 1707 		 * and field name (e.g., *foo** structure, **bar** field would be 
 1708 		 * `foo-bar`). The value is a function for custom handling that 
 1709 		 * accepts the 'e' value, the name of the structure-field, and 
 1710 		 * the value of the structure and field. You may also specify an 
 1711 		 * array of functions instead of a singleton. These callbacks are 
 1712 		 * invoked *after* the generic classes are filled.
 1713 		 */
 1714 		fill(e: HTMLElement|null, custom?: DataCallbacks|null): void
 1715 		{
 1716 			if (e !== null)
 1717 				this._fill(e, this.obj, true, custom);
 1718 		}
 1719 
 1720 		/**
 1721 		 * Like {@link fill} but not including the passed-in element.
 1722 		 * @param e The DOM element.
 1723 		 * @param custom Custom handler dictionary (see {@link fill} for 
 1724 		 * details).
 1725 		 */
 1726 		fillInner(e: HTMLElement|null, custom?: DataCallbacks|null): 
 1727 			void
 1728 		{
 1729 			if (e !== null)
 1730 				this._fill(e, this.obj, false, custom);
 1731 		}
 1732 
 1733 		/**
 1734 		 * Like {@link fill} but instead of accepting a single element to 
 1735 		 * fill, filling into all elements (inclusive) matching the given 
 1736 		 * class name beneath (inclusive) the element.
 1737 		 * @param e The DOM element.
 1738 		 * @param name Name of the class to fill.
 1739 		 * @param custom Custom handler dictionary (see {@link fill} for 
 1740 		 * details).
 1741 		 */
 1742 		fillByClass(e: HTMLElement|null, name: string, 
 1743 			custom?: DataCallbacks|null): void
 1744 		{
 1745 			if (e !== null)
 1746 				this._fillByClass(e, name, true, custom);
 1747 		}
 1748 
 1749 		/**
 1750 		 * Like {@link fillByClass} but not inclusive the root element 
 1751 		 * and class matches.
 1752 		 * @param e The DOM element.
 1753 		 * @param name Name of the class to fill.
 1754 		 * @param custom Custom handler dictionary (see {@link fill} for 
 1755 		 * details).
 1756 		 */
 1757 		fillInnerByClass(e: HTMLElement|null, name: string, 
 1758 			custom?: DataCallbacks|null): void
 1759 		{
 1760 			if (e !== null)
 1761 				this._fillByClass(e, name, false, custom);
 1762 		}
 1763 
 1764 		private _fill(e: HTMLElement, obj: sessionData|sessionData[], 
 1765 			inc: boolean, custom?: DataCallbacks|null): 
 1766 			void
 1767 		{
 1768 			if (obj instanceof Array && obj.length === 0)
 1769 				return;
 1770 			const o: sessionData =
 1771 				(obj instanceof Array) ? obj[0] : obj;
 1772 			if (typeof custom === 'undefined')
 1773 				custom = null;
 1774 			_fillField(e, 'session', 'user', custom,
 1775 				o.user, inc, false,
 1776 				new user(o.user));
 1777 			_fillField(e, 'session', 'userid', custom,
 1778 				o.userid, inc, false,null);
 1779 			_fillField(e, 'session', 'token', custom,
 1780 				o.token, inc, false,null);
 1781 			_fillField(e, 'session', 'mtime', custom,
 1782 				o.mtime, inc, false,null);
 1783 			_fillDateValue(e, 'session-mtime', o.mtime, inc);
 1784 			_fillField(e, 'session', 'id', custom, o.id, inc,
 1785 				false,null);
 1786 			if (custom !== null &&
 1787 			    typeof custom['session'] !== 'undefined') {
 1788 				if (custom['session'] instanceof Array) {
 1789 					let i: number;
 1790 					for (i = 0; i < custom['session'].length; i++)
 1791 						custom['session'][i](e, 'session', o);
 1792 				} else
 1793 					custom['session'](e, 'session', o);
 1794 			}
 1795 		}
 1796 
 1797 		private _fillByClass(e: HTMLElement, name: string, inc: boolean, 
 1798 			custom?: DataCallbacks|null): void
 1799 		{
 1800 			let i: number;
 1801 			const list: HTMLElement[] = 
 1802 				_elemList(e, name, inc);
 1803 			for (i = 0; i < list.length; i++)
 1804 				this._fill(list[i], this.obj, inc, custom);
 1805 		}
 1806 
 1807 		/**
 1808 		 * Like {@link fillArray}, but hiding an element if the array is 
 1809 		 * empty or null.
 1810 		 * @param e The DOM element.
 1811 		 * @param tohide DOM element to hide.
 1812 		 * @param o The array (or object) to fill.
 1813 		 * @param custom Custom handler dictionary (see {@link fill}).
 1814 		 */
 1815 		fillArrayOrHide(e: HTMLElement|null, tohide: HTMLElement|null, 
 1816 			custom?: DataCallbacks|null): void
 1817 		{
 1818 			let len: number;
 1819 			if (null === this.obj)
 1820 				len = 0;
 1821 			else if (this.obj instanceof Array)
 1822 				len = this.obj.length;
 1823 			else
 1824 				len = 1;
 1825 			if (null !== e)
 1826 				_hide(e);
 1827 			if (null !== tohide)
 1828 				_show(tohide);
 1829 			this.fillArray(e, custom);
 1830 			if (null !== tohide && 0 === len)
 1831 				_hide(tohide);
 1832 		}
 1833 
 1834 		/**
 1835 		 * Like {@link fillArray}, but showing an element if the array is 
 1836 		 * empty or null.
 1837 		 * @param e The DOM element.
 1838 		 * @param toshow The DOM element to show.
 1839 		 * @param o The array or object to fill.
 1840 		 * @param custom Custom handler dictionary (see {@link fill}).
 1841 		 */
 1842 		fillArrayOrShow(e: HTMLElement|null, toshow: HTMLElement|null, 
 1843 			custom?: DataCallbacks|null): void
 1844 		{
 1845 			let len: number;
 1846 			if (null === this.obj)
 1847 				len = 0;
 1848 			else if (this.obj instanceof Array)
 1849 				len = this.obj.length;
 1850 			else
 1851 				len = 1;
 1852 			if (null !== e)
 1853 				_hide(e);
 1854 			if (null !== toshow)
 1855 				_hide(toshow);
 1856 			this.fillArray(e, custom);
 1857 			if (null !== toshow && 0 === len)
 1858 				_show(toshow);
 1859 		}
 1860 
 1861 		/**
 1862 		 * Like {@link fill} but for an array. If the data is not an 
 1863 		 * array, it is remapped as an array of one. This will save the 
 1864 		 * first element within 'e', remove all children of 'e', then 
 1865 		 * repeatedly clone the saved element and re-append it, filling 
 1866 		 * in the cloned subtree with the array (inclusive of the subtree 
 1867 		 * root). If the input array is empty or null, 'e' is hidden by 
 1868 		 * using the *hide* class. Otherwise, the *hide* class is 
 1869 		 * removed.
 1870 		 * @param e The DOM element.
 1871 		 * @param custom Custom handler dictionary (see {@link fill}).
 1872 		 */
 1873 		fillArray(e: HTMLElement|null, custom?: DataCallbacks|null): 
 1874 			void
 1875 		{
 1876 			let i: number;
 1877 			const o: sessionData[] =
 1878 				(this.obj instanceof Array) ?
 1879 				 this.obj : [this.obj];
 1880 
 1881 			if (e === null || e.children.length === 0)
 1882 				return;
 1883 			_hide(e);
 1884 			if (o.length === 0 || this.obj === null)
 1885 				return;
 1886 			_show(e);
 1887 
 1888 			const row: HTMLElement =
 1889 				<HTMLElement>e.children[0];
 1890 			while (e.firstChild !== null)
 1891 				e.removeChild(e.firstChild)
 1892 			for (i = 0; i < o.length; i++) {
 1893 				const cln: HTMLElement =
 1894 					<HTMLElement>row.cloneNode(true);
 1895 				e.appendChild(cln);
 1896 				this._fill(cln, o[i], true, custom);
 1897 			}
 1898 		}
 1899 
 1900 		/**
 1901 		 * Like {@link fillArray} but instead of accepting a single 
 1902 		 * element to fill, filling all elements by class name beneath 
 1903 		 * the given root (non-inclusive).
 1904 		 * @param e The DOM element.
 1905 		 * @param name Name of the class to fill.
 1906 		 * @param custom Custom handler dictionary (see {@link fill} for 
 1907 		 * details).
 1908 		 */
 1909 		fillArrayByClass(e: HTMLElement|null, name: string, 
 1910 			custom?: DataCallbacks|null): void
 1911 		{
 1912 			let i: number;
 1913 			const list: HTMLElement[] =
 1914 				_elemList(e, name, false);
 1915 			for (i = 0; i < list.length; i++)
 1916 				this.fillArray(list[i], custom);
 1917 		}
 1918 
 1919 	}
 1920 
 1921 	/**
 1922 	 * Birthsex of individual
 1923 	 */
 1924 	export class sex {
 1925 		/**
 1926 		 * Male
 1927 		 */
 1928 		static readonly male: string = '0';
 1929 		/**
 1930 		 * Female
 1931 		 */
 1932 		static readonly female: string = '1';
 1933 		/**
 1934 		 * Other
 1935 		 */
 1936 		static readonly other: string = '2';
 1937 		/**
 1938 		 * Uses the enumeration item's **jslabel** (or an empty string if 
 1939 		 * no **jslabel** is defined or there is no matching item for the 
 1940 		 * value) to format a custom label. This will act on 
 1941 		 * *xxx-yyy-label* classes, where *xxx* is the structure name and 
 1942 		 * *yyy* is the field name.
 1943 		 * A null value is represented by the **isnull** labels (the 
 1944 		 * `ort-null` class is also appended in this case)
 1945 		 * @param e The DOM element.
 1946 		 * @param name If non-null, data is written to elements under the 
 1947 		 * root with the given class name. If null, data is written 
 1948 		 * directly into the DOM element.
 1949 		 * @param v The enumeration value.
 1950 		 */
 1951 		static format(e: HTMLElement, name: string|null, 
 1952 			v: string|number|null): void
 1953 		{
 1954 			let s: string;
 1955 			if (name !== null)
 1956 				name += '-label';
 1957 			if (v === null && name !== null) {
 1958 				_classaddcl(e, name, 'ort-null', false);
 1959 				_replcllang(e, name, {_default: ''});
 1960 				return;
 1961 			} else if (v === null) {
 1962 				_classadd(e, 'ort-null');
 1963 				_repllang(e, {_default: ''});
 1964 				return;
 1965 			}
 1966 			switch(v.toString()) {
 1967 			case sex.male:
 1968 				s = _strlang({_default: 'male'});
 1969 				break;
 1970 			case sex.female:
 1971 				s = _strlang({_default: 'female'});
 1972 				break;
 1973 			case sex.other:
 1974 				s = _strlang({_default: 'other'});
 1975 				break;
 1976 			default:
 1977 				s = '';
 1978 				break;
 1979 			}
 1980 			if (name !== null)
 1981 				_replcl(e, name, s, false);
 1982 			else
 1983 				_repl(e, s);
 1984 		}
 1985 	}
 1986 
 1987 }