// $Id: ListLib.js,v 1.5 2010-03-22 14:00:03 jrixon Exp $

function ListLib(name, props) {

	// check all the mandatory properties were given
	var i;
	var mandProps = [
		'renderTR',
		'itemCols',
		'numVisCols',
		'stripyRows',
		'els',
		'respOrderIsDflt',
		'clientOrdering',
		'dfltOrder',
		'orderWeight'
	];
	for (i = 0; i < mandProps.length; i++) {
		if (typeof props[mandProps[i]] == 'undefined') {
			alert(name + " is broken for ListLib: " + mandProps[i] + " is not defined");
			non_existant_function();
		}
	}

	// public vars in a container object
	var __pub = {
		items : [],
		els   : props.els
	};

	// public vars that have defaults but can be overidden
	var overPubProps = [];
	for (i = 0; i < overPubProps.length; i++) {
		if (typeof props[overPubProps[i]] != 'undefined') {
			__pub[overPubProps[i]] = props[overPubProps[i]];
		}
	}

	// private vars
	var _par = {};
	var _orders = {};
	var _orderAttrs = {};
	var _orderCol = {
		col  : null,
		dir  : null,
		key  : null
	};
	var _headTR = null;
	var _matchTR = null;
	var _matchTDs = [];
	var _orderTHs = {};
	var _orderTH = null;
	var _numWeights = 0;
	var _filterIdx = -1;
	var _selected = {
		id : null,
		tr : null
	};
	var _centreHeight = 0;
	var _colWidths = {
		done : false,
		allButLastWidth : 0,
		prevTRWidth : 0,
		colVis : []
	};

	// private vars from the supplied props
	var _renderTR             = props.renderTR;
	var _itemCols             = props.itemCols;
	var _numVisCols           = props.numVisCols;
	var _stripyRows           = props.stripyRows;
	var _respOrderIsDflt      = props.respOrderIsDflt;
	var _clientOrdering       = props.clientOrdering;
	var _dfltOrder            = props.dfltOrder;
	var _orderWeight          = props.orderWeight;
	var _preListData          = props.preListData;
	var _postListData         = props.postListData;
	var _clickTR              = props.clickTR;
	var _unclickTR            = props.unclickTR;
	var _dblClickTR           = props.dblClickTR;

	if (!_clientOrdering && !_respOrderIsDflt) {
		alert(name + ' is broken for ListLib: if !clientOrdering, must respOrderIsDflt');
		non_existant_function();
	}

	// private vars that have defaults but can be overidden

	if (props.paging) {
		var Paging = PagingLib(name, {
			divId   : __pub.els.divId,
			pageLen : props.paging.pageLen
		});
	}

	var Filters = [];
	if (props.filters) {
		for (i = 0; i < props.filters.length; i++) {
			Filters.push(FilterLib(name, props.filters[i]));
		}
	}
	if (Filters.length > 1) {
		if (typeof props.whichFilter == 'function') {
			var _whichFilter = props.whichFilter;
		} else {
			alert(name + " is broken for ListLib: >1 filter but whichFilter is not defined");
			non_existant_function();
		}
	} else {
		var _whichFilter = function() {
			return (Filters.length - 1);
		};
	}



function regPar(o) {

	_par = o;

	if (Paging) {
		__pub.par = _par;
	}

	_setupTable();
}

function dispCentre(show) {

	var i, filterIdx;

	if (show) {
		document.getElementById(__pub.els.divId).style.display = '';
		if (!_centreHeight) {
			// tell the filters, once, about the newly-revealed scroll div
			var scrollDiv = document.getElementById(__pub.els.wrapTabId).getElementsByTagName('tbody')[0].getElementsByTagName('td')[0].getElementsByTagName('div')[0];
			_centreHeight = scrollDiv.clientHeight;
			for (i = 0; i < Filters.length; i++) {
				Filters[i].setOverlap(scrollDiv, _centreHeight);
			}
		}
	} else {
		document.getElementById(__pub.els.divId).style.display = 'none';
	}

	filterIdx = show ? _whichFilter() : -1;

	for (i = 0; i < Filters.length; i++) {
		if (i == filterIdx) {
			Filters[i].dispFilter(true);
		} else {
			Filters[i].dispFilter(false);
		}
	}

}

function render(partial) {

	DEBUG('render for ' + _par.pub.name + '. partial=' + partial);

	_filterIdx = _whichFilter();

	_par.hint('done');

	if (__pub.items.length == 0) {
		dispBody('no_tables');

		// hide paginate details
		if (Paging) {
			Paging.paginateAdjust();
		}

		return;
	}

	var body    = document.getElementById(__pub.els.itemsTabId).getElementsByTagName('tbody')[2];
	var trs     = body.childNodes;
	var num_trs = trs.length;

	if (!_orderAttrs[_orderCol.col]) {
		// order col looks dodgy so use default
		_orderCol.col = _dfltOrder.col;
		_orderCol.dir = _dfltOrder.dir;
	} else if (_orderCol.dir != 'f' && _orderCol.dir != 'r') {
		// order dir looks dodgy so use default
		_orderCol.dir = _orderAttrs[_orderCol.col].dfltOrder;
	}

	var orderKey = _orderCol.col + ',' + _orderCol.dir;
	var orderKeyChanged = false;
	if (!_orderCol.key || orderKey != _orderCol.key) {
		_orderCol.key = orderKey;
		orderKeyChanged = true;
	}

	DEBUG('Rendering ' + _par.pub.name + ' with order ' + orderKey);

	// sort out order arrow
	if (_orderTH != _orderTHs[_orderCol.col]) {
		if (_orderTH) {
			sky.removeClass(_orderTH, 'asc');
			sky.removeClass(_orderTH, 'desc');
		}
		_orderTH = _orderTHs[_orderCol.col];
	}
	if (orderKeyChanged && _orderTH) {
		if (_orderCol.dir == 'r') {
			sky.addClass(_orderTH, 'desc');
			sky.removeClass(_orderTH, 'asc');
		} else {
			sky.addClass(_orderTH, 'asc');
			sky.removeClass(_orderTH, 'desc');
		}
	}

	if (_clientOrdering) {
		_makeOrder();
	} else {
		orderKey = _dfltOrder.col + ',' + _dfltOrder.dir;
	}

	var i, t, c, tr, td, classNames, className;
	var selectedOK = false;

	var shownCount = 0;

	// paginate the data; determine where to start and how many items to display
	var t_idx, total_items, prevWeightedTR;

	if (Paging) {
		Paging.paginateAdjust();
		t_idx = Paging.pub.pageStart;
  		total_items = Paging.pub.pageEnd - Paging.pub.pageStart;
	} else {
		t_idx = 0;
		total_items = __pub.items.length;
	}

	for (i = 1; i <= total_items; i++) {

		t = _orders[orderKey][t_idx++].i;

		if (i >= num_trs) {
			// create new tr
			tr = document.createElement('tr');

			for (c = 0; c < _numVisCols; c++) {
				td = document.createElement('td');
				tr.appendChild(td);
			}

			body.appendChild(tr);

		} else {
			// re-use tr
			tr = trs[i];

			if (tr.childNodes.length < _numVisCols) {
				// add missing tds
				var num_missing_tds = _numVisCols - tr.childNodes.length;
				for (var j = 0; j < num_missing_tds; j++) {
					td = document.createElement('td');
					tr.appendChild(td);
				}
			} else if (tr.childNodes.length > _numVisCols) {
				// remove extra tds
				var num_extra_tds = tr.childNodes.length - _numVisCols;
				for (var j = 0; j < num_extra_tds; j++) {
					tr.removeChild(tr.childNodes[0]);
				}
			}
		}

		if (typeof _clickTR == 'function') {
			tr.clickable = true;
		} else {
			tr.clickable = false;
		}

		// render the TR (unless partial render)
		if (!partial) {
			_renderTR(tr, t, __pub.items[t]);
		}

		if (_filterIdx >= 0) {
			hide = Filters[_filterIdx].applyFilter(__pub.items[t]);
		} else {
			hide = false;
		}

		// work out the classes and set className for the row
		classNames = [];

		if (hide) {
			classNames.push('hide');
		} else {
			// sort out stripe, promo and selected classes
			if (_stripyRows && shownCount % 2 == 0) {
				classNames.push('poker_');
			}
			if (i <= _numWeights) {
				classNames.push('tb_promo');
				prevWeightedTR = tr;
			} else if (prevWeightedTR) {
				sky.addClass(prevWeightedTR, 'promo_last');
				prevWeightedTR = null;
			}
			if (_selected.id != null && tr.itemId == _selected.id && tr.clickable) {
				classNames.push('selected');
				_selected.tr = tr;
				selectedOK = true;
			}
			if (tr.trClass) {
				classNames.push(tr.trClass);
			}
			if (tr.clickable) {
				classNames.push('clickable');
			}
			shownCount++;
		}

		className = classNames.join(' ');
		if (tr.className != className) {
			tr.className = classNames.join(' ');
		}
	}

	if (_selected.id != null && !selectedOK) {
		unselectItem();
		if (typeof _unclickTR == 'function') {
			_unclickTR();
		}
	}

	if (i < num_trs) {
		var spare_trs = [];
		for ( ; i < num_trs; i++) {
			spare_trs.push(trs[i]);
		}

		for (i = 0; i < spare_trs.length; i++) {
			body.removeChild(spare_trs[i]);
		}
	}

	if (shownCount > 0) {
		dispBody('main');
		matchCols();
	} else {
		dispBody('no_tables');
	}

	if (_filterIdx >= 0) {

		Filters[_filterIdx].dispXofY(shownCount, total_items);

		// Deep linking
		if (State.applyFilters) {

			// Only do on first time
			State.applyFilters = false;

			var args        = window.location.search.substring(1).split('&'),
			    filterTypes = ['Game', 'Type', 'Stake'],
			    filterId, filterVals, i, j, as;

			filterId  = 'filter' + _par.pub.name
			if (_par.pub.name == 'TnmtList') {
				filterId += TnmtList.pub.tnmtType.toUpperCase();
			}

			for (i = 0; i < args.length; i++) {

				// Find 'filter' arg
				as = args[i].split('=');
				if (as[0] != 'filter') {
					continue;
				}

				// Filter arg should be of the form 'Variant,Type,Stake', eg 'Holdem,All,High'.
				// See lobby.html for ids.
				filterVals = as[1].split(',');
				for (j = 0; j < filterVals.length && j < filterTypes.length; j++) {
					try {
						Filters[_filterIdx].itemClkA(document.getElementById(filterId + filterTypes[j] + filterVals[j]));
					} catch(err) {}
				}

				break;
			}
		}
	}
}

function dispBody(which) {

	var tbodies = document.getElementById(__pub.els.itemsTabId).getElementsByTagName('tbody');

	switch (which) {
		case 'loading':
			tbodies[0].style.display = 'none';
			tbodies[1].style.display = '';
			tbodies[2].style.display = 'none';
			break;

		case 'no_tables':
			tbodies[0].style.display = '';
			tbodies[1].style.display = 'none';
			tbodies[2].style.display = 'none';
			break;

		case 'main':
			tbodies[0].style.display = 'none';
			tbodies[1].style.display = 'none';
			tbodies[2].style.display = '';
			break;
	}
}

function hint(which) {

	switch (which) {
		case 'update':
			break;

		case 'new':
			dispBody('loading');
			if (Paging) {
				Paging.paginateHide();
			}
			break;

		case 'done':
			break;
	}
}

function suckListData(data, startIdx) {

	var i, t, r, c, num_items, item_obj, order_obj;

	i = startIdx;

	if (typeof _preListData == 'function') {
		i += _preListData(data, startIdx);
	}
	num_items = data[i];
	__pub.items = [];

	_orders = {};
	_numWeights = 0;

	var normalOrder = [];
	var highOrder   = [];

	i++;
	t = 0;
	for (r = 0; r < num_items; r++) {
		item_obj = {};
		for (c = 0; c < _itemCols.length; c++) {
			item_obj[_itemCols[c]] = data[i+c];
		}

		i += _itemCols.length;

		__pub.items.push(item_obj);

		if (_respOrderIsDflt) {
			order_obj = {i : t};
			if (_orderWeight.col && item_obj[_orderWeight.col] == _orderWeight.val) {
				_numWeights++;
				highOrder.push(order_obj);
			} else {
				normalOrder.push(order_obj);
			}
			t++;
		}
	}

	if (typeof _postListData == 'function') {
		_postListData(data, i);
	}

	if (_respOrderIsDflt) {
		// form default order list, of highlighted items, then normal items
		var orderKey = _dfltOrder.col + ',' + _dfltOrder.dir;
		_orders[orderKey] = [];
		for (i = 0; i < highOrder.length; i++) {
			_orders[orderKey].push(highOrder[i]);
		}
		for (i = 0; i < normalOrder.length; i++) {
			_orders[orderKey].push(normalOrder[i]);
		}
	}
}

function takeListData(items) {

	__pub.items = items;
	_orders = {};
//!!!!!!!!!!!! TODO - how can we get _numWeights? ?????????????
	_numWeights = 0;
}

function shareListDataTake(listObj) {

	var other = listObj.shareListDataGive();

	__pub.items = other.items;
	_orders = other.orders;
	_numWeights = other.numWeights;
}

function shareListDataGive() {

	return {
		items: __pub.items,
		orders : _orders,
		numWeights : _numWeights
	}
}

function _sortCol(o) {

	if (__pub.items.length == 0) {
		return;
	}

	var col = o.getAttribute('sortcol');

	// re-enable paginate
	if (Paging) {
		Paging.pub.pageEnd = 0;
	}

	DEBUG('sortCol for ' + _par.pub.name + ' (' + col + ')');

	if (col == _orderCol.col) {
		if (_orderCol.dir == 'f') {
			_orderCol.dir = 'r';
		} else {
			_orderCol.dir = 'f';
		}
	} else {
		_orderCol.dir = _orderAttrs[col].dfltOrder;
	}

	_orderCol.col = col;

	if (_clientOrdering) {
		render();
	} else {
		_par.sortCol();
	}

	if (document.isLobby) {
		pageMemStore();
	}
}

function _makeOrder() {

	var col = _orderCol.col;

	var f_key = col + ',f';
	var r_key = col + ',r';

	if (_orders[f_key] && _orders[r_key]) {
		return;
	}

	var i, obj;
	if (!_orders[f_key] && !_orders[r_key]) {
		// got neither dir so produce forwards
		DEBUG('_makeOrder: ' + _par.pub.name + ' (' + f_key + ') _f_sort', 'red');
		_orders[f_key] = [];
		_numWeights = 0;

		for (i = 0; i < __pub.items.length; i++) {
			obj = {
				i   : i,
				val : __pub.items[i][col]
			};

			switch (_orderAttrs[col].valType) {
				case 'n': // number
					obj.val = padNum(obj.val, 8);
				break;
				case 'l': // limit: use limit_1, ie remove anything after '/'
					obj.val = obj.val.replace(/\/.*/, '');
				// fall-through
				case 'm': // money : remove ccy symbol
					obj.val = parseFloat(obj.val.replace(/[^0-9-.]/g, ''));
				break;
				case 'lt' : // limit type
					if (obj.val == 'NL') {
						obj.val = '1';
					} else if (obj.val == 'PL') {
						obj.val = '2';
					} else if (obj.val == 'FL') {
						obj.val = '3';
					}
				break;
				default:
					obj.val = obj.val.toUpperCase();
			}

			if (_orderWeight.col) {
				// add weighting
				if (__pub.items[i][_orderWeight.col] == _orderWeight.val) {
					_numWeights++;
					obj.val = '0' + obj.val;
				} else {
					obj.val = '1' + obj.val;
				}
			}
			if (_dfltOrder.col2) {
				obj.val += __pub.items[i][_dfltOrder.col2];
			}

			_orders[f_key].push(obj);
		}
		_orders[f_key].sort(_f_sort);
	}

	// now produce the opposite ordering

	if (_orders[f_key]) {
		// produce reverse order by going backwards over the forwards order
		orig_key = f_key;
		new_key  = r_key;
	} else {
		// produce forwards order by going backwards over the reverse order
		// (the reverse order can pre-exists the forwards for data whose
		// default ordering is a reverse column)
		orig_key = r_key;
		new_key  = f_key;
	}

	DEBUG('_makeOrder: ' + _par.pub.name + ' (' + new_key + ') reverse of ' + orig_key, 'red');
	var tmp = [];

	// go backwards from end to just before the first weighted, storing in
	// temporary array
	for (i = _orders[orig_key].length - 1; i >= _numWeights; i--) {
		tmp.push({i : _orders[orig_key][i].i});
	}

	// create final array
	_orders[new_key] = [];

	// go backwards from first weighted to beginning, storing in final array
	for (i = _numWeights - 1; i >= 0; i--) {
		_orders[new_key].push({i : _orders[orig_key][i].i});
	}

	// add temporary array onto final array
	for (i = 0; i < tmp.length; i++) {
		_orders[new_key].push(tmp[i]);
	}
}

function getOrderedItems() {

	return _orders[_orderCol.key];
}

function getOrderCol() {

	if (!_orderAttrs[_orderCol.col]) {
		// order col looks dodgy so use default
		_orderCol.col = _dfltOrder.col;
		_orderCol.dir = _dfltOrder.dir;
	} else if (_orderCol.dir != 'f' && _orderCol.dir != 'r') {
		// order dir looks dodgy so use default
		_orderCol.dir = _orderAttrs[_orderCol.col].dfltOrder;
	}

	return _orderCol;
}

function getSelected() {

	return _selected;
}

function setOrderCol(col, dir) {

	if (!_orderAttrs[col]) {
		// order col looks dodgy so use default
		_orderCol.col = _dfltOrder.col;
	} else {
		_orderCol.col = col;
	}

	if (dir != 'f' && dir != 'r') {
		// order dir looks dodgy so use default
		_orderCol.dir = _orderAttrs[_orderCol.col].dfltOrder;
	} else {
		_orderCol.dir = dir;
	}
}

function setVisCols(arr) {

	if (arr.length != _colWidths.colVis.length) {
		alert('setVisCols called badly from ' + _par.pub.name);
		return;
	}

	var ths = _headTR.getElementsByTagName('th');
	var i, numVis = 0, changed = false;

	for (i = 0; i < _colWidths.colVis.length; i++) {
		if (arr[i]) {
			if (!_colWidths.colVis[i]) {
				ths[i].style.display       = '';
				_matchTDs[i].style.display = '';
				_colWidths.colVis[i] = true;
				changed = true;
			}
			numVis++;
		} else {
			if (_colWidths.colVis[i]) {
				ths[i].style.display       = 'none';
				_matchTDs[i].style.display = 'none';
				_colWidths.colVis[i] = false;
				changed = true;
			}
		}
	}

	if (changed) {
		_colWidths.done = false;
	}

	_numVisCols = numVis;
}

function _setupTable () {

	var table = document.getElementById(__pub.els.itemsTabId);

	cleanWhitespace(table);

	var thead = document.getElementById(__pub.els.wrapTabId).getElementsByTagName('thead')[0];

	table.getElementsByTagName('tbody')[2].clickTR    = _clickTR;
	table.getElementsByTagName('tbody')[2].dblClickTR = _dblClickTR;

	_doMatch(thead, table.getElementsByTagName('tbody')[2]);

	_doSort(thead);
}

function _doMatch(thead, tbody) {

	_matchTR = document.createElement('tr');
	sky.addClass(_matchTR, 'match');

	var i, td;
	var ths = thead.getElementsByTagName('th');
	for (i = 0; i < ths.length; i++) {
		if (!_headTR) {
			_headTR = ths[i].parentNode;
		}
		td = document.createElement('td');
		td.innerHTML = '&nbsp;';
		_matchTR.appendChild(td);
		_matchTDs.push(td);
		_colWidths.colVis[i] = true;
	}
	tbody.appendChild(_matchTR);
}

function _doSort(thead) {

	var ths = thead.getElementsByTagName('th');
	var i, sortCol, sortType, txt;

	for (i = 0; i < ths.length; i++) {
		sortCol   = ths[i].getAttribute('sortcol');
		sortType  = ths[i].getAttribute('sorttype');
		sortOrder = ths[i].getAttribute('sortorder');
		tt_title  = ths[i].getAttribute('title');
		if (!tt_title) {
			tt_title = '';
		}
		if (sortCol && sortCol != '') {
			txt = getTextValue(ths[i]);
			ths[i].innerHTML = '<span nothelp="1" title="' + tt_title + '" class="sortheader" sortcol="' + sortCol + '">' + txt + '</span>';
			ths[i].getElementsByTagName('span')[0].onclick = function() {_sortCol(this)};
			ths[i].setAttribute('title','');
			_orderTHs[sortCol] = ths[i];
			if (sortType != 'n' && sortType != 'm' && sortType != 'l' && sortType != 'lt') {
				sortType = 's';
			}
			if (sortOrder != 'r') {
				sortOrder = 'f';
			}
			_orderAttrs[sortCol] = {
				valType   : sortType,
				dfltOrder : sortOrder
			};
		}
	}
}

function matchCols() {

	// nothing to do unless the match tr's width has changed
	var TRWidth = _matchTR.clientWidth;
	if (TRWidth == 0) {
		// some browsers (Opera) don't have clientWidth for tr
		TRWidth = _matchTR.offsetWidth;
	}
	if (TRWidth == 0 || (_colWidths.done && TRWidth == _colWidths.prevTRWidth)) {
		return;
	}
	_colWidths.prevTRWidth = TRWidth;

	var i, width, totalWidth = 0;

	// we'll only pay attention to visible columns
	var visIdxs = [];
	for (i = 0; i < _colWidths.colVis.length; i++) {
		if (_colWidths.colVis[i]) {
			visIdxs.push(i);
		}
	}

	if (!_colWidths.done) {
		// set all but last column to the same width as its head td
		var headTDs = _headTR.getElementsByTagName('th');
		_colWidths.allButLastWidth = 0;
		for (i = 0; i < visIdxs.length - 1; i++) {
			width = headTDs[visIdxs[i]].clientWidth;
			_matchTDs[visIdxs[i]].style.width = width + 'px';
			_colWidths.allButLastWidth += width;
		}
		_colWidths.done = true;
	}

	// set the last column to the remaining width
	for (i = 0; i < visIdxs.length; i++) {
		totalWidth += headTDs[visIdxs[i]].clientWidth;
	}

	width = totalWidth - _colWidths.allButLastWidth;
	_matchTDs[visIdxs[visIdxs.length - 1]].style.width = width + 'px';
}

function scrollToTop() {

	try {
		document.getElementById(__pub.els.itemsTabId).parentNode.scrollTop = 0;
	} catch(e) {}
}

function scrollToTR(tr) {

	try {
		var i, trs, tr_pos, scroll_div, scroll_height, scroll_pos;
		scroll_div = document.getElementById(__pub.els.itemsTabId).parentNode;
		scroll_height = scroll_div.clientHeight;
		scroll_pos = scroll_div.scrollTop;

		trs = tr.parentNode.getElementsByTagName('tr');
		for (i = 0; i < trs.length; i++) {
			if (trs[i] == tr) {
				tr_pos = (i - 1) * tr.clientHeight;
				break;
			}
		}
		if (tr_pos < scroll_pos) {
			scroll_div.scrollTop = tr_pos - tr.clientHeight;
		} else if (tr_pos > scroll_pos + scroll_height - tr.clientHeight) {
			scroll_div.scrollTop = tr_pos - scroll_height + (2 * tr.clientHeight);
		}
	} catch(e) {}
}

function selectItem(tr, id) {

	if (tr != null) {
		if (tr != _selected.tr) {
			sky.addClass(tr, 'selected');
			if (_selected.tr != null) {
				sky.removeClass(_selected.tr, 'selected');
			}
		}
		_selected.tr = tr;
	}
	_selected.id = id;
}

function unselectItem() {

	if (_selected.tr != null) {
		sky.removeClass(_selected.tr, 'selected');
	}
	_selected.id = null;
	_selected.tr = null;
}

function memGetString() {

	var params = [], i;

	params.push(_par.Req.getId());

	params.push(_orderCol.col);
	params.push(_orderCol.dir);

	for (i = 0; i < Filters.length; i++) {
		params.push(Filters[i].memGetString());
	}

	return params.join('|');
}

function memRecover(cookieStr, urlStr, reqFn) {

	var cookieParams = cookieStr.split('|'), i;

	if (cookieStr == '') {
		setOrderCol('', '');
		for (i = 0; i < Filters.length; i++) {
			Filters[i].memRecover('');
		}
	} else {

		setOrderCol(cookieParams[1], cookieParams[2]);

		for (i = 0; i < Filters.length; i++) {
			if (typeof cookieParams[i + 3] == 'undefined') {
				Filters[i].memRecover('');
			} else {
				Filters[i].memRecover(cookieParams[i + 3]);
			}
		}
	}

	if (urlStr != '') {
		reqFn(urlStr);
	} else if (cookieStr != '') {
		reqFn(cookieParams[0]);
	} else {
		reqFn('');
	}
}

	var _this = {
		pub : __pub,
		Paging : Paging,
		Filters : Filters,
		regPar : regPar,
		dispCentre : dispCentre,
		hint : hint,
		suckListData : suckListData,
		takeListData : takeListData,
		shareListDataTake : shareListDataTake,
		shareListDataGive : shareListDataGive,
		render : render,
		dispBody : dispBody,
		matchCols : matchCols,
		getOrderedItems : getOrderedItems,
		getOrderCol : getOrderCol,
		getSelected : getSelected,
		setOrderCol : setOrderCol,
		scrollToTop : scrollToTop,
		scrollToTR : scrollToTR,
		setVisCols : setVisCols,
		selectItem : selectItem,
		unselectItem : unselectItem,
		memGetString : memGetString,
		memRecover : memRecover
	};

	if (Paging) {
		Paging.regPar(_this);
	}
	if (Filters.length) {
		for (i = 0; i < Filters.length; i++) {
			Filters[i].regPar(_this);
		}
	}

	return _this;
}
