
// TableInfo constructor

function TableInfo(name, tId, pageSizeRequested, tReady) {
    this.tableId = tId;

// register the table
    if (typeof(skipjackTables) == "undefined") skipjackTables = new Array();

    skipjackTables[this.tableId] = this;

    this.tableReady = tReady;
    this.pageLoadError = false;
    this.postRenderCallback = null;
    this.tableExpired = false;
    this.outputFmt = "HTML";
    this.serverOpInProgress   = false;
    this.tableName = name;
    this.curPage = 0;
    if (this.tableReady) this.loadedPage = 0;
    this.generatingTableSpan = document.getElementById("__" + this.tableName + "_generatingTableSpan");
    this.container    = document.getElementById("__" + this.tableName + "_span");
    this.dragDiv      = document.getElementById("__" + this.tableName + "_dragDiv");
    this.csvForm      = document.getElementById("__" + this.tableName + "_csvForm");
    this.settingsForm = document.getElementById("__" + this.tableName + "_settingsForm");

    this.checkBoxOff  = "/skipjack/images/checkbox/box-empty-16.gif";
    this.checkBoxOn   = "/skipjack/images/checkbox/box-black-x-16.gif";

    this.browserInfo = getBrowserInfo();    
    this.sortDir = "ASC";
    this.rowsInitialized = false;

    if (this.csvForm["tableId"].value == "") {
	this.csvForm["tableId"].value = this.tableId;
    } 

    this.wasRefresh = this.csvForm["tableId"].value != this.tableId;
    
    if (this.wasRefresh) {
	this.csvForm["tableId"].value = this.tableId;
	this.settingsForm["tableExpired"].value = "false";
    }

    this.pageSize = (1 * pageSizeRequested);
    
    this.parseResponse = function(text) {

	var resp = new Object();
	resp.page = this.page;

	var idx = text.indexOf("\n");
	var line = text.substring(0,idx);
	var status = line.split("|");
	
	if (status.length < 4) {
	    resp.status = "UNKERROR";
	    resp.statusText = "Unknown error.";
	} else if (status[1] != "OK") {
	    resp.status = status[1];
	    resp.statusText  = status[2];
	} else {
	    resp.status = status[1];	    
	    this.container.innerHTML = text;
	    if (this.titleType == "GROUP") {
		var t = document.getElementById("__" + this.tableName + "_table");
		var i = 0;
		var box = this.totalContainer;
		while (box.tagName != "TABLE" && i < this.totalContainer.childNodes.length) {
		    box = this.totalContainer.childNodes[i++];
		}

		if (box.style.width > 0 && t.offsetWidth + 12 > box.style.width) box.style.width = t.offsetWidth + 12;
	    }
	    
	    if (typeof(this.filterInput) != "undefined" && this.filterInput != null) {
		var input = document.getElementById(this.filterInput);
		if (input != null && typeof(input) != "undefined") {
		    window.setTimeout("skipjackTables['" + this.tableId + "'].focusOnInput(document.getElementById('" + this.filterInput + "'));", 100);
		}
	    }

	    this.generatingTableSpan.style.display = 'none';
	    if (this.showCSV == "true") {
		document.getElementById("__" + this.tableName + "_csvLink").style.display = '';
	    }
	}

	return resp;
    }

    this.focusOnInput = function(input) {
	input.focus();
	if (this.browserInfo.IE) {
	    var range = input.createTextRange();
	    range.collapse(false);
	    range.select();
	}
	this.filterInput = null;
    }

    this.loadPageErrorHandler = function (tx) {
	var tableInfo = tx.tableInfo;

	var msg = tableInfo.wasErrorText + " " + tableInfo.needRefreshText + "\n\nServer Response:\n" + tx.errorMsg;
	
	if (tx.errorType == "UNSUPPORTED") {
	    msg = tableInfo.unsupportedText;
	}
	
	alert(msg);
	tableInfo.setMessage(tableInfo.errorMsgText);
	tableInfo.pageLoadError = true;
	tableInfo.setInProgress(false);
    }

    this.numSelectedSpan = function() {
	return document.getElementById("__" + this.tableName + "_numSelectedSpan");
    }

    this.filterRow = function() {
	return document.getElementById("__" + this.tableName + "_filterRow");
    }

    this.headerRow = function() {
	return document.getElementById("__" + this.tableName + "_headerRow");
    }

    this.loadPage = function(force) {
	if (this.serverOpInProgress || this.pageLoadError || this.tableExpired) return;
	
	if (this.curPage == this.loadedPage && !force) return;

	this.setInProgress(true);

	this.loadStart = new Date();

	var tx = new Transaction();
	tx.setContentType("text/plain");
	tx.setParam("tableId", this.tableId);
	tx.setParam("startRow", this.pageSize * this.curPage);
	tx.setParam("rowCount", this.pageSize);
	tx.setParam("outputFmt", this.outputFmt);
	if (typeof(this.sortCol) == "undefined") {
	    tx.setParam("sortCol", -1);
	} else {
	    tx.setParam("sortCol", this.sortCol);
	}
	if (typeof(this.sortDir) == "undefined") {
	    tx.setParam("sortDir", "ASC");
	} else {
	    tx.setParam("sortDir", this.sortDir);	    
	}

	tx.setParam("showFilter", this.showRowFilter);
	tx.setParam("viewName", this.curViewName);
	if (this.visCols.length == 0) {
	    tx.setParam("cols", "NONE");
	} else {
	    tx.setParam("cols", this.visCols.join(","));
	}

	tx.setErrorHandler(this.loadPageErrorHandler);
	tx.collectTimes = true;

	var i;
	
	for (i = 0; i < this.cols.length; i++) {
	    tx.setParam("filter" + i, this.settingsForm["filter" + i].value);
	}
	
	this.storeViewSettings();

	tx.tableInfo = this;
	tx.execute("/skipjack/tableMgr/data.tdf", this.finishPageLoad);
    }

    this.finishPageLoad = function (tx) {
	var tableInfo = tx.tableInfo;

	tableInfo.txPrepTime = tx.startTx.getTime() - tx.startPrep.getTime();
	tableInfo.txCallTime = tx.endTx.getTime() - tx.startTx.getTime();
	tableInfo.parsePageStart = new Date();

	var resp = tableInfo.parseResponse(tx.responseText);
	if (resp.status == "OK") {
	    tableInfo.page = resp.page;
	    tableInfo.loadedPage = tableInfo.curPage;
	} else if (resp.status == "BADFILTER") {
	    var msg = resp.statusText.replace(/:/g,":\n\n");
	    alert(msg);	    
	} else if (resp.status == "UNKERROR") {
	    alert(tableInfo.wasErrorText + " " + tableInfo.needRefreshText);
	    tableInfo.showErrorResponse(tx.responseText);
	} else if (resp.status == "ERROR" && resp.statusText == "DELETED") {		
	    alert(tableInfo.tableExpiredText + " " + tableInfo.needRefreshText);
	    tableInfo.tableExpired = true;
	    tableInfo.settingsForm["tableExpired"].value = true;
	    tableInfo.setMessage(tableInfo.expiredMsgText);
	} else {
	    alert(tableInfo.wasErrorText + " " + tableInfo.needRefreshText + "\n\nServer Response:\n" + tx.responseText);
	    tableInfo.pageLoadError = true;
	}


	tableInfo.setInProgress(false);
	
	tableInfo.loadEnd = new Date();
	
	if (tableInfo.postRenderCallback != null) {
	    tableInfo.postRenderCallback(tableInfo);
	}
    }
    
    this.setPageSize = function (pageSizeRequested) {
	this.pageSize = 1 * pageSizeRequested;
    }    
    
    this.setInterval = function(expr, millis) {

	if (typeof(this.intervals) == "undefined") {
	    this.intervals = new Array();
	}

	this.intervals[this.intervals.length] = window.setInterval(expr, millis);
    }

    this.clearIntervals = function() {

	if (typeof(this.tableGenIntervalID) != "undefined" && this.tableGenIntervalID != null) {
	    window.clearInterval(this.tableGenIntervalID);
	}
	
	if (typeof(this.intervals) == "undefined") return;
	var i;
	for (i = 0; i < this.intervals.length; i++) {
	    window.clearInterval(this.intervals[i]);
	}	
    }

    this.create = function() {
	if (!this.tableReady) {
	    this.tableGenWait();
	} else {
	    if (this.loadViewSettings()) {
		this.setViewChangeMsg();
		this.loadPage(true);
	    }
	}
	    
    }

    this.getViewNum = function (viewName) {
	var viewNum;
	
	for (viewNum = 0; viewNum < this.views.length; viewNum++) {
	    if (this.views[viewNum].viewName == viewName) {
		break; 
	    }
	}
	
	// if it's an invalid view
	if (viewNum == this.views.length) return -1;
	
	return viewNum;
    }

    this.loadViewSettings = function() {
	if (this.settingsForm["settingsInitialized"].value != "Y") return false;

	var dirty = false;
	var val = parseInt(this.settingsForm["curPage"].value);
	if (val != this.curPage) {
	    this.curPage = val;
	    dirty = true;
	}
	
	if (this.settingsForm["sortCol"].value != "") {
	    val = parseInt(this.settingsForm["sortCol"].value);
	} else {
	    val = -1;
	}

	if (this.sortCol != val) {
	    this.sortCol = val;
	    dirty = true;
	}

	val = this.settingsForm["sortDir"].value;
	if (this.sortDir != val) {
	    this.sortDir = val;
	    dirty = true;
	}

	val = this.settingsForm["curViewName"].value;
	if (this.curViewName != val) {
	    this.curViewName = val;
	    dirty = true;
	}

	val = this.settingsForm["showRowFilter"].value;
	if (this.showRowFilter != val) {
	    this.showRowFilter = val;
	    dirty = true;
	}

	val = parseInt(this.settingsForm["pageSize"].value);
	if (this.pageSize != val) {
	    this.pageSize = val;
	    dirty = true;
	}

	val = this.settingsForm["visCols"].value.split(",");
	if (this.visCols.length != val.length) {
	    this.visCols = val;
	    dirty = true;
	} else {
	    for (i = 0; i < this.visCols.length; i++) {
		if (this.visCols[i] != val[i]) {
		    this.visCols = val;
		    dirty = true;
		    break;
		}
	    }
	}
	
	var filt;
	for (i = 0; i < this.visCols.length; i++) {
	    if (!this.visCols[i] || this.visCols[i] == "") continue;
	    if (this.filterRow() != null && this.filterRow().cells[i + this.leftCols] != null) {
		val = this.settingsForm["filter" + this.visCols[i]].value;
		filt = this.filterRow().cells[i + this.leftCols].firstChild;
		if (filt.value != val) {
		    filt.value = val;
		    dirty = true;
		}
	    }
	}	    
		
	this.updateViewMenu(this.curViewName);
	this.updateColumnMenu();

	return dirty;
    }

    this.tableGenWait = function() {
	if (this.settingsForm["tableExpired"].value == "true") {
	    this.tableExpired = true;
	    this.generatingTableSpan.innerHTML = this.tableExpiredText + " " + this.needRefreshText;	    
	} else {	
	    this.tableGenIntervalID = window.setInterval("skipjackTables['" + this.tableId + "'].tableGenCheck()", this.tableGenCheckInterval);
	    // try right away
	    this.tableGenCheck(); 
	}	
    }

    this.clearTableCheck = function() {
	if (typeof(this.tableGenIntervalID) != "undefined" && this.tableGenIntervalID != null) {
	    var id = this.tableGenIntervalID;
	    this.tableGenIntervalID = null;
	    window.clearInterval(id);
	}
    }

    this.tableGenCheck = function() {
	
	if (this.tableGenIntervalID == null) return;
	
	var tx = new Transaction();
	
	tx.setParam("tableId", this.tableId);	
	tx.setErrorHandler(this.tableGenCheckErrorHandler);
	tx.tableInfo = this;
	
	tx.execute(this.tableGenCheckTx, this.tableGenCheckCompletion);
    }
    
    this.tableGenCheckErrorHandler = function(tx) {
	var tableInfo = tx.tableInfo;
	if (tableInfo.tableGenIntervalID == null) return;
	tableInfo.clearTableCheck();
	var msg = tableInfo.generateTableErrorText + tx.errorMsg;
	
	if (tx.errorType == "UNSUPPORTED") {
	    msg = tableInfo.unsupportedText;
	}
	
	tableInfo.generatingTableSpan.innerHTML = msg;
    }
    
    this.cancelGen = function() {
	if (this.tableGenIntervalID == null) return;

	this.clearTableCheck();
	this.generatingTableSpan.innerHTML = this.genCancelText;
	var tx = new Transaction();

	tx.setParam("tableId", this.tableId);
	tx.setErrorHandler(function(tx) { return; });
	tx.execute(this.genCancelTx, function(tx) { return; });
    }


    this.tableGenCheckCompletion = function(tx) {
	var tableInfo = tx.tableInfo;
	
	if (tableInfo.tableGenIntervalID == null) return;

	var map = tx.getResultMap();

	if (map["wasError"] == true) {
	    tableInfo.clearTableCheck();	    
	    tableInfo.generatingTableSpan.innerHTML = tableInfo.generateTableErrorText + tx.responseText;
	} else if (map["output.tableReady"] == "true") {
	    tableInfo.clearTableCheck();
	    
	    tableInfo.tableReady = true;
	    if (1 * map["output.dataRows"] > 0) {
		tableInfo.loadPage(tableInfo.loadViewSettings());
	    } else {
		tableInfo.generatingTableSpan.innerHTML = tableInfo.noRowsMsg;
	    }
	} else if (map["output.tableExpired"] == "true") {
	    tableInfo.clearTableCheck();
	    tableInfo.tableExpired = true;
	    tableInfo.settingsForm["tableExpired"].value = true;
	    tableInfo.generatingTableSpan.innerHTML = tableInfo.tableExpiredText + " " + tableInfo.needRefreshText;	    
	} else if (map["output.tableError"] == "true") {
	    tableInfo.clearTableCheck();
	    
	    tableInfo.generatingTableSpan.innerHTML = tableInfo.generateTableErrorText + map["output.errorMsg"];
	}
    }
    
    
    this.getColId = function(colName) {
	var i; 
	for (i = 0; i < this.cols.length; i++) {
	    if (this.cols[i].name == colName) {
		return i;
	    }
	}
	
	return -1;
    }
    

    /**
     *
     * setSortColumn(colName) sets the sort column based
     * on the column name.
     *
     **/
    
    this.setSortColumn = function(colName) {
	this.sortCol = this.getColId(colName);
    }

    /**
     *
     * setFilter(colName, filterVal) sets the sort column based
     * on the column name.
     *
     **/

    this.setFilter = function(colName, filterVal) {
	var colId = this.getColId(colName);
	if (colId > -1) {
	    var inp = document.getElementById("__" + this.tableName + "_filterInput_" + colId);
	    if (typeof(inp) != "undefined" && inp != null)
		inp.value = filterVal;
	    this.settingsForm["filter" + colId].value = filterVal;
	}
    }

    this.showViewMenu = function () {
	var vm = document.getElementById("__" + this.tableName + "_viewMenu");
	vm.style.left = findPosX(this.headerRow().cells[0]) - this.borderWidth;
	vm.style.top = findPosY(this.headerRow().cells[0]) - this.borderWidth;
	
	vm.style.display = 'block';
    }

    this.hideViewMenu = function () {
	var vm = document.getElementById("__" + this.tableName + "_viewMenu");
	vm.style.display = "none";	
    }

    this.showColumnMenu = function () {
	var cm = document.getElementById("__" + this.tableName + "_columnMenu");
	var vm = document.getElementById("__" + this.tableName + "_viewMenu");
	var item = document.getElementById("__" + this.tableName + "_columnMenuChoice");

	cm.style.left = findPosX(vm);
	cm.style.top = findPosY(vm);
	cm.style.display = 'block';
	
	//	alert(cm.offsetHeight);
	//	if (cm.offsetHeight > document.body.offsetHeight - 80) {
	//	    cm.style.height = document.body.offsetHeight - 80;
	//	}

	this.hideViewMenu();
    }

    this.hideColumnMenu = function () {
	var cm = document.getElementById("__" + this.tableName + "_columnMenu");
	cm.style.display = 'none';
    }

    this.applyColumnMenu = function () {
	if (this.inProgress()) return;

	this.hideColumnMenu();

	this.setMessage(this.colDisplayChangeText);

	this.visCols = new Array();
	
	var i = 0;
	for (i = 0; i < this.viewCols.length; i++) {
	    var colName = this.cols[this.viewCols[i]].name;
	    var img = document.getElementById("__" + this.tableName + "_columnMenu_" + colName);
	    if (img && sameLastToken("/",img.src,this.checkBoxOn))
		this.addVisCol(colName, this.viewCols[i]);
	
	}
	
	for (i = 0; i < this.defaultVisCols.length; i++) {
	    if (!arrayContains(this.viewCols, this.defaultVisCols[i])) {
		this.addVisCol(this.cols[this.defaultVisCols[i]].name, this.defaultVisCols[i]);
	    }
	}

	this.storeViewSettings();
	this.loadPage(true);
    }

    this.cancelColumnMenu = function () {
	this.hideColumnMenu();
	this.updateColumnMenu();
    }

    this.addVisCol = function (colName, colId) {
	if (colId <= -1) return;

	// just return if this col is already visible
	
	for (i = 0; i < this.visCols.length; i++) if (this.visCols[i] == colId) return;
	
	
	// if not, put it in in the right place
	var found = false;
	var img;
	for(i = 0; i < this.visCols.length; i++) {
	    if (this.cols[colId].position < this.cols[this.visCols[i]].position) {
		found = true;
		this.visCols.splice(i,0,colId);
		img = document.getElementById("__" + this.tableName + "_columnMenu_" + colName);
		if (img != null) img.src = this.checkBoxOn;
		break;
	    }
	}
	
	if (!found) {
	    this.visCols[this.visCols.length] = colId;
	    img = document.getElementById("__" + this.tableName + "_columnMenu_" + colName)
	    if (img != null) img.src = this.checkBoxOn;
	}		    
    }	

    this.toggleColumn = function(colName) {
	img = document.getElementById("__" + this.tableName + "_columnMenu_" + colName);
	if (img != null) {
	    if (sameLastToken("/",img.src,this.checkBoxOn)) {
		img.src = this.checkBoxOff;
	    } else {
		img.src = this.checkBoxOn;
	    }
	}       
    }

    this.updateColumnMenu = function() {
	var i, img;
	for (i = 0; i < this.viewCols.length; i++) {
	    img = document.getElementById("__" + this.tableName + "_columnMenu_" + this.cols[this.viewCols[i]].name);
	    img.src = this.checkBoxOff;
	}
	for (i = 0; i < this.visCols.length; i++) {
	    img = document.getElementById("__" + this.tableName + "_columnMenu_" + this.cols[this.visCols[i]].name);
	    if (img != null) {
		img.src = this.checkBoxOn;
	    } 
	}
    }

    this.changeView = function (viewName) {
	this.hideViewMenu();
	       
	this.setViewChangeMsg();

        if (this.applyViewSettings(viewName)) this.loadPage(true);
    }

    this.applyViewSettings = function (viewName) {
	var attr, i;

	var viewNum = this.getViewNum(viewName);
	
	// just return if it's an invalid view
	if (viewNum == -1) return false;

	// clear the filters

	this.clearFilters();

	// set all the view settings	
	view = this.views[viewNum];
	for (attr in view) {
	    if (attr.charAt(0) != "_") {
		if (attr == "orderBy") {
		    this.sortCol = this.getColId(view[attr]);
		} else if (attr == "orderByDir") {
		    if (view[attr] == "ASC" || view[attr] == "DESC") {
			this.sortDir = view[attr];
		    } else {
			this.sortDir = "ASC";
		    }
		} else if (attr == "pageSize") {
		    this.setPageSize(view[attr]);
		} else if (attr.indexOf("filter_") == 0) {		
		    this.setFilter(attr.substr("filter_".length), view[attr]);
		} else if (attr.indexOf("vis_") == 0) {
		    // do nothing here, handled below
		} else {	    
		    this[attr] = view[attr];
		}
	    }
	}       	    

	this.setVisCols(view);
	
	// update visibility indicators
	this.updateColumnMenu();		

	// always go back to first page when the view changes
	
	this.curPage = 0;
	
	// change selected view in menu
	this.updateViewMenu(viewName);

	return true;
    }

    this.clearFilters = function() {
	for (i = 0; i < this.cols.length; i++) this.settingsForm["filter" + i].value = "";
	if (this.filterRow() && this.filterRow().cells) {
	    var cells = this.filterRow().cells;
	    for (i = this.leftCols; i < cells.length; i++) {
		cells[i].firstChild.value = "";
	    }
	}
    }

    this.setVisCols = function(view) {
	var visFoundInd = false;
	this.visCols = new Array();
	
	for (attr in view) {
	    if (attr.indexOf("vis_") == 0) {
		visFoundInd = true;
		if (view[attr] == "true") {
		    var colName = attr.substr("vis_".length);
		    this.addVisCol(colName, this.getColId(colName));
		}
	    }
	}
	
	// backward compatibilty for views that don't have visibility info
	
	if (!visFoundInd) {
	    this.visCols = this.defaultVisCols;
	}
    }

    this.deleteView = function (viewName) {
	var i, j;
	for (i = 0; i < this.views.length; i++) {
	    if (this.views[i].viewName == viewName) {
		this.views.splice(i,1);
		var viewRows = document.getElementById("__" + this.tableName + "_viewMenuTable").rows;
		
		for (j = 0; j < viewRows.length && viewRows[j].getAttribute("isViewRow") == "1"; j++)
		    if (viewRows[j].getAttribute("viewName") == viewName) {
			var t = viewRows[j].parentNode;
			t.deleteRow(j);
			break;
		    }
		break;
	    }
	}

	if (viewName == this.curViewName) {
	    this.changeView(this.standardView, false);
	}
    }
    
    this.getPropertiesFormURL = function (newView) {
	var editStdView = this.curViewName == this.standardView && !newView;
	var stdView = this.views[this.getViewNum(this.standardView)];

	var href = this.propertiesFormURL +
	"?tableId=" + 
	this.tableId +
	"&tableName=" + 
	this.qualifiedTableName +
	"&pageSize=";
	
	if (editStdView) {
	    href += stdView.pageSize + "&showRowFilter=" + stdView.showRowFilter;

	    if (typeof(stdView.sortCol) != "undefined" && stdView.sortCol != -1) {
		href += "&sortColumn=" + escape(this.cols[stdView.sortCol].name);
		href += "&sortDirection=" + stdView.sortDir;
	    }
	    
	} else {
	    href += this.pageSize + "&showRowFilter=" + this.showRowFilter;
	    
	    if (typeof(this.sortCol) != "undefined" && this.sortCol != -1) {
		href += "&sortColumn=" + escape(this.cols[this.sortCol].name);
		href += "&sortDirection=" + this.sortDir;
	    }
	    
	}
	
	if (this.useCategories) {
	    href += "&categoryName=" + escape(this.categoryName);
	    href += "&categoryLabel=" + escape(this.categoryLabel);
	}
	
	var i, filters, vis, colId;
	filters = "&";
	vis = "";
	for (i = 0; i < this.viewCols.length; i++) {
	    colId = this.viewCols[i];
	    if (editStdView) {
		filters += "f" + colId + "=&";
	    } else {		
		filters += "f" + colId + "=" + escape(this.settingsForm["filter" + this.viewCols[i]].value) + "&";
	    }
	}
	
	if (editStdView) {
	    vis = this.defaultVisCols.join(",");
	} else {
	    vis = this.visCols.join(",");
	}
	
	href += filters + "v=" + vis + "&";
	
	var cols = "";

	for (i = 0; i < this.orderByFields.length; i++) {
	    if (i > 0) cols += ",";
	    cols += this.getColId(this.orderByFields[i]);
	}
		
	if (cols != "") {
	    href += "s=" + cols + "&";
	} 
	
	if (newView) {
	    href += "mode=create";
	} else {
	    href += "mode=update&viewName=" + escape(this.curViewName);
	}
	
	if (this.curViewName == this.defaultViewName && !newView) {
	    href += "&makeDefault=on";
	}
	
	if (href.length > 2048) {
	    alert("Properties form URL is " + href.length + " characters!");
	}

	return href;	
    }


    this.showPropertiesWindow = function (newView) {
	this.storeFilters();
	var href = this.getPropertiesFormURL(newView);
	this.hideViewMenu();
	
	var height = 420 + this.viewCols.length * 32;
	var maxHeight = screen.availHeight - 80;

	if (height > maxHeight) height = maxHeight;

	showWindow(href,"Props", 500, height,'yes','yes');
    }
    
    this.createViewObj = function () {
	return new Object();
    }
    
    this.setInProgress = function(prog) {
	this.serverOpInProgress = prog;
    }

    this.inProgress = function () {
	if (this.serverOpInProgress) {
	    alert(this.inProgressText);
	    return true;
	} else if (this.pageLoadError) {
	    alert(this.wasErrorText + " " + this.needRefreshText);
	    return true;
	} else if (this.tableExpired) {
	    alert(this.tableExpiredText + " " + this.needRefreshText);
	    return true;
	}
	
	return false;
    }

    this.getMessageHTML = function() {
	var span = document.getElementById("__" + this.tableName + "_pageInfoSpan");
	if (span != null) return span.innerHTML;
        return "";
    }

    this.setMessage = function(msg) {
	var span = document.getElementById("__" + this.tableName + "_pageInfoSpan");
	if (span != null) span.innerHTML = msg;
    }

    this.setPagingMsg = function() {
	this.setMessage(this.pagingText);
    }

    this.setSortingMsg = function() {
	this.setMessage(this.sortingText);
    }

    this.setFilteringMsg = function() {
	this.setMessage(this.filteringText);
    }

    this.setViewChangeMsg = function() {
	this.setMessage(this.viewChangeText);
    }

    this.gotoPage = function (pageNo) {
	if (this.inProgress()) return;
	this.setPagingMsg();
	
	if (pageNo < 0) pageNo = 0; 
	
	this.curPage = pageNo;
	
	this.loadPage(false);
    }
    
    this.cellMousedown = function(e) { 
	    if (!e) var e = window.event;
	    var t;
	    if (e.target)t = e.target; 
	    else if (e.srcElement) t = e.srcElement; 
	    else return;
	    
	    if (t.nodeType == 3) t = t.parentNode; 
	    
	    if (typeof(t.isHeaderCell) == "undefined" || !t.isHeaderCell)
	    return true;

	    if (!t.tableInfo.allowColumnMove) return true;

	    var row = t.parentNode;
	    var i;
	    for (i = t.tableInfo.leftCols; i < row.cells.length; i++)
	    if (t == row.cells[i]) break;
	    document.dragCol = i - t.tableInfo.leftCols;
	    document.dragTargetCol = i - t.tableInfo.leftCols;
	    document.dragTable = t.tableInfo;
	    document.onmousemove = handleMoveDrag;
	    document.onmouseup = endMoveDrag;
	    return false;
    }	
    
    this.moveColumn = function(moveFrom, moveTo) {
	if (moveFrom == moveTo) return;
		
    }    

    this.toCSV = function (allData) {
	this.hideViewMenu();
	
	if (allData) {
	    this.csvForm["all"].value = 1;
	} else {
	    this.csvForm["all"].value = 0;
	}
	
	this.csvForm["cols"].value = this.csvCols.join(",");
	this.csvForm["outputFmt"].value = "CSV";
	this.csvForm["contentType"].value = this.csvForm["csvContentType"].value;
	this.csvForm.action = this.csvActionURL;
		
	this.csvForm.submit();	
    }

    this.toPDF = function (allData) {
	this.hideViewMenu();
	
	if (allData) {
	    this.csvForm["all"].value = 1;
	} else {
	    this.csvForm["all"].value = 0;
	}
	
	this.csvForm["cols"].value = this.visCols.join(",");
	this.csvForm["outputFmt"].value = "PDF";
	this.csvForm["contentType"].value = this.csvForm["pdfContentType"].value;	
	this.csvForm.action = this.pdfActionURL;
	this.csvForm.submit();	
    }
        
            
    this.callRowSelectTx = function(state, indexVal, oldHTML) {
	if (this.rowSelectTx != "") {
	    var tx = new Transaction();
	    tx.setParam(this.rowSelectParamName, indexVal);
	    tx.setParam("selectState", state);
	    tx.setErrorHandler(this.rowSelectTxErrorHandler);
	    tx.tableInfo = this;
            tx.oldHTML = oldHTML;

	    tx.execute(this.rowSelectTx, this.rowSelectTxCompletion);
	} else {
	    this.setInProgress(false);
	    this.setMessage(oldHTML);
        }
    }

    this.rowSelectTxErrorHandler = function (tx) {
	var tableInfo = tx.tableInfo;
	var msg = tableInfo.rowSelectTxErrorText + "\n\n" + tx.errorMsg;
	
	alert(msg);
    }

    this.rowSelectTxCompletion = function (tx) {
	var tableInfo = tx.tableInfo;

	var map = tx.getResultMap();
	if (map["wasError"]) {
	    if (confirm("The server returned invalid data. Click OK to see the server response.")) {
		tableInfo.showErrorResponse(tx.responseText);
	    }
	} else if (map["tx.status"] != "100 Transaction Successful") {
	    var msg = tableInfo.rowSelectTxErrorText + "\n\n" + map["tx.status"] + "\n\n" + map["tx.errorMsg"];
	    alert(msg);
	}	

	tableInfo.setInProgress(false);
        tableInfo.setMessage(tx.oldHTML);
    }

    this.getRowSelectInfo = function(rowNum) {
	var state = "on";
	var img = document.getElementById("__" + this.tableName + "_rowSelectImg_" + rowNum);
	if (typeof(img) == "undefined" || img == null) return null;
	
	if (sameLastToken("/",img.src,formRowSelectOffImage)) state = "off";
	
	return new Array(state, img.getAttribute("value"), img);
    }

    this.rowSelectToggle = function(rowNum) {
	
	if (this.inProgress()) return;
	this.setInProgress(true);

	var rsInfo = this.getRowSelectInfo(rowNum);

	if (rsInfo == null) return;
	
	var oldHTML = this.getMessageHTML();
        this.setMessage(this.rowSelectText);

	var state = "on";
	if (rsInfo[0] == "on") state = "off";
	var val = rsInfo[1];

	var tx = new Transaction();
	tx.setParam("tableId", this.tableId);
	tx.setParam("type", "value");
	tx.setParam("state", state);
	tx.setParam("value", val);
	
	tx.execute("/skipjack/tableMgr/select.tdf", function() { return; });

	this.callRowSelectTx(state, val, oldHTML);
	
	var numSpan = this.numSelectedSpan();
	var numSelected = (1 * numSpan.innerHTML);
	if (state == "off") {
	    numSelected -= 1;
	    rsInfo[2].src = formRowSelectOffImage;
	} else {
	    numSelected += 1;
	    rsInfo[2].src = formRowSelectOnImage;
	}
	
	numSpan.innerHTML = numSelected;
    }
    
    this.rowSelectPage = function(state) {

	if (this.inProgress()) return;
	this.setInProgress(true);

	var oldHTML = this.getMessageHTML();
        this.setMessage(this.rowSelectText);

	var startRow = this.curPage * this.pageSize;
	var tx = new Transaction();
	tx.setParam("tableId", this.tableId);
	tx.setParam("type", "all");
	tx.setParam("state", state);
	tx.setParam("startRow", startRow);
	tx.setParam("rowCount", this.pageSize);
	
	tx.execute("/skipjack/tableMgr/select.tdf", function() { return; });

	var numSpan = this.numSelectedSpan();
	var numSelected = (1 * numSpan.innerHTML);

	// figure out which changed state
	var i, rsInfo;
	changed = new Array();
	for (i = startRow + 1; i <= this.pageSize + startRow; i++) {
	    rsInfo = this.getRowSelectInfo(i);
	    if (rsInfo != null && rsInfo[0] != state) {
		changed[changed.length] = rsInfo[1];	
		if (state == "off") {
		    numSelected -= 1;
		    rsInfo[2].src = formRowSelectOffImage;
		} else {
		    numSelected += 1;
		    rsInfo[2].src = formRowSelectOnImage;
		}
	    }    
	}       	
	
	if (changed.length > 0) {
	    this.callRowSelectTx(state, changed.join(","), oldHTML);
	    numSpan.innerHTML = numSelected;
	} else {
	    this.setMessage(oldHTML);
 	    this.setInProgress(false);
	}
    }


    this.showErrorResponse = function(responseText) {
	var features = "menubar=no";
	features += ",toolbar=no";
	features += ",height=500";
	features += ",width=600";
	features += ",resizable=yes";
	features += ",scrollbars=yes";
	
	var win = window.open ("", "ErrorWindow", features);
	
	win.document.write(responseText);

	win.focus();
    }

    this.updateViewMenu = function(viewName) {
	var viewRows = document.getElementById("__" + this.tableName + "_viewMenuTable").rows;
	
	var i;
	for (i = 0; i < viewRows.length && viewRows[i].getAttribute("isViewRow") == "1"; i++) {
	    if (viewRows[i].getAttribute("viewName") == viewName) {
		viewRows[i].cells[0].innerHTML = this.itemSelectedGlyph;
	    } else {
		viewRows[i].cells[0].innerHTML = "";
	    }
	}

	this.curViewName = viewName;
    }


    //
    // Stores the current settings in the form
    // so the back button will work as expected
    //
    
    this.storeViewSettings = function() {    
	this.settingsForm["curPage"].value = this.curPage;
	if (typeof(this.sortCol) != "undefined") {
	    this.settingsForm["sortCol"].value = this.sortCol;
	    this.settingsForm["sortDir"].value = this.sortDir;
	}
	this.settingsForm["curViewName"].value = this.curViewName;
	this.settingsForm["showRowFilter"].value = this.showRowFilter;
	this.settingsForm["pageSize"].value = this.pageSize;
	this.settingsForm["visCols"].value = this.visCols;
	
	this.storeFilters();
	
	this.settingsForm["settingsInitialized"].value = "Y";
    }

    this.storeFilters = function() {
	var inp;
	for (i = 0; i < this.visCols.length; i++) {		
	    inp = document.getElementById("__" + this.tableName + "_filterInput_" + this.visCols[i]);
	    if (inp) this.settingsForm["filter" + this.visCols[i]].value = inp.value;
	}
    }

    this.updateView = function(viewInfo) {
	var i;
	for (i = 0; i < this.views.length; i++)
	if (this.views[i].viewName == viewInfo.viewName) {
	    this.views[i] = viewInfo;
	    break;
	}
	
	// if we didn't find it, add it
	if (i == this.views.length) {
	    this.views[this.views.length] = viewInfo;
	    var lc = viewInfo.viewName.toLowerCase();
	    var viewRows = document.getElementById("__" + this.tableName + "_viewMenuTable").rows;

	    for (i = 0; i < viewRows.length && viewRows[i].getAttribute("isViewRow") == "1"; i++) {
		if (viewRows[i].getAttribute("viewName").toLowerCase() > lc) break;
	    }

	    var vmt = document.getElementById("__" + this.tableName + "_viewMenuTable");
	    createViewRow(this,vmt,i,viewInfo.viewName);
	}
    }

    this.filter = function() {
	this.setFilteringMsg();
	this.storeFilters();
	this.curPage = 0;
	this.loadPage(true);
    }
    
    this.sort = function(newSortCol) {
	if (this.inProgress()) return;    
        
	this.setSortingMsg();
	
	if (this.sortCol != newSortCol) {
	    this.sortDir = this.cols[newSortCol].initialSortDir;
	} else {
	    this.sortDir = this.sortDir == "ASC" ? "DESC" : "ASC";
	}
        
	this.sortCol = newSortCol;
	
	this.loadPage(true);
    }

    this.handleContextClick = function(menuId, e) {	
	if (!e) var e = window.event;
	
	var t;
	if (e.target)t = e.target; 
	else if (e.srcElement) t = e.srcElement; 
	else return;
	
	if (t.nodeType == 3) t = t.parentNode; 
	
	if (e.button && (e.button == 2 || e.button == 3)) {
	    showContextMenu(menuId,t);
	    return false;
	}
	
	if (e.which && (e.which == 2 || e.which == 3)) {
	    showContextMenu(menuId,t);
	    return false;
	}

	return true;
    }
}

