1 (function(root) {
    2 	'use strict';
    3 
    4 	function _attr(e, attr, text)
    5 	{
    6 		if (null === e)
    7 			return;
    8 		e.setAttribute(attr, text);
    9 	}
   10 
   11 	function _attrcl(e, attr, name, text, inc)
   12 	{
   13 		var list, i;
   14 		if (null === e)
   15 			return;
   16 		list = _elemList(e, name, inc);
   17 		for (i = 0; i < list.length; i++)
   18 			_attr(list[i], attr, text);
   19 	}
   20 
   21 	function _elemList(e, cls, inc)
   22 	{
   23 		var a = [], list, i;
   24 		if (null === e)
   25 			return(a);
   26 		list = e.getElementsByClassName(cls);
   27 		for (i = 0; i < list.length; i++)
   28 			a.push(list[i]);
   29 		if (inc && e.classList.contains(cls))
   30 			a.push(e);
   31 		return(a);
   32 	}
   33 
   34 	function _repl(e, text)
   35 	{
   36 		if (null === e)
   37 			return;
   38 		while (e.firstChild)
   39 			e.removeChild(e.firstChild);
   40 		e.appendChild(document.createTextNode(text));
   41 	}
   42 
   43 	function _replcl(e, name, text, inc)
   44 	{
   45 		var list, i;
   46 		if (null === e)
   47 			return;
   48 		list = _elemList(e, name, inc);
   49 		for (i = 0; i < list.length; i++)
   50 			_repl(list[i], text);
   51 	}
   52 
   53 	function _hide(e)
   54 	{
   55 		if (null === e)
   56 			return(null);
   57 		if ( ! e.classList.contains('hide'))
   58 			e.classList.add('hide');
   59 		return(e);
   60 	}
   61 	
   62 	function _hidecl(e, name, inc)
   63 	{
   64 		var list, i;
   65 		if (null === e)
   66 			return;
   67 		list = _elemList(e, name, inc);
   68 		for (i = 0; i < list.length; i++)
   69 			_hide(list[i]);
   70 	}
   71 
   72 	function _show(e)
   73 	{
   74 		if (null === e)
   75 			return(null);
   76 		if (e.classList.contains('hide'))
   77 			e.classList.remove('hide');
   78 		return(e);
   79 	}
   80 	
   81 	function _showcl(e, name, inc)
   82 	{
   83 		var list, i;
   84 		if (null === e)
   85 			return;
   86 		list = _elemList(e, name, inc);
   87 		for (i = 0; i < list.length; i++)
   88 			_show(list[i]);
   89 	}
   90 
   91 	/**
   92 	 * 
   93 	 * A user within our system.<br />
   94 	 * 
   95 	 * This constructor accepts the "user" objects or array of objects 
   96 	 * serialises into a DOM tree.
   97 	 * @param {(Object|Object[])} obj - The user object or array of 
   98 	 * objects.
   99 	 * @class user
  100 	 */
  101 	function user(obj)
  102 	{
  103 		this.obj = obj;
  104 
  105 		/**
  106 		 * Fill in a "user" object at the given element in the DOM 
  107 		 * tree.
  108 		 * If the object was initialised with an array, the first element 
  109 		 * is used.
  110 		 * Elements within (and including) "e" having the following 
  111 		 * classes are manipulated as follows:
  112 		 * <ul>
  113 		 * <li>user-email-text: replace contents with email data</li>
  114 		 * <li>user-email-value: replace "value" attribute with email 
  115 		 * data</li>
  116 		 * <li>user-hash-text: replace contents with hash data</li>
  117 		 * <li>user-hash-value: replace "value" attribute with hash 
  118 		 * data</li>
  119 		 * <li>user-id-text: replace contents with id data</li>
  120 		 * <li>user-id-value: replace "value" attribute with id data</li>
  121 		 * </ul>
  122 		 * @param {Object} e - The DOM element.
  123 		 * @param {Object} custom - A dictionary of functions keyed by 
  124 		 * structure and field name (e.g., "foo" structure, "bar" field 
  125 		 * would be "foo-bar"). The value is a function for custom 
  126 		 * handling that accepts the "e" value, the name of the 
  127 		 * structure-field, and the value of the structure and 
  128 		 * field.
  129 		 * @memberof user#
  130 		 * @method fill
  131 		 */
  132 		this.fill = function(e, custom) {
  133 			this._fill(e, this.obj, 1, custom);
  134 		};
  135 
  136 		/**
  137 		 * Like [fill]{@link user#fill} but not including the root 
  138 		 * element "e".
  139 		 * @param {Object} e - The DOM element.
  140 		 * @param {Object} custom - The custom handler dictionary (see 
  141 		 * [fill]{@link user#fill} for details).
  142 		 * @memberof user#
  143 		 * @method fillInner
  144 		 */
  145 		this.fillInner = function(e, custom) {
  146 			this._fill(e, this.obj, 0, custom);
  147 		};
  148 
  149 		/**
  150 		 * Implements all [fill]{@link user#fill} style 
  151 		 * functions.
  152 		 * @private
  153 		 * @method _fill
  154 		 * @memberof user#
  155 		 * @param {Object} e - The DOM element.
  156 		 * @param {(Object|Object[])} o - The object (or array) to 
  157 		 * fill.
  158 		 * @param {Number} inc - Whether to include the root or not when 
  159 		 * processing.
  160 		 * @param {Object} custom - The custom handler dictionary (see 
  161 		 * [fill]{@link user#fill}).
  162 		 */
  163 		this._fill = function(e, o, inc, custom) {
  164 			if (null === o || null === e)
  165 				return;
  166 			if (o instanceof Array) {
  167 				if (0 === o.length)
  168 					return;
  169 				o = o[0];
  170 			}
  171 			if (typeof custom !== 'undefined' && 
  172 			    'user-email' in custom)
  173 				custom['user-email'](e, "user-email", o.email);
  174 			_replcl(e, 'user-email-text', o.email, inc);
  175 			_attrcl(e, 'value', 'user-email-value', o.email, inc);
  176 			if (typeof custom !== 'undefined' && 
  177 			    'user-hash' in custom)
  178 				custom['user-hash'](e, "user-hash", o.hash);
  179 			_replcl(e, 'user-hash-text', o.hash, inc);
  180 			_attrcl(e, 'value', 'user-hash-value', o.hash, inc);
  181 			if (typeof custom !== 'undefined' && 
  182 			    'user-id' in custom)
  183 				custom['user-id'](e, "user-id", o.id);
  184 			_replcl(e, 'user-id-text', o.id, inc);
  185 			_attrcl(e, 'value', 'user-id-value', o.id, inc);
  186 		};
  187 
  188 		/**
  189 		 * Like [fill]{@link user#fill} but for an array of user.
  190 		 * This will remove the first element within "e" then repeatedly 
  191 		 * clone and re-append it, filling in the cloned subtree with the 
  192 		 * array.
  193 		 * If "e" is not an array, it is construed as an array of one.
  194 		 * If the input array is empty, "e" is hidden by using the "hide" 
  195 		 * class.
  196 		 * Otherwise, the "hide" class is removed.
  197 		 * @param {Object} e - The DOM element.
  198 		 * @param {Object} custom - The custom handler dictionary (see 
  199 		 * [fill]{@link user#fill}).
  200 		 * @memberof user#
  201 		 * @method fillArray
  202 		 */
  203 		this.fillArray = function(e, custom) {
  204 			var o = this.obj;
  205 			var j, row, cln;
  206 			if (null === o || null === e)
  207 				return;
  208 			if ( ! (o instanceof Array)) {
  209 				var ar = [];
  210 				ar.push(o);
  211 				o = ar;
  212 			}
  213 			if (0 === o.length) {
  214 				_hide(e);
  215 				return;
  216 			}
  217 			_show(e);
  218 			row = e.children[0];
  219 			if (null === row)
  220 				return;
  221 			e.removeChild(row);
  222 			while (null !== e.firstChild)
  223 				e.removeChild(e.firstChild)
  224 			for (j = 0; j < o.length; j++) {
  225 				cln = row.cloneNode(true);
  226 				e.appendChild(cln);
  227 				this._fill(cln, o[j], 1);
  228 			}
  229 		};
  230 	}
  231 
  232 	/**
  233 	 * 
  234 	 * A logged-in user.<br />
  235 	 * 
  236 	 * This constructor accepts the "sess" objects or array of objects 
  237 	 * serialises into a DOM tree.
  238 	 * @param {(Object|Object[])} obj - The sess object or array of 
  239 	 * objects.
  240 	 * @class sess
  241 	 */
  242 	function sess(obj)
  243 	{
  244 		this.obj = obj;
  245 
  246 		/**
  247 		 * Fill in a "sess" object at the given element in the DOM 
  248 		 * tree.
  249 		 * If the object was initialised with an array, the first element 
  250 		 * is used.
  251 		 * Elements within (and including) "e" having the following 
  252 		 * classes are manipulated as follows:
  253 		 * <ul>
  254 		 * <li>sess-user-obj: invoke [fillInner]{@link user#fillInner} 
  255 		 * with user data</li>
  256 		 * <li>sess-userid-text: replace contents with userid data</li>
  257 		 * <li>sess-userid-value: replace "value" attribute with userid 
  258 		 * data</li>
  259 		 * <li>sess-token-text: replace contents with token data</li>
  260 		 * <li>sess-token-value: replace "value" attribute with token 
  261 		 * data</li>
  262 		 * <li>sess-id-text: replace contents with id data</li>
  263 		 * <li>sess-id-value: replace "value" attribute with id data</li>
  264 		 * </ul>
  265 		 * @param {Object} e - The DOM element.
  266 		 * @param {Object} custom - A dictionary of functions keyed by 
  267 		 * structure and field name (e.g., "foo" structure, "bar" field 
  268 		 * would be "foo-bar"). The value is a function for custom 
  269 		 * handling that accepts the "e" value, the name of the 
  270 		 * structure-field, and the value of the structure and 
  271 		 * field.
  272 		 * @memberof sess#
  273 		 * @method fill
  274 		 */
  275 		this.fill = function(e, custom) {
  276 			this._fill(e, this.obj, 1, custom);
  277 		};
  278 
  279 		/**
  280 		 * Like [fill]{@link sess#fill} but not including the root 
  281 		 * element "e".
  282 		 * @param {Object} e - The DOM element.
  283 		 * @param {Object} custom - The custom handler dictionary (see 
  284 		 * [fill]{@link sess#fill} for details).
  285 		 * @memberof sess#
  286 		 * @method fillInner
  287 		 */
  288 		this.fillInner = function(e, custom) {
  289 			this._fill(e, this.obj, 0, custom);
  290 		};
  291 
  292 		/**
  293 		 * Implements all [fill]{@link sess#fill} style 
  294 		 * functions.
  295 		 * @private
  296 		 * @method _fill
  297 		 * @memberof sess#
  298 		 * @param {Object} e - The DOM element.
  299 		 * @param {(Object|Object[])} o - The object (or array) to 
  300 		 * fill.
  301 		 * @param {Number} inc - Whether to include the root or not when 
  302 		 * processing.
  303 		 * @param {Object} custom - The custom handler dictionary (see 
  304 		 * [fill]{@link sess#fill}).
  305 		 */
  306 		this._fill = function(e, o, inc, custom) {
  307 			var list, strct, i;
  308 			if (null === o || null === e)
  309 				return;
  310 			if (o instanceof Array) {
  311 				if (0 === o.length)
  312 					return;
  313 				o = o[0];
  314 			}
  315 			if (typeof custom !== 'undefined' && 
  316 			    'sess-user' in custom)
  317 				custom['sess-user'](e, "sess-user", o.user);
  318 			list = _elemList(e, 'sess-user-obj');
  319 			strct = new user(o.user);
  320 			for (i = 0; i < list.length; i++) {
  321 				strct.fillInner(list[i]);
  322 			}
  323 			if (typeof custom !== 'undefined' && 
  324 			    'sess-userid' in custom)
  325 				custom['sess-userid'](e, "sess-userid", o.userid);
  326 			_replcl(e, 'sess-userid-text', o.userid, inc);
  327 			_attrcl(e, 'value', 'sess-userid-value', o.userid, inc);
  328 			if (typeof custom !== 'undefined' && 
  329 			    'sess-token' in custom)
  330 				custom['sess-token'](e, "sess-token", o.token);
  331 			_replcl(e, 'sess-token-text', o.token, inc);
  332 			_attrcl(e, 'value', 'sess-token-value', o.token, inc);
  333 			if (typeof custom !== 'undefined' && 
  334 			    'sess-id' in custom)
  335 				custom['sess-id'](e, "sess-id", o.id);
  336 			_replcl(e, 'sess-id-text', o.id, inc);
  337 			_attrcl(e, 'value', 'sess-id-value', o.id, inc);
  338 		};
  339 
  340 		/**
  341 		 * Like [fill]{@link sess#fill} but for an array of sess.
  342 		 * This will remove the first element within "e" then repeatedly 
  343 		 * clone and re-append it, filling in the cloned subtree with the 
  344 		 * array.
  345 		 * If "e" is not an array, it is construed as an array of one.
  346 		 * If the input array is empty, "e" is hidden by using the "hide" 
  347 		 * class.
  348 		 * Otherwise, the "hide" class is removed.
  349 		 * @param {Object} e - The DOM element.
  350 		 * @param {Object} custom - The custom handler dictionary (see 
  351 		 * [fill]{@link sess#fill}).
  352 		 * @memberof sess#
  353 		 * @method fillArray
  354 		 */
  355 		this.fillArray = function(e, custom) {
  356 			var list, strct, i;
  357 			var o = this.obj;
  358 			var j, row, cln;
  359 			if (null === o || null === e)
  360 				return;
  361 			if ( ! (o instanceof Array)) {
  362 				var ar = [];
  363 				ar.push(o);
  364 				o = ar;
  365 			}
  366 			if (0 === o.length) {
  367 				_hide(e);
  368 				return;
  369 			}
  370 			_show(e);
  371 			row = e.children[0];
  372 			if (null === row)
  373 				return;
  374 			e.removeChild(row);
  375 			while (null !== e.firstChild)
  376 				e.removeChild(e.firstChild)
  377 			for (j = 0; j < o.length; j++) {
  378 				cln = row.cloneNode(true);
  379 				e.appendChild(cln);
  380 				this._fill(cln, o[j], 1);
  381 			}
  382 		};
  383 	}
  384 
  385 	root.user = user;
  386 	root.sess = sess;
  387 })(this);