function ckCommonEditObj() {
	this.varName=(arguments.length==1 ? arguments[0] : "commonEdit");
	this.fwDefaultWidth = 500;
	this.fieldPrefix = this.varName +".";
	
	//these can be forced to non-default values by setting in individual object inits
	this.listContainerID = this.varName + ".tab.content"; //default to view on own tab.
	this.viewContainerID = this.varName + ".tab.content"; //default to view on own tab.
	this.editContainerID = "floatingWindow." + this.varName; //default to edit in floating window
	
	this.fnCustomReturnHandler_list = null;
	this.aParams = Array(); //Should be used to set data that always gets sent...except if saving FORM object
	
	this.getURL = "";
	this.saveURL = "";
	this.editURL = "";
	this.listURL = "";
	this.deleteURL = "";
	this.saveSortOrderURL = "";
	
	return this;
}

/*----- Save --------------------------------------------------------------------------------------------*/

ckCommonEditObj.prototype.save=function() {
	var bAutoValidate = (arguments.length >= 1 ? arguments[0] : true);
	var variant = (arguments.length >= 2 ? arguments[1] : this.varName + ".field"); //some edit objects like galleryEditObj have multiple save types (image,group,gallery). This could be the name attribute or a FORM object
	var bShowWait = (arguments.length == 3 ? arguments[2] : true);
	if (bAutoValidate) oError.autoValidate(variant); //param allows custom handling and just use superClass for submission
	if (!oError.anyErrors()) {
		oFloatingWindow.hideErrWarnSuccess();
		
		if (typeof(variant)=="object") (new ckAjaxObj()).postForm(variant,this.ajaxReturnHandler_save,this);
		else {	
			var sURL = this.saveURL; //so we're not modifying the global URL and constantly appending
			var sParams = this.getParams();
			if (sParams != "") sURL += "?" + sParams;
			(new ckAjaxObj()).postFormDataByName(sURL,variant,this.ajaxReturnHandler_save,this);
		}
		
		if (bShowWait) oFloatingWindow.showWait();
	}
}
ckCommonEditObj.prototype.ajaxReturnHandler_save = function(oAjax) {
	if (!oAjax.responseObj) oFloatingWindow.showError(oAjax.responseText);
	else {
		oFloatingWindow.hide();
		this.list();
	}
}

/*----- List --------------------------------------------------------------------------------------------*/

ckCommonEditObj.prototype.list = function() {
	var sData = (arguments.length==1 ? arguments[0] : "");
	
	var oAjax = new ckAjaxObj();
	//oAjax.setErrorDisplayID(this.listContainerID + ".status"); //dont think I need this since oError detects if floatingWindow is open
	oAjax.postFormData(this.listURL,this.getParams(sData),this.ajaxReturnHandler_list,this);
	

}
ckCommonEditObj.prototype.ajaxReturnHandler_list = function(oAjax) {
	//this handler is never overwritten so we can always revert to default handler by passing in null value for the custom return handler. 
	if (this.fnCustomReturnHandler_list) this.fnCustomReturnHandler_list.call(this,oAjax);
	else {
		this.fillContainer(document.getElementById(this.listContainerID),oAjax.responseText);
		oAjax.executeScripts();
	}
}
ckCommonEditObj.prototype.showListContainerWait = function() {
	this.showContainerWait(this.listContainerID,(arguments.length==1 ? arguments[0] : "Retrieving list..."));
}
/*----- Sort Order --------------------------------------------------------------------------------------*/

ckCommonEditObj.prototype.saveSortOrder= function() {
	oFloatingWindow.showWait();
	oStdContainer.clearAll();
	var sData = (arguments.length >= 1 ? arguments[0] : "");
	var sActionCode = (arguments.length >= 2 ? arguments[1] : "saveOrder"); //in case multiple orders in single action page
	var sOrderedIDs = (arguments.length == 3 ? arguments[2] : oTableRowSort.getOrderedIDs());
	sData += (sData != "" ? "&" : "") + "actionCode=" + sActionCode + "&orderedIDs=" + sOrderedIDs;
	(new ckAjaxObj()).postFormData(this.saveSortOrderURL,this.getParams(sData),this.ajaxReturnHandler_saveSortOrder,this);
}
ckCommonEditObj.prototype.ajaxReturnHandler_saveSortOrder= function(oAjax) {
	if (!oAjax.responseObj) oFloatingWindow.showError(oAjax.responseText);
	else {
		this.setSortOrderMessage("The sort order has been saved")
		oFloatingWindow.hideWait();
	}
}
ckCommonEditObj.prototype.clearSortOrderMessage = function() { this.setSortOrderMessage(''); }
ckCommonEditObj.prototype.setSortOrderMessage = function(sMsg) { this.fillContainer(document.getElementById(this.varName + ".sortOrder.message"),sMsg); }