function showContextMenu(id,t) {
    var menu = document.getElementById(id);
    if (menu != null) {
	menu.style.left = findPosX(t) - 6;
	menu.style.top = findPosY(t) - 6;
	menu.style.display = 'block';
    } else {
	alert("Context menu not found.");
    }
}

function hideContextMenu(id,t) {
    var menu = document.getElementById(id);
    if (menu != null) {
	menu.style.display = 'none';
    } else {
	alert("Context menu not found.");
    }
}

function handleResizeDrag(e) {
    if (!e) var e = window.event;
    var t;
    if (e.target)t = e.target; 
    else if (e.srcElement) t = e.srcElement; 
    else return;
    
    if (t.nodeType == 3) t = t.parentNode; 

    var tableInfo = document.dragTable;
    var dragCol = document.dragCol;

    // find which column we are in 
    var i = 0;
    var newCol = 0;
    var newColLeft = -1;
    var newColTop  = -1;
    var colLeft;
    for (i = tableInfo.leftCols; i < tableInfo.headerRow().cells.length; i++) {
	colLeft = findPosX(tableInfo.headerRow().cells[i]);	
	if (colLeft < e.clientX) {
	    newColLeft = colLeft;
	    newCol = i - tableInfo.leftCols;
	}
	if (newColLeft == -1)
	    newColLeft = colLeft;
	if (newColTop == -1)
	    newColTop = findPosY(tableInfo.headerRow().cells[i]);
    }

    colLeft = colLeft + tableInfo.headerRow().cells[i-1].offsetWidth;
    if (colLeft < e.clientX) {
	newColLeft = colLeft;
	newCol++;
    }

    if (dragCol < newCol)
	newCol--;

    tableInfo.dragDiv.style.left = newColLeft - tableInfo.borderWidth;
    tableInfo.dragDiv.style.top  = newColTop;
    tableInfo.dragDiv.style.height = tableInfo.tableElem.offsetHeight - (newColTop - findPosY(tableInfo.tableElem)) - tableInfo.borderWidth;
    if (tableInfo.dragDiv.style.display == 'none')
	tableInfo.dragDiv.style.display = '';

    document.dragTargetCol = newCol;
    return false;
}

