1 /**
    2  * Top-level namespace of these objects.
    3  * @namespace
    4  */
    5 var ort;
    6 (function(ort) {
    7 	'use strict';
    8 
    9 	/**
   10 	 * Convenience function to resolve a set of translated strings into a 
   11 	 * single one depending upon the current language.
   12 	 * @param {langmap} vals - All translations of a given word.
   13 	 * @private
   14 	 * @function _strlang
   15 	 * @memberof ort
   16 	 */
   17 	function _strlang(vals)
   18 	{
   19 		var lang;
   20 		lang = document.documentElement.lang;
   21 		if (null !== lang && lang in vals)
   22 			return vals[lang];
   23 		else if ('_default' in vals)
   24 			return vals['_default'];
   25 		else
   26 			return '';
   27 	}
   28 
   29 	/**
   30 	 * Used exclusively by enumerations and bitfields to do language 
   31 	 * replacement conditional upon the label (<i>jslabel</i> in the 
   32 	 * configuration).
   33 	 * Like {@link ort._replcl} with inclusion set to false.
   34 	 * @param {HTMLElement} e - The root of the DOM tree in which we 
   35 	 * query for elements to fill into.
   36 	 * @param {String} name - The class name we search for within the 
   37 	 * root (not inclusive).
   38 	 * @param {langmap} vals - All possible translations.
   39 	 * @private
   40 	 * @function _replcllang
   41 	 * @memberof ort
   42 	 */
   43 	function _replcllang(e, name, vals)
   44 	{
   45 		_replcl(e, name, _strlang(vals), false);
   46 	}
   47 
   48 	/**
   49 	 * Used exclusively by enumerations and bitfields to do language 
   50 	 * replacement conditional upon the label (<i>jslabel</i> in the 
   51 	 * configuration).
   52 	 * Like {@link ort._repl}.
   53 	 * @param {HTMLElement} e - The root of the DOM tree in which we 
   54 	 * query for elements to fill into.
   55 	 * @param {langmap} vals - All possible translations.
   56 	 * @private
   57 	 * @function _repllang
   58 	 * @memberof ort
   59 	 */
   60 	function _repllang(e, vals)
   61 	{
   62 		_repl(e, _strlang(vals));
   63 	}
   64 
   65 	function _attr(e, attr, text)
   66 	{
   67 		if (null !== e)
   68 			e.setAttribute(attr, text);
   69 	}
   70 
   71 	function _rattr(e, attr)
   72 	{
   73 		if (null !== e)
   74 			e.removeAttribute(attr);
   75 	}
   76 
   77 	/**
   78 	 * Internal function for checking inputs for all elements of class 
   79 	 * strct-name-value-checked whose value matches the object's value. 
   80 	 * If the object is null, all elements are unchecked.
   81 	 * @param {HTMLElement} e - The root of the DOM tree in which we 
   82 	 * query for elements to fill into.
   83 	 * @param {String} strct - The name of the structure that we're 
   84 	 * filling in.
   85 	 * @param {String} name - The name of the field.
   86 	 * @param {Number|String|null} obj - The data itself.
   87 	 * @param {Boolean} inc - Whether to include the root element in 
   88 	 * looking for elements to fill.
   89 	 * @private
   90 	 * @function _fillValueChecked
   91 	 * @memberof ort
   92 	 */
   93 	function _fillValueChecked(e, fname, val, inc)
   94 	{
   95 		var list;
   96 		var i;
   97 		var valstr;
   98 		fname += '-value-checked';
   99 		valstr = null === val ? null : 
  100 			("number" === typeof val ? val.toString() : val);
  101 		list = _elemList(e, fname, inc);
  102 		for (i = 0; i < list.length; i++)
  103 			if (valstr === null)
  104 				_rattr(list[i], 'checked');
  105 			else if (valstr === (list[i]).value)
  106 				_attr(list[i], 'checked', 'true');
  107 			else
  108 				_rattr(list[i], 'checked');
  109 	}
  110 
  111 	/**
  112 	 * Internal function that takes all <code>&lt;option&gt;</code> 
  113 	 * elements in the root and sets or unsets their 
  114 	 * <code>selected</code> status depending upon whether it matches the 
  115 	 * object's value.
  116 	 * @param {HTMLElement} e - The root of the DOM tree in which we 
  117 	 * query for elements to fill into.
  118 	 * @param {Number|String} val - The object's value.
  119 	 * @private
  120 	 * @function _fillValueSelect
  121 	 * @memberof ort
  122 	 */
  123 	function _fillValueSelect(e, val)
  124 	{
  125 		var list;
  126 		var i;
  127 		var v;
  128 		if (null === e)
  129 			return;
  130 		list = e.getElementsByTagName('option');
  131 		for (i = 0; i < list.length; i++) {
  132 			v = 'number' === typeof val ? 
  133 			     parseInt((list[i]).value) :
  134 			     (list[i]).value;
  135 			if (val === v)
  136 				_attr(list[i], 'selected', 'true');
  137 			else
  138 				_rattr(list[i], 'selected');
  139 		}
  140 	}
  141 
  142 	function _attrcl(e, attr, name, text, inc)
  143 	{
  144 		var list;
  145 		var i;
  146 		if (null === e)
  147 			return;
  148 		list = _elemList(e, name, inc);
  149 		for (i = 0; i < list.length; i++)
  150 			_attr(list[i], attr, text);
  151 	}
  152 
  153 	function _elemList(e, cls, inc)
  154 	{
  155 		var a;
  156 		var list;
  157 		var i;
  158 		a = [];
  159 		if (null === e)
  160 			return a;
  161 		list = e.getElementsByClassName(cls);
  162 		for (i = 0; i < list.length; i++)
  163 			a.push(list[i]);
  164 		if (inc && e.classList.contains(cls))
  165 			a.push(e);
  166 		return a;
  167 	}
  168 
  169 	function _repl(e, text)
  170 	{
  171 		if (null === e)
  172 			return;
  173 		while (e.firstChild)
  174 			e.removeChild(e.firstChild);
  175 		e.appendChild(document.createTextNode(text));
  176 	}
  177 
  178 	/**
  179 	 * Internal function for filling in ISO-8601 dates.
  180 	 * @param {HTMLElement} e - The root of the DOM tree in which we 
  181 	 * query for elements to fill into.
  182 	 * @param {String} strct - The name of the structure that we're 
  183 	 * filling in.
  184 	 * @param {String} name - The name of the field.
  185 	 * @param {Number|null} obj - The data itself.
  186 	 * @param {Boolean} inc - Whether to include the root element in 
  187 	 * looking for elements to fill.
  188 	 * @private
  189 	 * @function _fillDateValue
  190 	 * @memberof ort
  191 	 */
  192 	function _fillDateValue(e, strct, name, val, inc)
  193 	{
  194 		var fname;
  195 		var year;
  196 		var mo;
  197 		var day;
  198 		var full;
  199 		var d;
  200 		if (null === val)
  201 			return;
  202 		d = new Date();
  203 		d.setTime(val * 1000);
  204 		year = d.getFullYear();
  205 		mo = d.getMonth() + 1;
  206 		day = d.getDate();
  207 		full = year + '-' +
  208 			(mo < 10 ? '0' : '') + mo + '-' +
  209 			(day < 10 ? '0' : '') + day;
  210 		fname = strct + '-' + name + '-date-value';
  211 		_attrcl(e, 'value', fname, full, inc);
  212 		fname = strct + '-' + name + '-date-text';
  213 		_replcl(e, fname, full, inc);
  214 	}
  215 
  216 	/**
  217 	 * Internal function for checking inputs for all elements of class 
  218 	 * strct-name-bits-checked whose value is the bit-wise AND of the 
  219 	 * object's value. If the object is null, all elements are unchecked.
  220 	 * @param {HTMLElement} e - The root of the DOM tree in which we 
  221 	 * query for elements to fill into.
  222 	 * @param {String} strct - The name of the structure that we're 
  223 	 * filling in.
  224 	 * @param {String} name - The name of the field.
  225 	 * @param {Number|null} obj - The data itself.
  226 	 * @param {Boolean} inc - Whether to include the root element in 
  227 	 * looking for elements to fill.
  228 	 * @private
  229 	 * @function _fillBitsChecked
  230 	 * @memberof ort
  231 	 */
  232 	function _fillBitsChecked(e, strct, name, val, inc)
  233 	{
  234 		var list;
  235 		var fname;
  236 		var i;
  237 		var v;
  238 		fname = strct + '-' + name + '-bits-checked';
  239 		list = _elemList(e, fname, inc);
  240 		for (i = 0; i < list.length; i++) {
  241 			if (val === null) {
  242 				_rattr(list[i], 'checked');
  243 				continue;
  244 			}
  245 			v = parseInt((list[i]).value);
  246 			if (isNaN(v))
  247 				_rattr(list[i], 'checked');
  248 			else if (0 === v && 0 === val)
  249 				_attr(list[i], 'checked', 'true');
  250 			else if ((1 << (v - 1)) & val)
  251 				_attr(list[i], 'checked', 'true');
  252 			else
  253 				_rattr(list[i], 'checked');
  254 		}
  255 	}
  256 
  257 	/**
  258 	 * Internal function for filling a structure field.
  259 	 * This first does the has/no class setting for null values, then 
  260 	 * optionally returns if null (running the custom fields first), 
  261 	 * otherwise the generic text/value/etc fields, then finally the 
  262 	 * custom fields.
  263 	 * @param {HTMLElement} e - The root of the DOM tree in which we 
  264 	 * query for elements to fill into.
  265 	 * @param {String} strct - The name of the structure that we're 
  266 	 * filling in.
  267 	 * @param {String} name - The name of the field.
  268 	 * @param {ort.DataCallbacks|null} custom - Custom callback functions 
  269 	 * to invoke on the field.
  270 	 * @param obj - The data itself, which is either a native type or one 
  271 	 * of the data interfaces for an application-specific type.
  272 	 * @param {Boolean} inc - Whether to include the root element in 
  273 	 * looking for elements to fill. Note that nested structures are 
  274 	 * alwyas filled non-inclusively.
  275 	 * @param {Boolean} cannull - Whether the data object might be null.
  276 	 * @param {Boolean} isblob - Whether the data object is a blob.
  277 	 * @param sub - If the data object is a nested structure interface, 
  278 	 * this is the allocated class of that interface.
  279 	 * @private
  280 	 * @function _fillField
  281 	 * @memberof ort
  282 	 */
  283 	function _fillField(e, strct, name, custom, obj, inc, cannull, isblob, sub)
  284 	{
  285 		var i;
  286 		var fname;
  287 		var list;
  288 		fname = strct + '-' + name;
  289 		/* First handle our has/no null situation. */
  290 		if (cannull) {
  291 			if (null === obj) {
  292 				_hidecl(e, strct + '-has-' + name, inc);
  293 				_showcl(e, strct + '-no-' + name, inc);
  294 			} else {
  295 				_showcl(e, strct + '-has-' + name, inc);
  296 				_hidecl(e, strct + '-no-' + name, inc);
  297 			}
  298 		}
  299 		/* Don't process null values that can be null. */
  300 		if (cannull && null === obj) {
  301 			if (null !== custom && fname in custom) {
  302 				if (custom[fname] instanceof Array) {
  303 					for (i = 0; i < custom[fname].length; i++)
  304 						custom[fname][i](e, fname, null);
  305 				} else {
  306 					custom[fname](e, fname, null);
  307 				}
  308 			}
  309 			return;
  310 		}
  311 		/* Non-null non-structs. */
  312 		/* Don't account for blobs. */
  313 		if (null !== sub) {
  314 			list = _elemList(e, fname + '-obj', inc);
  315 			for (i = 0; i < list.length; i++) {
  316 				sub.fillInner(list[i], custom);
  317 			}
  318 		} else if ( ! isblob) {
  319 			list = _elemList(e, fname + '-enum-select', inc);
  320 			for (i = 0; i < list.length; i++) {
  321 				_fillValueSelect(list[i], obj);
  322 			}
  323 			_replcl(e, fname + '-text', obj, inc);
  324 			_attrcl(e, 'value', fname + '-value', obj, inc);
  325 			_fillValueChecked(e, fname, obj, inc);
  326 		}
  327 		/* Lastly, handle the custom callback. */
  328 		if (null !== custom && fname in custom) {
  329 			if (custom[fname] instanceof Array) {
  330 				for (i = 0; i < custom[fname].length; i++)
  331 					custom[fname][i](e, fname, obj);
  332 			} else {
  333 				custom[fname](e, fname, obj);
  334 			}
  335 		}
  336 	}
  337 
  338 	function _replcl(e, name, text, inc)
  339 	{
  340 		var list;
  341 		var i;
  342 		if (null === e)
  343 			return;
  344 		list = _elemList(e, name, inc);
  345 		for (i = 0; i < list.length; i++)
  346 			_repl(list[i], text);
  347 	}
  348 
  349 	function _classadd(e, name)
  350 	{
  351 		if (null === e)
  352 			return(null);
  353 		if ( ! e.classList.contains(name))
  354 			e.classList.add(name);
  355 		return(e);
  356 	}
  357 
  358 	function _classaddcl(e, name, cls, inc)
  359 	{
  360 		var list;
  361 		var i;
  362 		if (null === e)
  363 			return;
  364 		list = _elemList(e, name, inc);
  365 		for (i = 0; i < list.length; i++)
  366 			_classadd(list[i], cls);
  367 	}
  368 
  369 	function _hide(e)
  370 	{
  371 		if (null === e)
  372 			return null;
  373 		if ( ! e.classList.contains('hide'))
  374 			e.classList.add('hide');
  375 		return e;
  376 	}
  377 
  378 	function _hidecl(e, name, inc)
  379 	{
  380 		var list;
  381 		var i;
  382 		if (null === e)
  383 			return;
  384 		list = _elemList(e, name, inc);
  385 		for (i = 0; i < list.length; i++)
  386 			_hide(list[i]);
  387 	}
  388 
  389 	function _show(e)
  390 	{
  391 		if (null === e)
  392 			return null;
  393 		if (e.classList.contains('hide'))
  394 			e.classList.remove('hide');
  395 		return e;
  396 	}
  397 
  398 	function _showcl(e, name, inc)
  399 	{
  400 		var list;
  401 		var i;
  402 		if (null === e)
  403 			return;
  404 		list = _elemList(e, name, inc);
  405 		for (i = 0; i < list.length; i++)
  406 			_show(list[i]);
  407 	}
  408 
  409 	/**
  410 	 * All possible callback functions for passing to the "custom" 
  411 	 * associative array when filling in DOM trees.
  412 	 * @interface ort.DataCallbacks
  413 	 */
  414 	/**
  415 	 * 
  416 	 * A user within our system.<br/>
  417 	 * 
  418 	 * @interface ort.userData
  419 	 */
  420 	/**
  421 	 * 
  422 	 * A logged-in user.<br/>
  423 	 * 
  424 	 * @interface ort.sessData
  425 	 */
  426 	/**
  427 	 * Accepts {@link ort.userData} for writing into a DOM tree.
  428 	 * @param {(ort.userData|ort.userData[])} obj - The object(s) to 
  429 	 * write.
  430 	 * @memberof ort
  431 	 * @constructor
  432 	 * @class
  433 	 */
  434 	var user = (function()
  435 	{
  436 		function user(o)
  437 		{
  438 			this.obj = o;
  439 		}
  440 		/**
  441 		 * Write the {@link ort.userData} into the given HTMLElement in 
  442 		 * the DOM tree.
  443 		 * If constructed with an array, the first element is used.
  444 		 * Elements within (and including) "e" having the following 
  445 		 * classes are manipulated as follows:
  446 		 * <ul>
  447 		 * <li>user-email-enum-select: sets the <code>select</code> 
  448 		 * attribute for <code>&lt;option&gt;</code> values matching 
  449 		 * <i>email</i> under the element</li>
  450 		 * <li>user-email-value-checked: sets the <code>checked</code> 
  451 		 * attribute under the element matching the input</li>
  452 		 * <li>user-email-text: replace contents with <i>email</i> 
  453 		 * data</li>
  454 		 * <li>user-email-value: replace <code>value</code> attribute 
  455 		 * with <i>email</i> data</li>
  456 		 * <li>user-hash-enum-select: sets the <code>select</code> 
  457 		 * attribute for <code>&lt;option&gt;</code> values matching 
  458 		 * <i>hash</i> under the element</li>
  459 		 * <li>user-hash-value-checked: sets the <code>checked</code> 
  460 		 * attribute under the element matching the input</li>
  461 		 * <li>user-hash-text: replace contents with <i>hash</i> 
  462 		 * data</li>
  463 		 * <li>user-hash-value: replace <code>value</code> attribute with 
  464 		 * <i>hash</i> data</li>
  465 		 * <li>user-id-enum-select: sets the <code>select</code> 
  466 		 * attribute for <code>&lt;option&gt;</code> values matching 
  467 		 * <i>id</i> under the element</li>
  468 		 * <li>user-id-value-checked: sets the <code>checked</code> 
  469 		 * attribute under the element matching the input</li>
  470 		 * <li>user-id-text: replace contents with <i>id</i> data</li>
  471 		 * <li>user-id-value: replace <code>value</code> attribute with 
  472 		 * <i>id</i> data</li>
  473 		 * </ul>
  474 		 * @param {HTMLElement} e - The DOM element.
  475 		 * @param {ort.DataCallbacks} custom - The optional dictionary of 
  476 		 * functions keyed by structure and field name (e.g., <i>foo</i> 
  477 		 * structure, <i>bar</i> field would be <code>foo-bar</code>). 
  478 		 * The value is a function for custom handling that accepts the 
  479 		 * "e" value, the name of the structure-field, and the value of 
  480 		 * the structure and field.
  481 		 * You may also specify an array of functions instead of a 
  482 		 * singleton.
  483 		 * These callbacks are invoked <b>after</b> the generic classes 
  484 		 * are filled.
  485 		 * @function fill
  486 		 * @memberof ort.user#
  487 		 */
  488 		user.prototype.fill = function(e, custom)
  489 		{
  490 			this._fill(e, this.obj, true, custom);
  491 		};
  492 
  493 		/**
  494 		 * Like {@link ort.user#fill} but instead of accepting a single 
  495 		 * element to fill, filling into all elements (non-inclusive) 
  496 		 * matching the given class name beneath (non-inclusive) the 
  497 		 * given root.
  498 		 * @param {HTMLElement} e - The DOM element.
  499 		 * @param {String} name - The name of the class into which to 
  500 		 * fill.
  501 		 * @param {ort.DataCallbacks} custom - The optional custom 
  502 		 * handler dictionary (see {@link ort.user#fill} for details).
  503 		 * @function fillByClass
  504 		 * @memberof ort.user#
  505 		 */
  506 		user.prototype.fillByClass = function(e, name, custom)
  507 		{
  508 			this._fillByClass(e, name, true, custom);
  509 		};
  510 
  511 		/**
  512 		 * Like {@link ort.user#fillByClass} but inclusive the root and 
  513 		 * targets by class.
  514 		 * @param {HTMLElement} e - The DOM element.
  515 		 * @param {String} name - The name of the class into which to 
  516 		 * fill.
  517 		 * @param {ort.DataCallbacks} custom - The optional custom 
  518 		 * handler dictionary (see {@link ort.user#fill} for details).
  519 		 * @function fillInnerByClass
  520 		 * @memberof ort.user#
  521 		 */
  522 		user.prototype.fillInnerByClass = function(e, name, custom)
  523 		{
  524 			this._fillByClass(e, name, false, custom);
  525 		};
  526 
  527 		/**
  528 		 * Like {@link ort.user#fill} but not including the root element 
  529 		 * "e".
  530 		 * @param {HTMLElement} e - The DOM element.
  531 		 * @param {ort.DataCallbacks} custom - The optional custom 
  532 		 * handler dictionary (see {@link ort.user#fill} for details).
  533 		 * @function fillInner
  534 		 * @memberof ort.user#
  535 		 */
  536 		user.prototype.fillInner = function(e, custom)
  537 		{
  538 			this._fill(e, this.obj, false, custom);
  539 		};
  540 
  541 		/**
  542 		 * Implements all {@link ort.user#fill} functions.
  543 		 * @param {HTMLElement} e - The DOM element.
  544 		 * @param {ort.userData|ort.userData[]|null} o - The object (or 
  545 		 * array) to fill.
  546 		 * @param {Boolean} inc - Whether to include the root or not when 
  547 		 * processing.
  548 		 * @param {ort.DataCallbacks} custom - The optional custom 
  549 		 * handler dictionary (see {@link ort.user#fill}).
  550 		 * @private
  551 		 * @function _fill
  552 		 * @memberof ort.user#
  553 		 */
  554 		user.prototype._fill = function(e, o, inc, custom)
  555 		{
  556 			var i;
  557 			if (null === o || null === e)
  558 				return;
  559 			if (o instanceof Array) {
  560 				if (0 === o.length)
  561 					return;
  562 				o = o[0];
  563 			}
  564 			if (typeof custom === 'undefined')
  565 				custom = null;
  566 			_fillField(e, 'user', 'email', custom, o.email, inc, false, false, null);
  567 			_fillField(e, 'user', 'hash', custom, o.hash, inc, false, false, null);
  568 			_fillField(e, 'user', 'id', custom, o.id, inc, false, false, null);
  569 			if (null !== custom && 'user' in custom) {
  570 				if (custom['user'] instanceof Array) {
  571 					for (i = 0; i < custom['user'].length; i++)
  572 						(custom['user'])[i](e, 'user', o);
  573 				} else {
  574 					(custom['user'])(e, 'user', o);
  575 				}
  576 			}
  577 		};
  578 
  579 		/**
  580 		 * Like {@link ort.user#_fill} but instead of accepting a single 
  581 		 * element to fill, filling into all elements matching the given 
  582 		 * class name beneath the given root.
  583 		 * @param {HTMLElement} e - The DOM element.
  584 		 * @param {String} name - The name of the class into which to 
  585 		 * fill.
  586 		 * @param {Boolean} inc - Whether to include the roots or not 
  587 		 * when processing.
  588 		 * @param {ort.DataCallbacks} custom - The optional custom 
  589 		 * handler dictionary (see {@link ort.user#fill} for details).
  590 		 * @private
  591 		 * @function _fillByClass
  592 		 * @memberof ort.user#
  593 		 */
  594 		user.prototype._fillByClass = function(e, name, inc, custom)
  595 		{
  596 			var i;
  597 			var list;
  598 			list = _elemList(e, name, inc);
  599 			for (i = 0; i < list.length; i++)
  600 				this._fill(list[i], this.obj, inc, custom);
  601 		};
  602 
  603 		/**
  604 		 * Like {@link ort.user#fillArray}, but hiding an element if the 
  605 		 * array is empty or null.
  606 		 * @param {HTMLElement|null} e - The DOM element.
  607 		 * @param {HTMLElement|null} tohide - The DOM element to hide.
  608 		 * @param {ort.userData|ort.userData[]|null} o - The array (or 
  609 		 * object) to fill.
  610 		 * @param {ort.DataCallbacks} custom - The optional custom 
  611 		 * handler dictionary (see {@link ort.user#fill}).
  612 		 * @function fillArrayOrHide
  613 		 * @memberof ort.user#
  614 		 */
  615 		user.prototype.fillArrayOrHide = function(e, tohide, custom)
  616 		{
  617 			var len;
  618 			if (null === this.obj)
  619 				len = 0;
  620 			else if (this.obj instanceof Array)
  621 				len = this.obj.length;
  622 			else
  623 				len = 1;
  624 			if (null !== e)
  625 				_hide(e);
  626 			if (null !== tohide)
  627 				_show(tohide);
  628 			this.fillArray(e, custom);
  629 			if (null !== tohide && 0 === len)
  630 				_hide(tohide);
  631 		};
  632 		/**
  633 		 * Like {@link ort.user#fillArray}, but showing an element if the 
  634 		 * array is empty or null.
  635 		 * @param {HTMLElement|null} e - The DOM element.
  636 		 * @param {HTMLElement|null} toshow - The DOM element to show.
  637 		 * @param {ort.userData|ort.userData[]|null} o - The array (or 
  638 		 * object) to fill.
  639 		 * @param {ort.DataCallbacks} custom - The optional custom 
  640 		 * handler dictionary (see {@link ort.user#fill}).
  641 		 * @function fillArrayOrShow
  642 		 * @memberof ort.user#
  643 		 */
  644 		user.prototype.fillArrayOrShow = function(e, toshow, custom)
  645 		{
  646 			var len;
  647 			if (null === this.obj)
  648 				len = 0;
  649 			else if (this.obj instanceof Array)
  650 				len = this.obj.length;
  651 			else
  652 				len = 1;
  653 			if (null !== e)
  654 				_hide(e);
  655 			if (null !== toshow)
  656 				_hide(toshow);
  657 			this.fillArray(e, custom);
  658 			if (null !== toshow && 0 === len)
  659 				_show(toshow);
  660 		};
  661 		/**
  662 		 * Like {@link ort.user#fill} but for an array of {@link 
  663 		 * ort.userData}.
  664 		 * If the data is not an array, it is remapped as an array of 
  665 		 * one.
  666 		 * This will save the first element within "e", remove all 
  667 		 * children of "e", then repeatedly clone the saved element and 
  668 		 * re-append it, filling in the cloned subtree with the array 
  669 		 * (inclusive of the subtree root).
  670 		 * If the input array is empty or null, "e" is hidden by using 
  671 		 * the <code>hide</code> class.
  672 		 * Otherwise, the <code>hide</code> class is removed.
  673 		 * @param {HTMLElement} e - The DOM element.
  674 		 * @param {ort.DataCallbacks} custom - The optional custom 
  675 		 * handler dictionary (see {@link ort.user#fill}).
  676 		 * @memberof ort.user#
  677 		 * @function fillArray
  678 		 */
  679 		user.prototype.fillArray = function(e, custom)
  680 		{
  681 			var j;
  682 			var o;
  683 			var cln;
  684 			var ar;
  685 			var row;
  686 			o = this.obj;
  687 			if (null !== e)
  688 				_hide(e);
  689 			if (null === o || null === e)
  690 				return;
  691 			if ( ! (o instanceof Array)) {
  692 				ar = [];
  693 				ar.push(o);
  694 				o = ar;
  695 			}
  696 			if (0 === o.length)
  697 				return;
  698 			_show(e);
  699 			row = e.children[0];
  700 			if (null === row)
  701 				return;
  702 			e.removeChild(row);
  703 			while (null !== e.firstChild)
  704 				e.removeChild(e.firstChild)
  705 			for (j = 0; j < o.length; j++) {
  706 				cln = row.cloneNode(true);
  707 				e.appendChild(cln);
  708 				this._fill(cln, o[j], true, custom);
  709 			}
  710 		};
  711 		/**
  712 		 * Like {@link ort.user#fillArray} but instead of accepting a 
  713 		 * single element to fill, filling all elements by class name 
  714 		 * beneath the given root (non-inclusive).
  715 		 * @param {HTMLElement} e - The DOM element.
  716 		 * @param {String} name - The name of the class into which to 
  717 		 * fill.
  718 		 * @param {ort.DataCallbacks} custom - The optional custom 
  719 		 * handler dictionary (see {@link ort.user#fill} for details).
  720 		 * @function fillArrayByClass
  721 		 * @memberof ort.user#
  722 		 */
  723 		user.prototype.fillArrayByClass = function(e, name, custom)
  724 		{
  725 			var i;
  726 			var list;
  727 			list = _elemList(e, name, false);
  728 			for (i = 0; i < list.length; i++)
  729 				this.fillArray(list[i], custom);
  730 		};
  731 
  732 		return user;
  733 	}());
  734 	ort.user = user;
  735 
  736 	/**
  737 	 * Accepts {@link ort.sessData} for writing into a DOM tree.
  738 	 * @param {(ort.sessData|ort.sessData[])} obj - The object(s) to 
  739 	 * write.
  740 	 * @memberof ort
  741 	 * @constructor
  742 	 * @class
  743 	 */
  744 	var sess = (function()
  745 	{
  746 		function sess(o)
  747 		{
  748 			this.obj = o;
  749 		}
  750 		/**
  751 		 * Write the {@link ort.sessData} into the given HTMLElement in 
  752 		 * the DOM tree.
  753 		 * If constructed with an array, the first element is used.
  754 		 * Elements within (and including) "e" having the following 
  755 		 * classes are manipulated as follows:
  756 		 * <ul>
  757 		 * <li>sess-user-obj: invoke {@link ort.user#fillInner} with user 
  758 		 * data</li>
  759 		 * <li>sess-userid-enum-select: sets the <code>select</code> 
  760 		 * attribute for <code>&lt;option&gt;</code> values matching 
  761 		 * <i>userid</i> under the element</li>
  762 		 * <li>sess-userid-value-checked: sets the <code>checked</code> 
  763 		 * attribute under the element matching the input</li>
  764 		 * <li>sess-userid-text: replace contents with <i>userid</i> 
  765 		 * data</li>
  766 		 * <li>sess-userid-value: replace <code>value</code> attribute 
  767 		 * with <i>userid</i> data</li>
  768 		 * <li>sess-token-enum-select: sets the <code>select</code> 
  769 		 * attribute for <code>&lt;option&gt;</code> values matching 
  770 		 * <i>token</i> under the element</li>
  771 		 * <li>sess-token-value-checked: sets the <code>checked</code> 
  772 		 * attribute under the element matching the input</li>
  773 		 * <li>sess-token-text: replace contents with <i>token</i> 
  774 		 * data</li>
  775 		 * <li>sess-token-value: replace <code>value</code> attribute 
  776 		 * with <i>token</i> data</li>
  777 		 * <li>sess-id-enum-select: sets the <code>select</code> 
  778 		 * attribute for <code>&lt;option&gt;</code> values matching 
  779 		 * <i>id</i> under the element</li>
  780 		 * <li>sess-id-value-checked: sets the <code>checked</code> 
  781 		 * attribute under the element matching the input</li>
  782 		 * <li>sess-id-text: replace contents with <i>id</i> data</li>
  783 		 * <li>sess-id-value: replace <code>value</code> attribute with 
  784 		 * <i>id</i> data</li>
  785 		 * </ul>
  786 		 * @param {HTMLElement} e - The DOM element.
  787 		 * @param {ort.DataCallbacks} custom - The optional dictionary of 
  788 		 * functions keyed by structure and field name (e.g., <i>foo</i> 
  789 		 * structure, <i>bar</i> field would be <code>foo-bar</code>). 
  790 		 * The value is a function for custom handling that accepts the 
  791 		 * "e" value, the name of the structure-field, and the value of 
  792 		 * the structure and field.
  793 		 * You may also specify an array of functions instead of a 
  794 		 * singleton.
  795 		 * These callbacks are invoked <b>after</b> the generic classes 
  796 		 * are filled.
  797 		 * @function fill
  798 		 * @memberof ort.sess#
  799 		 */
  800 		sess.prototype.fill = function(e, custom)
  801 		{
  802 			this._fill(e, this.obj, true, custom);
  803 		};
  804 
  805 		/**
  806 		 * Like {@link ort.sess#fill} but instead of accepting a single 
  807 		 * element to fill, filling into all elements (non-inclusive) 
  808 		 * matching the given class name beneath (non-inclusive) the 
  809 		 * given root.
  810 		 * @param {HTMLElement} e - The DOM element.
  811 		 * @param {String} name - The name of the class into which to 
  812 		 * fill.
  813 		 * @param {ort.DataCallbacks} custom - The optional custom 
  814 		 * handler dictionary (see {@link ort.sess#fill} for details).
  815 		 * @function fillByClass
  816 		 * @memberof ort.sess#
  817 		 */
  818 		sess.prototype.fillByClass = function(e, name, custom)
  819 		{
  820 			this._fillByClass(e, name, true, custom);
  821 		};
  822 
  823 		/**
  824 		 * Like {@link ort.sess#fillByClass} but inclusive the root and 
  825 		 * targets by class.
  826 		 * @param {HTMLElement} e - The DOM element.
  827 		 * @param {String} name - The name of the class into which to 
  828 		 * fill.
  829 		 * @param {ort.DataCallbacks} custom - The optional custom 
  830 		 * handler dictionary (see {@link ort.sess#fill} for details).
  831 		 * @function fillInnerByClass
  832 		 * @memberof ort.sess#
  833 		 */
  834 		sess.prototype.fillInnerByClass = function(e, name, custom)
  835 		{
  836 			this._fillByClass(e, name, false, custom);
  837 		};
  838 
  839 		/**
  840 		 * Like {@link ort.sess#fill} but not including the root element 
  841 		 * "e".
  842 		 * @param {HTMLElement} e - The DOM element.
  843 		 * @param {ort.DataCallbacks} custom - The optional custom 
  844 		 * handler dictionary (see {@link ort.sess#fill} for details).
  845 		 * @function fillInner
  846 		 * @memberof ort.sess#
  847 		 */
  848 		sess.prototype.fillInner = function(e, custom)
  849 		{
  850 			this._fill(e, this.obj, false, custom);
  851 		};
  852 
  853 		/**
  854 		 * Implements all {@link ort.sess#fill} functions.
  855 		 * @param {HTMLElement} e - The DOM element.
  856 		 * @param {ort.sessData|ort.sessData[]|null} o - The object (or 
  857 		 * array) to fill.
  858 		 * @param {Boolean} inc - Whether to include the root or not when 
  859 		 * processing.
  860 		 * @param {ort.DataCallbacks} custom - The optional custom 
  861 		 * handler dictionary (see {@link ort.sess#fill}).
  862 		 * @private
  863 		 * @function _fill
  864 		 * @memberof ort.sess#
  865 		 */
  866 		sess.prototype._fill = function(e, o, inc, custom)
  867 		{
  868 			var i;
  869 			if (null === o || null === e)
  870 				return;
  871 			if (o instanceof Array) {
  872 				if (0 === o.length)
  873 					return;
  874 				o = o[0];
  875 			}
  876 			if (typeof custom === 'undefined')
  877 				custom = null;
  878 			_fillField(e, 'sess', 'user', custom, o.user, inc, false, false, new user(o.user));
  879 			_fillField(e, 'sess', 'userid', custom, o.userid, inc, false, false, null);
  880 			_fillField(e, 'sess', 'token', custom, o.token, inc, false, false, null);
  881 			_fillField(e, 'sess', 'id', custom, o.id, inc, false, false, null);
  882 			if (null !== custom && 'sess' in custom) {
  883 				if (custom['sess'] instanceof Array) {
  884 					for (i = 0; i < custom['sess'].length; i++)
  885 						(custom['sess'])[i](e, 'sess', o);
  886 				} else {
  887 					(custom['sess'])(e, 'sess', o);
  888 				}
  889 			}
  890 		};
  891 
  892 		/**
  893 		 * Like {@link ort.sess#_fill} but instead of accepting a single 
  894 		 * element to fill, filling into all elements matching the given 
  895 		 * class name beneath the given root.
  896 		 * @param {HTMLElement} e - The DOM element.
  897 		 * @param {String} name - The name of the class into which to 
  898 		 * fill.
  899 		 * @param {Boolean} inc - Whether to include the roots or not 
  900 		 * when processing.
  901 		 * @param {ort.DataCallbacks} custom - The optional custom 
  902 		 * handler dictionary (see {@link ort.sess#fill} for details).
  903 		 * @private
  904 		 * @function _fillByClass
  905 		 * @memberof ort.sess#
  906 		 */
  907 		sess.prototype._fillByClass = function(e, name, inc, custom)
  908 		{
  909 			var i;
  910 			var list;
  911 			list = _elemList(e, name, inc);
  912 			for (i = 0; i < list.length; i++)
  913 				this._fill(list[i], this.obj, inc, custom);
  914 		};
  915 
  916 		/**
  917 		 * Like {@link ort.sess#fillArray}, but hiding an element if the 
  918 		 * array is empty or null.
  919 		 * @param {HTMLElement|null} e - The DOM element.
  920 		 * @param {HTMLElement|null} tohide - The DOM element to hide.
  921 		 * @param {ort.sessData|ort.sessData[]|null} o - The array (or 
  922 		 * object) to fill.
  923 		 * @param {ort.DataCallbacks} custom - The optional custom 
  924 		 * handler dictionary (see {@link ort.sess#fill}).
  925 		 * @function fillArrayOrHide
  926 		 * @memberof ort.sess#
  927 		 */
  928 		sess.prototype.fillArrayOrHide = function(e, tohide, custom)
  929 		{
  930 			var len;
  931 			if (null === this.obj)
  932 				len = 0;
  933 			else if (this.obj instanceof Array)
  934 				len = this.obj.length;
  935 			else
  936 				len = 1;
  937 			if (null !== e)
  938 				_hide(e);
  939 			if (null !== tohide)
  940 				_show(tohide);
  941 			this.fillArray(e, custom);
  942 			if (null !== tohide && 0 === len)
  943 				_hide(tohide);
  944 		};
  945 		/**
  946 		 * Like {@link ort.sess#fillArray}, but showing an element if the 
  947 		 * array is empty or null.
  948 		 * @param {HTMLElement|null} e - The DOM element.
  949 		 * @param {HTMLElement|null} toshow - The DOM element to show.
  950 		 * @param {ort.sessData|ort.sessData[]|null} o - The array (or 
  951 		 * object) to fill.
  952 		 * @param {ort.DataCallbacks} custom - The optional custom 
  953 		 * handler dictionary (see {@link ort.sess#fill}).
  954 		 * @function fillArrayOrShow
  955 		 * @memberof ort.sess#
  956 		 */
  957 		sess.prototype.fillArrayOrShow = function(e, toshow, custom)
  958 		{
  959 			var len;
  960 			if (null === this.obj)
  961 				len = 0;
  962 			else if (this.obj instanceof Array)
  963 				len = this.obj.length;
  964 			else
  965 				len = 1;
  966 			if (null !== e)
  967 				_hide(e);
  968 			if (null !== toshow)
  969 				_hide(toshow);
  970 			this.fillArray(e, custom);
  971 			if (null !== toshow && 0 === len)
  972 				_show(toshow);
  973 		};
  974 		/**
  975 		 * Like {@link ort.sess#fill} but for an array of {@link 
  976 		 * ort.sessData}.
  977 		 * If the data is not an array, it is remapped as an array of 
  978 		 * one.
  979 		 * This will save the first element within "e", remove all 
  980 		 * children of "e", then repeatedly clone the saved element and 
  981 		 * re-append it, filling in the cloned subtree with the array 
  982 		 * (inclusive of the subtree root).
  983 		 * If the input array is empty or null, "e" is hidden by using 
  984 		 * the <code>hide</code> class.
  985 		 * Otherwise, the <code>hide</code> class is removed.
  986 		 * @param {HTMLElement} e - The DOM element.
  987 		 * @param {ort.DataCallbacks} custom - The optional custom 
  988 		 * handler dictionary (see {@link ort.sess#fill}).
  989 		 * @memberof ort.sess#
  990 		 * @function fillArray
  991 		 */
  992 		sess.prototype.fillArray = function(e, custom)
  993 		{
  994 			var j;
  995 			var o;
  996 			var cln;
  997 			var ar;
  998 			var row;
  999 			o = this.obj;
 1000 			if (null !== e)
 1001 				_hide(e);
 1002 			if (null === o || null === e)
 1003 				return;
 1004 			if ( ! (o instanceof Array)) {
 1005 				ar = [];
 1006 				ar.push(o);
 1007 				o = ar;
 1008 			}
 1009 			if (0 === o.length)
 1010 				return;
 1011 			_show(e);
 1012 			row = e.children[0];
 1013 			if (null === row)
 1014 				return;
 1015 			e.removeChild(row);
 1016 			while (null !== e.firstChild)
 1017 				e.removeChild(e.firstChild)
 1018 			for (j = 0; j < o.length; j++) {
 1019 				cln = row.cloneNode(true);
 1020 				e.appendChild(cln);
 1021 				this._fill(cln, o[j], true, custom);
 1022 			}
 1023 		};
 1024 		/**
 1025 		 * Like {@link ort.sess#fillArray} but instead of accepting a 
 1026 		 * single element to fill, filling all elements by class name 
 1027 		 * beneath the given root (non-inclusive).
 1028 		 * @param {HTMLElement} e - The DOM element.
 1029 		 * @param {String} name - The name of the class into which to 
 1030 		 * fill.
 1031 		 * @param {ort.DataCallbacks} custom - The optional custom 
 1032 		 * handler dictionary (see {@link ort.sess#fill} for details).
 1033 		 * @function fillArrayByClass
 1034 		 * @memberof ort.sess#
 1035 		 */
 1036 		sess.prototype.fillArrayByClass = function(e, name, custom)
 1037 		{
 1038 			var i;
 1039 			var list;
 1040 			list = _elemList(e, name, false);
 1041 			for (i = 0; i < list.length; i++)
 1042 				this.fillArray(list[i], custom);
 1043 		};
 1044 
 1045 		return sess;
 1046 	}());
 1047 	ort.sess = sess;
 1048 
 1049 	ort.user = user;
 1050 	ort.sess = sess;
 1051 })(ort || (ort = {}));