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