function endResizeDrag(e) {
    document.onmousemove = null;
    document.onmouseup = null;
    if (!document.dragTable) return;

    var tableInfo = document.dragTable;
    var dragCol = document.dragCol;
    var dragTargetCol = document.dragTargetCol;

    tableInfo.dragDiv.style.display = 'none';
    document.dragCol = -1;
    document.dragTargetCol = -1;
    document.dragTable = null;
    
    tableInfo.moveColumn(dragCol,dragTargetCol);
}

function handleMoveDrag(e) {
    if (!e) var e = window.event;
    var t;
    if (e.target)t = e.target; 
    else if (e.srcElement) t = e.srcElement; 
    else return;
    
    if (t.nodeType == 3) t = t.parentNode; 

    var tableInfo = document.dragTable;
    var dragCol = document.dragCol;

    // find which column we are in 
    var i = 0;
    var newCol = 0;
    var newColLeft = -1;
    var newColTop  = -1;
    var colLeft;
    for (i = tableInfo.leftCols; i < tableInfo.headerRow().cells.length; i++) {
	colLeft = findPosX(tableInfo.headerRow().cells[i]);	
	if (colLeft < e.clientX) {
	    newColLeft = colLeft;
	    newCol = i - tableInfo.leftCols;
	}
	if (newColLeft == -1)
	    newColLeft = colLeft;
	if (newColTop == -1)
	    newColTop = findPosY(tableInfo.headerRow().cells[i]);
    }

    colLeft = colLeft + tableInfo.headerRow().cells[i-1].offsetWidth;
    if (colLeft < e.clientX) {
	newColLeft = colLeft;
	newCol++;
    }

    if (dragCol < newCol)
	newCol--;

    tableInfo.dragDiv.style.left = newColLeft - tableInfo.borderWidth;
    tableInfo.dragDiv.style.top  = newColTop;
    tableInfo.dragDiv.style.height = tableInfo.tableElem.offsetHeight - (newColTop - findPosY(tableInfo.tableElem)) - tableInfo.borderWidth;
    if (tableInfo.dragDiv.style.display == 'none')
	tableInfo.dragDiv.style.display = '';

    document.dragTargetCol = newCol;
    return false;
}