/*----- Edit ---------------------------------------------------------------------------*/

ckCommonEditObj.prototype.create=function() { this.edit(''); }
ckCommonEditObj.prototype.edit = function(sData) {
	var sTitle = (arguments.length==2 ? arguments[1] : "");
	var oEl;
	if (oEl = oFloatingWindow.getOrCreate(this.editContainerID,this.fwDefaultWidth,sTitle)) {
		oFloatingWindow.showAndWait(this.editContainerID);
		(new ckAjaxObj()).postFormData(this.editURL,this.getParams(sData),this.ajaxReturnHandler_edit,this);
	}
}
ckCommonEditObj.prototype.ajaxReturnHandler_edit = function(oAjax) {
	if (oFloatingWindow.fillAndShow(this.editContainerID,oAjax.responseText)) {
		oAjax.executeScripts();
		
		oFloatingWindow.refreshDisplay();//scripts could show/hide elements that require resizing window
		oValidation.markRequiredFields();
		this.onEditActions(); //allow object that inherit ckCommonEdit to implement so they can still always use this as the default return handler call.
	}
}

ckCommonEditObj.prototype.onEditActions = function() { }


/*--------------------------------------------------------------------------------
Delete
--------------------------------------------------------------------------------*/
ckCommonEditObj.prototype.deleteData = function(sData) {
	var sDeleteText = (arguments.length>=2 ? arguments[1] : "");
	var bCustomPhrase = (arguments.length >=3 ? arguments[2] : false);
	if (sDeleteText !="") {
		var sDeletePhrase = (bCustomPhrase ? sDeleteText : "Are you sure you want to delete this " + sDeleteText + "?");

		if (oFloatingWindow.confirm(sDeletePhrase,this)) {
			(new ckAjaxObj()).postFormData(this.deleteURL,this.getParams(sData),this.ajaxReturnHandler_delete,this);
		}
	} else {
		(new ckAjaxObj()).postFormData(this.deleteURL,this.getParams(sData),this.ajaxReturnHandler_delete,this);
	}
}
ckCommonEditObj.prototype.ajaxReturnHandler_delete = function(oAjax) {
	if (!oAjax.responseObj) oFloatingWindow.showError(oAjax.responseText);
	else {
		oFloatingWindow.hide();
		var oEl, oResponse;
		if ((oResponse = oAjax.responseObj) && (oResponse.payload.deletedID != null)) { 
			if (oEl = document.getElementById(this.varName + "." + oResponse.payload.deletedID)) {
				oEl.style.display="none"; 
				if ((oEl.tagName=="TR") && (oEl.className.toLowerCase()=="tablerow1" || oEl.className.toLowerCase()=="tablerow2")) {
					var oTable, oRow
					if (oTable = oDHTML.seekParentTag(oEl,"TABLE")) {
						var rowIndex = 0;
						var rowCount = oTable.rows.length;
						for (var index=0; index < rowCount; index++) {
							if ((oRow = oTable.rows.item(index)) && (oRow.style.display != "none")) oRow.className=(++rowIndex % 2==0 ? "tablerow1" : "tableRow2");
						}
					}
				}
				oEl.parentNode.removeChild(oEl); //hide, reorder(need oEl reference still), then delete. Actual node delete required so ckTableRowSort works properly. It doesn't like hidden rows
				return;
			}
		}
		this.list();
	}
}
/*--------------------------------------------------------------------------------
Get
--------------------------------------------------------------------------------*/
ckCommonEditObj.prototype.get = function() {
	var sData = (arguments.length==1 ? arguments[0] : "");
	(new ckAjaxObj()).postFormData(this.getURL,this.getParams(sData),this.ajaxReturnHandler_get,this);
}
ckCommonEditObj.prototype.ajaxReturnHandler_get = function(oAjax) {
	this.fillContainer(document.getElementById(this.viewContainerID),oAjax.responseText);
	oAjax.executeScripts();
	try {
		if (oFloatingWindow.isShowing()) oFloatingWindow.refreshDisplay();//scripts could show/hide elements that require resizing window
	} catch (err) {}
}
ckCommonEditObj.prototype.showViewContainerWait = function() {
	this.showContainerWait(this.viewContainerID,(arguments.length==1 ? arguments[0] : "Retrieving..."));
}

