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