function endMoveDrag(e) {
    document.onmousemove = null;
    document.onmouseup = null;
    if (!document.dragTable) return;

    var tableInfo = document.dragTable;
    var dragCol = document.dragCol;
    var dragTargetCol = document.dragTargetCol;

    tableInfo.dragDiv.style.display = 'none';
    document.dragCol = -1;
    document.dragTargetCol = -1;
    document.dragTable = null;
    
    tableInfo.moveColumn(dragCol,dragTargetCol);
}

// register the unload handler

if (window.addEventListener)
    window.addEventListener('unload', tablePageUnload, false);
else {
    window.detachEvent('onunload', tablePageUnload);
    window.attachEvent('onunload', tablePageUnload);
}

function tablePageUnload(e) {
    if (window.addEventListener)
	window.removeEventListener('unload', tablePageUnload, false);
    else {
	window.detachEvent('onunload', tablePageUnload);
    }
    
    if (typeof(skipjackTables) == "undefined") return;
    
    var id;
    for (id in skipjackTables) {	    
	skipjackTables[id].cancelGen();
	skipjackTables[id].clearIntervals();
    }
}

function doFilter(tableInfo, e, input) {
    if (!e) var e = window.event;

    if (e.keyCode == 13) {
	if (tableInfo.inProgress()) return false;	
	tableInfo.filterInput = input.id;
	tableInfo.filter();
	return false;
    }

    return true;
}