/*--------------------------------------------------------------------------------
Utilities
--------------------------------------------------------------------------------*/
ckCommonEditObj.prototype.showContainerWait = function(containerID) {
	var sMsg = (arguments.length >= 2 ? arguments[1] : "Retrieving...");
	var bReplaceContent = (arguments.length >= 3 ? arguments[2] : true); //by default, wait content replaces all other content in container.

	var oEl = document.getElementById(containerID);
	if (oEl) {
		if (bReplaceContent) oEl.innerHTML = "";
	
		if (!document.getElementById(containerID + ".status")) { 
			//to avoid messing up any classes placed on outer container, a separate div is created within with the ".status" extension
			//	since that is the default displayID for certain ajax call errors.
			var oDiv = document.createElement("DIV");
			oDiv.id = containerID + ".status";
			
			oEl.insertAdjacentElement("afterBegin",oDiv);
		}
		if (oEl = document.getElementById(containerID + ".status")) {
			this.fillContainer(oEl,'<div class="waitingDisplay">' + sMsg + '</div>');
			oEl.style.display="block";
		}
	}
}

ckCommonEditObj.prototype.setReturnHandler_save=function(fnPtr) {
	if (!fnPtr) this.ajaxReturnHandler_save=null; //no return desired
	else this.ajaxReturnHandler_save = fnPtr; 
}
ckCommonEditObj.prototype.setReturnHandler_delete=function(fnPtr) {
	if (!fnPtr) this.ajaxReturnHandler_delete=null; //no return desired
	else this.ajaxReturnHandler_delete = fnPtr;
}
ckCommonEditObj.prototype.setReturnHandler_list=function(fnPtr) {
	if (!fnPtr) this.fnCustomReturnHandler_list=null; //revert to default
	else this.fnCustomReturnHandler_list = fnPtr;
}

ckCommonEditObj.prototype.getElement=function(sName) {
	return(document.getElementById(this.fieldPrefix + sName));
}
ckCommonEditObj.prototype.getContainer=function(sID) {
	//floating window is assumed, so automatically create container if not found
	var oDiv = document.getElementById(sID);
	if (!oDiv) {
		var width = (arguments.length==2 ? arguments[1] : this.fwDefaultWidth);
		
		oDiv = document.createElement("DIV");
		oDiv.id = sID
		oDiv.style.width = width + "px";
		oDiv.style.display = "none";
		oDiv = document.body.appendChild(oDiv);
	}
	return oDiv;
}
ckCommonEditObj.prototype.showAndWait=function(containerID,sTitle) {
	//floatingWindow assumed for this call
	oFloatingWindow.addContentType(containerID,sTitle,this.getContainer(containerID)); 
	oFloatingWindow.showAndWait(containerID);
}
ckCommonEditObj.prototype.fillContainer=function(oEl,sHTML) {
	if (oEl) {
		oEl.innerHTML = sHTML;
		return true;
	} else {
		throwConsoleError("ckCommonEditObj.fillContainer()","Container is null");
		return false;
	}
}
ckCommonEditObj.prototype.setParam= function(sName,sValue) {
	this.aParams[sName] = sValue;
}
ckCommonEditObj.prototype.getParams = function() { 
	//should always be called when sending data since it takes aParams into consideration
	var sParams = (arguments.length==1 ? arguments[0] : "");
	for (var key in this.aParams) sParams += (sParams != "" ? "&" : "") + key + "=" + this.aParams[key]
	return sParams;
}

/*--------------------------------------------------------------------------------

UNCOFIRMED BELOW HERE

--------------------------------------------------------------------------------*/


ckCommonEditObj.prototype.getFormValue=function(sName) {
	var oEl;
	var sValue = "";
	
	if (oEl = this.getElement(sName)) {
		switch (oEl.type) {
			case "checkbox":
				sValue = (oEl.checked ? oEl.value : "");
				break;
			case "radio" :
				//if "radioDisplay" is used, all radios for a field are going to have the same name and id attributes
				var aFields = document.getElementsByName(this.fieldPrefix + sName);
				for (var index=0; index < aFields.length; index++) {
					if (aFields[index].checked) sValue=aFields[index].value;
				}
				break;
			default :
				sValue = oEl.value;
		}
	}
		
	return sValue;
}