function getBrowserInfo() {
    info = new Object();
    
    info.DOM = (document.getElementById) ? true : false;
    info.NS4 = (document.layers) ? true : false;
    info.IE = navigator.userAgent.indexOf("MSIE") > -1;
    info.IE4 = info.IE && !info.DOM;
    info.Mac = (navigator.appVersion.indexOf("Mac") != -1);
    info.IE4M = info.IE4 && info.Mac;
    info.Opera = (navigator.userAgent.indexOf("Opera")!=-1);
    info.Konqueror = (navigator.userAgent.indexOf("Konqueror")!=-1);
    info.Gecko = navigator.product == ("Gecko");
    
    info.IEM = info.IE && info.Mac;
    info.IEW = info.IE && !info.Mac;
    info.NS6 = (navigator.vendor == ("Netscape6") || navigator.product == ("Gecko"));
    info.IEpos = info.IE || (info.NS6 && parseInt(navigator.productSub)>=20010710);
    info.IEDTD = (info.IE && document.doctype) ? document.doctype.name.indexOf(".dtd")!=-1 : false;
    info.IEnoDTD = info.IE && !info.IEDTD;

    return info;
}


function createViewRow (tableInfo, t, i, viewName) {
    var row, cell;

    row = t.insertRow(i);
    
    row.setAttribute("viewName", viewName);
    row.setAttribute("isViewRow", 1);

    cell = document.createElement("td");
    cell.className = tableInfo.viewMenuItemClassName;
    
    if (viewName == tableInfo.curViewName) {
	cell.innerHTML = tableInfo.itemSelectedGlyph;
    } else
	cell.innerHTML = "";
    
    row.appendChild(cell);
    
    cell = document.createElement("td");
    link = document.createElement("a");
    link.className = tableInfo.viewMenuItemClassName;
    link.href = 'javascript:skipjackTables["' + tableInfo.tableId + '"].changeView("' + viewName + '",true)';
    link.innerHTML = viewName;
    cell.appendChild(link);
    row.appendChild(cell);
}

function findPosX(obj)
{
	var curleft = 0;
	if (document.getElementById || document.all)
	{
		while (obj.offsetParent)
		{
			curleft += obj.offsetLeft
			obj = obj.offsetParent;
		}
	}
	else if (document.layers)
		curleft += obj.x;
	return curleft;
}

function findPosY(obj)
{
	var curtop = 0;
	if (document.getElementById || document.all)
	{
		while (obj.offsetParent)
		{
			curtop += obj.offsetTop
			obj = obj.offsetParent;
		}
	}
	else if (document.layers)
		curtop += obj.y;
	return curtop;
}


function handleMenuMouseOut (e, attr) {
    if (!e) var e = window.event;
    var t;
    if (e.target)t = e.target;
    else if (e.srcElement) t = e.srcElement;
    else return;
    
    if (t.nodeType == 3) t = t.parentNode;
    
    if (t.getAttribute(attr) == 1)
	t.style.display = 'none';
}

function arrayContains(arr, val) {
    return arrayIndexOf(arr,val) > -1;
}

function arrayIndexOf(arr, val) {
    var i;
    for (i = 0; i < arr.length; i++) if (arr[i] == val) return i;
    return -1;
}    

function sameLastToken(delim, str1, str2) {
    var s1 = str1.substr(str1.lastIndexOf(delim));
    var s2 = str2.substr(str2.lastIndexOf(delim));

    return s1 == s2;
}

function hoverMouseOver(elem, delay, x, y) {
    var id = elem.id;
    elem.doHover = true;
    window.setTimeout("hover(\"" + id + "\"," + x + "," + y + ");", delay );
}

function hoverMouseOut(elem) {
    elem.doHover = false;
    var w = document.getElementById(elem.id + "_div");
    if (w) w.style.display = 'none';   
}

function hoverDivMouseOver(w) {
    if (w) w.style.display = 'block';       
}

function hoverDivMouseOut(w) {
    if (w) w.style.display = 'none';       
}

function hover(id, x, y) {
    var elem = document.getElementById(id);
    if (elem && elem.doHover) {
	var w = document.getElementById(elem.id + "_div");	
	if (w) {
	    w.style.left    = findPosX(elem) + x;
	    w.style.top     = findPosY(elem) + elem.offsetHeight + y;
	    w.style.display = 'block';   
	}
    }	
}

function tableFind (tblName)
{
	if(typeof(skipjackTables) == "undefined") {
		return 0;
	}

	for (tblID in skipjackTables) {
		var tbl = skipjackTables[tblID];
		if (tbl.tableName == tblName) {
			return tbl;
		}
	}

	return 0;
}

function tableFilter (tblName, colName, filterVal)
{
	var tbl = tableFind (tblName);
	if (!tbl) {
		alert("No data available");
		return;
	}
	tbl.setFilter (colName, filterVal);
	tbl.filter();
}

function tableView (tblName, viewName)
{
	var tbl = tableFind (tblName);
	if (!tbl) {
		alert("No data available");
		return;
	}
	tbl.changeView (viewName);
}
