Location: PHPKode > scripts > phpMyAccess > phpmyaccess-1.5.3/phpmyaccess/pma-editinline.php
<?
/*
  Edit Inline
  version 1		29 July 2009(.js)
  version 2		17 Dec 2009(.js)
  version 3		01 Nov 2010(.php)
  version 3.1	11 Jan 2011(.php)
  version 4		13 Jan 2011(.php)
  version 4.1	18 Mar 2011(.php): fix alert on line 111 
  version 4.5	01 Jun 2011(.php)
  version 4.5.1 06 Jul 2011(.php)
  version 5.0a	20 Feb 2011 : alpha including epulldowninline WIP (not finished)
  version 5.0a108	08 Oct 2012 - 16 Oct 2012 (.php): trying to deal with post after refresh -- need Syncronous
  gfdos
  
  Instructions:
  1. Add 
	$editinlinelocal = "//Desired js subfunction before text reloaded into cell here\n";
	include("pma-editinline.php");
  to your php source
  2. Add onclick="editinline(authlvl,db-name_table-name.field-name_1,this);" to any table cell you'd like to make it editable
  NOTE: An additional operand added to the call: editinline(999,id_table-name.field-name_1,this,'yes');
  		will tell editinline to run the javascript stored in php variable $editinline local. 
		This variable only needs to be non-null to cause the run, but can also be used to pass a variable into that code without using a global. 
 
  Change Log:
  NOTE: Some of the functions added are not used anywhere in phpMyAccess -- I use them in other projects
        They are added here incase you want to or need to use them in any derivative work.
  Version 5.0a108 Add bananafresh fuction, and change internal opperands in calls between banana functions to pass references through.
  				All changes made so that actual SQL call to pull info to refresh cell happens 
				AFTER(not Asyncronus) the post of replacement data. In the interim "Posting..." is displayed.
				
				If the data being changed was long this started to be come more likely in earlier code but was intermitant.
				Further if the connection had very low latency (local network rather than internet) this was even more aparent --> call to refresh would finish first pulling old data before the post of new data had completed, making it appear as though the change hadn't been commited -- even though it really had.
				
  Version 4.5.1 Add "12to24" functions to allow input of 12 hour with am/pm, store 24 hour value, reload 12 hour with am/pm
  Version 4.5 Integrate innovations from all branches of 3.x used in other projects and 4.x used in phpMyAccess and phpMyAccess Alpha:
  				"EC" versions of functions to check for valid names for MS ACCESS/SQL names before allowing posting
				"form" (nodb) versions of functions to allow use of edit inline with ajax form with no backend db
  Version 4/4.1 added authlvl variable to call, added requirement of prikeyname to call
  Version 3.1 code sanitized for inclusion in phpMyAccess
  Version 3 has you put the js code into var $editinlinelocal -- then calls it only if 3rd opperand was specified in the initial call
  Version 2 calls a function editinlinelocal(x,x,x) -- only if the 3rd operand was specified in the inital call.
  This can be used to do any after changes that are affected by the cell change: IE recalculating formulas, etc.
*/
?>
<script language="Javascript" type="text/javascript">
function getXMLHTTP() { //fuction to return the xml http object
	var xmlhttp=false;
	//For Safari, Firefox, and other non-MS Browsers	
	try{
		xmlhttp=new XMLHttpRequest();
	}
	//for IE
	catch(e)	{		
		try{			
			xmlhttp= new ActiveXObject("Microsoft.XMLHTTP");
		}
		catch(e){
			try{
			req = new ActiveXObject("Msxml2.XMLHTTP");
			}
			catch(e1){
				xmlhttp=false;
			}
		}
	}	 	
	return xmlhttp;
}
function parentByTag( node, tag )//do not assume what DOM structure a browser uses -- go up by KNOWN parent tags: tr, table...
{
    while ( node != null )
    {
        if (node.tagName == tag ) return node;
        node = node.parentNode;
    }
    return null; // or -1 or ???
}
function childByTag( node, tag )//do not assume what DOM structure a browser uses -- go up by KNOWN parent tags: tr, table...
{
    while ( node != null )
    {
        if (node.tagName == tag ) return node;
        node = node.parentNode;
    }
    return null; // or -1 or ???
}

function editinline(auth,id,cell,inout) {		
		var cellidx = cell.cellIndex;
		var row = parentByTag(cell,'TR');
		var tbl = parentByTag(row,'TABLE');
		var editrow = row.cells;

		for(eachcell=0; eachcell < editrow.length; eachcell++) {
			if(eachcell==cellidx){
				//editrow[eachcell].innerHTML="banana cell";
				editrow[eachcell].onclick='';
				editrow[eachcell].style.display='none';
				var newbanana=row.insertCell(eachcell);
				if (editrow[eachcell+1].rowSpan == 2){
				newbanana.rowSpan=editrow[eachcell+1].rowSpan;
				}
				//NOTE: newbanana now = editrow[eachcell], the old cell content is now in editrow[eachcell+1]
				//newbanana.bgColor=editrow[eachcell+1].bgColor;
				editrow[eachcell].bgColor=editrow[eachcell+1].bgColor;
				if(inout){
					editrow[eachcell].innerHTML='<textarea name="'+id+'" onblur="unbanana('+"'"+auth+"','"+id+"'"+',this.parentNode,'+"'"+inout+"'"+');">'+editrow[eachcell+1].innerHTML+"</textarea>";
				} else {
					editrow[eachcell].innerHTML='<textarea name="'+id+'" onblur="unbanana('+"'"+auth+"','"+id+"'"+',this.parentNode);">'+editrow[eachcell+1].innerHTML+"</textarea>";
				}
				editrow[eachcell].firstChild.focus();
			}
		}
}
function editinline12to24(auth,id,cell,inout) {	
		//This is for time conversion 12to24. This expects 12 hour with am/pm entry, does conversion to 24 hour time for storage, converts that back to 12 hour am/pm for display.
		//Will also do some error checking -- if 12 hour format is not recognized, it will attempt conversion anyway -- if it fails, return conversion will have to display "error" some how.
		var cellidx = cell.cellIndex;
		var row = parentByTag(cell,'TR');
		var tbl = parentByTag(row,'TABLE');
		var editrow = row.cells;

		for(eachcell=0; eachcell < editrow.length; eachcell++) {
			if(eachcell==cellidx){
				//editrow[eachcell].innerHTML="banana cell";
				editrow[eachcell].onclick='';
				editrow[eachcell].style.display='none';
				var newbanana=row.insertCell(eachcell);
				if (editrow[eachcell+1].rowSpan == 2){
				newbanana.rowSpan=editrow[eachcell+1].rowSpan;
				}
				//NOTE: newbanana now = editrow[eachcell], the old cell content is now in editrow[eachcell+1]
				//newbanana.bgColor=editrow[eachcell+1].bgColor;
				editrow[eachcell].bgColor=editrow[eachcell+1].bgColor;
				if(inout){
					editrow[eachcell].innerHTML='<textarea name="'+id+'" onblur="unbanana12to24('+"'"+auth+"','"+id+"'"+',this.parentNode,'+"'"+inout+"'"+');">'+editrow[eachcell+1].innerHTML+"</textarea>";
				} else {
					editrow[eachcell].innerHTML='<textarea name="'+id+'" onblur="unbanana12to24('+"'"+auth+"','"+id+"'"+',this.parentNode);">'+editrow[eachcell+1].innerHTML+"</textarea>";
				}
				editrow[eachcell].firstChild.focus();
			}
		}
}
function editinlineEC(auth,id,cell,inout) {		
		//This is for EC -- error checking. At this stage this checks only for restricted characters in file names.
		//It should reject the "unblur" (unbanana) and confirm  -- user wants to keep editing name or cancel (which should restore previous value)
		var cellidx = cell.cellIndex;
		var row = parentByTag(cell,'TR');
		var tbl = parentByTag(row,'TABLE');
		var editrow = row.cells;

		for(eachcell=0; eachcell < editrow.length; eachcell++) {
			if(eachcell==cellidx){
				//editrow[eachcell].innerHTML="banana cell";
				editrow[eachcell].onclick='';
				editrow[eachcell].style.display='none';
				var newbanana=row.insertCell(eachcell);
				if (editrow[eachcell+1].rowSpan == 2){
				newbanana.rowSpan=editrow[eachcell+1].rowSpan;
				}
				//NOTE: newbanana now = editrow[eachcell], the old cell content is now in editrow[eachcell+1]
				//newbanana.bgColor=editrow[eachcell+1].bgColor;
				editrow[eachcell].bgColor=editrow[eachcell+1].bgColor;
				if(inout){
					editrow[eachcell].innerHTML='<textarea name="'+id+'" onblur="unbananaEC('+"'"+auth+"','"+id+"'"+',this.parentNode,'+"'"+inout+"'"+');">'+editrow[eachcell+1].innerHTML+"</textarea>";
				} else {
					editrow[eachcell].innerHTML='<textarea name="'+id+'" onblur="unbananaEC('+"'"+auth+"','"+id+"'"+',this.parentNode);">'+editrow[eachcell+1].innerHTML+"</textarea>";
				}
				editrow[eachcell].firstChild.focus();
			}
		}
}
function editinlineform(auth,id,cell,inout) {		
		//This is for "form" -- it will not make AJAX calls for post. 
		//It is ment to give the same feel as the AJAX version, but then require a "submit" to post the change.
		//The "Danger" is that people using the system get used to the fact that the interface is posting directly to a db,
		//so use sparingly and/or with a alert that watches for leaving the page to remind user to submit or changes will be lost.
		var cellidx = cell.cellIndex;
		var row = parentByTag(cell,'TR');
		var tbl = parentByTag(row,'TABLE');
		var editrow = row.cells;

		for(eachcell=0; eachcell < editrow.length; eachcell++) {
			if(eachcell==cellidx){
				//editrow[eachcell].innerHTML="banana cell";
				//editrow[eachcell].onclick='';
				editrow[eachcell].style.display='none';
				var newbanana=row.insertCell(eachcell);
				if (editrow[eachcell+1].rowSpan == 2){
				newbanana.rowSpan=editrow[eachcell+1].rowSpan;
				}
				//NOTE: newbanana now = editrow[eachcell], the old cell content is now in editrow[eachcell+1]
				//newbanana.bgColor=editrow[eachcell+1].bgColor;
				editrow[eachcell].bgColor=editrow[eachcell+1].bgColor;
				if(inout){
					editrow[eachcell].innerHTML='<textarea name="'+id+'" onblur="unbananaform('+"'"+auth+"','"+id+"'"+',this.parentNode,'+"'"+inout+"'"+');">'+editrow[eachcell+1].innerHTML+"</textarea>";
				} else {
					editrow[eachcell].innerHTML='<textarea name="'+id+'" onblur="unbananaform('+"'"+auth+"','"+id+"'"+',this.parentNode);">'+editrow[eachcell+1].innerHTML+"</textarea>";
				}
				editrow[eachcell].firstChild.focus();
			}
		}
}
<? /*
function epulldowninline(auth,id,cell,src,inout) {		
//epulldowninline       ('0', 'id.hrscheds.name.NULL.121','Contact_Info.Full_Name.50.Status=\"C\"' this)
		var cellidx = cell.cellIndex;
		var row = parentByTag(cell,'TR');
		var tbl = parentByTag(row,'TABLE');
		var editrow = row.cells;

		for(eachcell=0; eachcell < editrow.length; eachcell++) {
			if(eachcell==cellidx){
				//editrow[eachcell].innerHTML="banana cell";
				editrow[eachcell].onclick='';
				editrow[eachcell].style.display='none';
				var newbanana=row.insertCell(eachcell);
				if (editrow[eachcell+1].rowSpan == 2){
				newbanana.rowSpan=editrow[eachcell+1].rowSpan;
				}
				//NOTE: newbanana now = editrow[eachcell], the old cell content is now in editrow[eachcell+1]
				//newbanana.bgColor=editrow[eachcell+1].bgColor;
				editrow[eachcell].bgColor=editrow[eachcell+1].bgColor;
				if(inout){
					//#editrow[eachcell].innerHTML='<textarea name="'+id+'" onblur="unbanana('+"'"+auth+"','"+id+"'"+',this.parentNode,'+"'"+inout+"'"+');">'+editrow[eachcell+1].innerHTML+"</textarea>";
				} else {
					//#editrow[eachcell].innerHTML='<textarea name="'+id+'" onblur="unbanana('+"'"+auth+"','"+id+"'"+',this.parentNode);">'+editrow[eachcell+1].innerHTML+"</textarea>";
//#					
				var strURL="pma-ajaxpulldown.php";
				//replace & or " so it doesn't break URL call
				var strCell = cell.firstChild.value;
				strCell = strCell.replace(/&/g,"%26");
				strCell = strCell.replace(/"/g,'\\"');
				//strCell = strCell.replace(/'/g,"\\'");
				var strParams="auth="+auth+"&bmethod=put&rowid="+id+"&pullsrc="+src+"&putdata="+strCell;
				var req = getXMLHTTP();

				if (req) {
					req.open("POST", strURL, true);
					//Send the proper header information along with the request
					req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		
					req.onreadystatechange = function() {
						if (req.readyState == 4) {
							// only if "OK"
							if (req.status == 200) {
								//NOTE:req.responseText for get,req.statusText for post
								var celdata = eval('(' + req.responseText + ')');
								//#var oldceldata = cell.innerHTML;					
								//cell.innerHTML=celdata[0];
								//CODE HERE TO CREATE PULL DOWN AND INSERT EACH item in req.responseText as an<option>
								alert "celdata: "+celdata[0];
								alert "celdata.length?: "+celdata.length;
								alert "celdata[1]: "+celdata[1]
								cell.innerHTML=celdata[0];
							} else {
								alert("There was a problem while using XMLHTTP:\n" + req.statusText);
							}
						}				
					}			
					req.send(strParams);
				}
//#					
				}
				editrow[eachcell].firstChild.focus();
			}
		}
}
*/
?>
function unbanana(auth,id,cell,inout) {		
		var cellidx = cell.cellIndex;
		var row = parentByTag(cell,'TR');
		var tbl = parentByTag(row,'TABLE');
		var editrow = row.cells;
		
		for(eachcell=0; eachcell < editrow.length; eachcell++) {
			if(eachcell==cellidx){	
				//compare new data to original data and determine if sql post call is needed
				if(editrow[eachcell].firstChild.value!=editrow[eachcell+1].innerHTML){//NOTE editrow[eachcell+1] is hidden cell with orginal value
				//if data has changed
					bananapost(auth,id,editrow[eachcell],editrow,eachcell,row,inout);
					editrow[eachcell].innerHTML = "Posting...";
					editrow[eachcell+1].innerHTML = "Posting...";
					//alert('id: '+id);
				} else {
				//else put original cell innerHTML back
					editrow[eachcell+1].innerHTML=editrow[eachcell].firstChild.value;
					row.deleteCell(eachcell);
					editrow[eachcell].style.display='';
					//REARM onclick handler event trap
					if (inout) {
						editrow[eachcell].onclick=function(){ editinline(auth,id,this,inout);};
					} else {
						editrow[eachcell].onclick=function(){ editinline(auth,id,this);};
					}
				}
			}
		}	
}
function unbanana12to24(auth,id,cell,inout) {		
		var cellidx = cell.cellIndex;
		var row = parentByTag(cell,'TR');
		var tbl = parentByTag(row,'TABLE');
		var editrow = row.cells;
		
		for(eachcell=0; eachcell < editrow.length; eachcell++) {
			if(eachcell==cellidx){	
				//compare new data to original data and determine if sql post call is needed
				if(editrow[eachcell].firstChild.value!=editrow[eachcell+1].innerHTML){//NOTE editrow[eachcell+1] is hidden cell with orginal value
				//if data has changed
					bananapost12to24(auth,id,editrow[eachcell]);
					editrow[eachcell].innerHTML = "Posting...";
					//alert('id: '+id);
					bananarefresh12to24(auth,id,editrow[eachcell+1],inout);
					row.deleteCell(eachcell);
					editrow[eachcell].style.display='';
				} else {
				//else put original cell innerHTML back
					editrow[eachcell+1].innerHTML=editrow[eachcell].firstChild.value;
					row.deleteCell(eachcell);
					editrow[eachcell].style.display='';
				}
				//REARM onclick handler event trap
				if (inout) {
					editrow[eachcell].onclick=function(){ editinline12to24(auth,id,this,inout);};
				} else {
					editrow[eachcell].onclick=function(){ editinline12to24(auth,id,this);};
				}
			}
		}	
}
function unbananaEC(auth,id,cell,inout) {		
		var cellidx = cell.cellIndex;
		var row = parentByTag(cell,'TR');
		var tbl = parentByTag(row,'TABLE');
		var editrow = row.cells;
		
		for(eachcell=0; eachcell < editrow.length; eachcell++) {
			if(eachcell==cellidx){	
				//compare new data to original data and determine if sql post call is needed
				if(editrow[eachcell].firstChild.value!=editrow[eachcell+1].innerHTML){//NOTE editrow[eachcell+1] is hidden cell with orginal value
				//if data has changed
				var str = editrow[eachcell].firstChild.value;
					// MSaccess specific error checking -- fieldnames cannot contain:
					// ./*;:!#&-?"'$%
					// MySQL Database and table names cannot contain 
					// /\.  (characters that are not permitted in file names) --linux NUL and /, -- windows " * / : < > ? \ |
					//so should avoid: ./\*;:!#&-?"'$% <>| null
					if((str.search("[./\*;:!#&?$%<>|-]") != -1) || (str.search(null) != -1) || (str == '') || (str ==' ')){
						alert("Field names cannot contain ./\*;:!#&-?"+'"'+"'$% <>| or nul");
						editrow[eachcell].firstChild.focus();
						//confirm() //use confirm instead? to allow for fixing change without putting back original or cancel to put back original.
						
						//REARM onblur handler event trap
						if (inout) {
							editrow[eachcell].onblur=function(){ unbananaEC(auth,id,this.parentNode,inout); };
						} else {
							editrow[eachcell].onblur=function(){ unbananaEC(auth,id,this.parentNode); };
						}
						return;//return here to prevent rest of code from executing.
					}
					bananapost(auth,id,editrow[eachcell]);
					editrow[eachcell].innerHTML = "Posting...";
					bananarefresh(auth,id,editrow[eachcell+1],inout);
					row.deleteCell(eachcell);
					editrow[eachcell].style.display='';
				} else {
				//else put original cell innerHTML back
					editrow[eachcell+1].innerHTML=editrow[eachcell].firstChild.value;
					row.deleteCell(eachcell);
					editrow[eachcell].style.display='';
				}
				//REARM onclick handler event trap
				if (inout) {
					editrow[eachcell].onclick=function(){ editinlineEC(auth,id,this,inout);};
				} else {
					editrow[eachcell].onclick=function(){ editinlineEC(auth,id,this);};
				}
			}
		}	
}
function unbananaform(auth,id,cell,inout) {		
		var cellidx = cell.cellIndex;
		var row = parentByTag(cell,'TR');
		var tbl = parentByTag(row,'TABLE');
		var editrow = row.cells;
		
		for(eachcell=0; eachcell < editrow.length; eachcell++) {
			if(eachcell==cellidx){	
				//compare new data to original data and determine if sql post call is needed
				if(editrow[eachcell].firstChild.value!=editrow[eachcell+1].innerHTML){//NOTE editrow[eachcell+1] is hidden cell with orginal value
				//if data has changed
					//bananapost(id,editrow[eachcell]);					
					editrow[eachcell+1].innerHTML = editrow[eachcell].firstChild.value;
					
					editrow[eachcell].innerHTML = "Updating...";
					editrow[eachcell+1].style.visibility='hidden';
					editrow[eachcell+1].style.display='';
					row.deleteCell(eachcell);					
					
					//bananarefresh(auth,id,editrow[eachcell+1],inout);
					if (inout) { //if inout is specified (not undefined) call a local function to do whatever follow up is needed --used to change other cells based on the change done here.														
						<?
						echo $editinlinelocal;
						?>
					}
					
					//row.deleteCell(eachcell);
					editrow[eachcell].style.visibility='visible';
				} else {
				//else put original cell innerHTML back
					//editrow[eachcell+1].innerHTML=editrow[eachcell].firstChild.value;
					row.deleteCell(eachcell);
					editrow[eachcell].style.display='';
				}
				//REARM onclick handler event trap
				if (inout) {
					editrow[eachcell].onclick=function(){ editinlineform(auth,id,this,inout);};
				} else {
					editrow[eachcell].onclick=function(){ editinlineform(auth,id,this);};
				}
			}
		}	
}
function bananapost(auth,id,cell,editrow,eachcell,row,inout) {		
	var strURL="pma-ajaxcell.php";
	//replace & or " so it doesn't break URL call
	var strCell = cell.firstChild.value;
	strCell = strCell.replace(/&/g,"%26");
	strCell = strCell.replace(/"/g,'\\"');
	//strCell = strCell.replace(/'/g,"\\'");
	var strParams="auth="+auth+"&bmethod=put&rowid="+id+"&putdata="+strCell;
	var req = getXMLHTTP();

	if (req) {
		req.open("POST", strURL, true);
		//Send the proper header information along with the request
		req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		
		req.onreadystatechange = function() {
			if (req.readyState == 4) {
				// only if "OK"
				if (req.status == 200) {
					//NOTE:req.responseText for get,req.statusText for post
					var returndata = eval('(' + req.responseText + ')');
					bananafresh(auth,id,editrow,inout,eachcell,row,returndata);					
				} else {
					alert("There was a problem while using XMLHTTP:\n" + req.statusText);
				}
			}				
		}			
		req.send(strParams);
	}			
}
function bananapost12to24(auth,id,cell) {		
	var strURL="pma-ajaxcell.php";
	//replace & or " so it doesn't break URL call
	var strCell = cell.firstChild.value;
	//CODE TO DO 12 to 24 Conversion will go here
	//What to do if it isn't stored correctly? just dump stored data? -- Note that calculation will not work properly -- may need to add error checking to that code
	//If data is not formatted correctly and this is a "date" field in the database, it will store "0" and that will show as 0 = midnight. This is a known issue.
	//additional checking code below trys to be as helpful as possible to avoid invalid data by looking for inputs that don't match the correct standard "hh:mm XM"
//alert ("timecell: "+strCell);
	var timecell = strCell.toUpperCase();
	var timecelllen =timecell.length;
	if (timecell.search(":") != -1) {//if there is a : in the string
		var timecellarr = timecell.split(":");
		var hr = timecellarr[0];
//alert ("there is a : in the string, hr:"+hr);
		//below works for correctly formated "hh:mm X(M)", "hh:mmX(M)", "hh:" //"hh: mmX(M)", "hh: mm X(M)" both currently Record "hh:00 XM" 
		if (timecellarr[1].length == 0){//minute and a/pm omitted, treated as 24 hour time
			var mn = "00";
			var xm = ""; 
		} else if (timecellarr[1].search(" ") != -1) {//if there is a " " in the string
			if(timecellarr[1].indexOf(" ") == 0){//the first char after the : is a space
				if (timecellarr[1].search("A") != -1) {//if there is an A in the string
					if(timecellarr[1].indexOf("A") == 1){//example 8: Ax
						var mn = "00";
						var xm = "AM";
					} else {//example "8: 30 Ax" or "8: 30Ax"
						var mn = timecellarr[1].substr(0,timecellarr[1].indexOf("A"));
						//var xm = timecellarr[1].substr(timecellarr[1].indexOf("A"));
						var xm = "AM";
					
						//check to see if mn is a number
						var ValidChars = "0123456789.";
						var IsNumber=true;
						var Char;
						for (i = 0; i < mn.length && IsNumber == true; i++) { 
							Char = mn.charAt(i); 
							if (ValidChars.indexOf(Char) == -1) {
								IsNumber = false;
							}
						}
					
						if(IsNumber == false){
							mn = 00;
						}
					}
				} else if (timecellarr[1].search("P") != -1) {//if there is a P in the string			
					if(timecellarr[1].indexOf("P") == 1){
						var mn = "00";
						var xm = "PM";
					} else {
						var mn = timecellarr[1].substr(0,timecellarr[1].indexOf("P"));
						//var xm = timecellarr[1].substr(timecellarr[1].indexOf("P"));
						var xm = "PM";
					
						//check to see if mn is a number
						var ValidChars = "0123456789.";
						var IsNumber=true;
						var Char;
						for (i = 0; i < mn.length && IsNumber == true; i++) { 
							Char = mn.charAt(i); 
							if (ValidChars.indexOf(Char) == -1) {
								IsNumber = false;
							}
						}
					
						if(IsNumber == false){
							mn = 00;
						}
					}
				} else {//if there is no A or P in the string
					var mn_xmArr = timecellarr[1].split(" ");//removes the space, treats this as 24 hour time.
					//check to see if mn is a number
						var ValidChars = "0123456789.";
						var IsNumber=true;
						var Char;
						for (i = 0; i < mn.length && IsNumber == true; i++) { 
							Char = mn.charAt(i); 
							if (ValidChars.indexOf(Char) == -1) {
								IsNumber = false;
							}
						}
					
						if(IsNumber == false){
							mn = 00;
						}
				}
			} else {//there is info before and after the space -->--> error checking???
				var mn_xmArr = timecellarr[1].split(" ");
				var mn = mn_xmArr[0];
				var xm = mn_xmArr[1];//for am/pm		
			}
//alert ("after there is a space in the string, mn:"+mn+" xm:"+xm);
		} else {//there is no space in the string
//alert ("there is no space in the string");
			//what to do if there is no space between mn and xm, or mn/xm has been omitted
			if (strCell.search("A") != -1) {//if there is an A in the string
				if(timecellarr[1].indexOf("A") == 0){//example 8:Ax
					var mn = "00";
					var xm = "AM";
				} else {//example 8:30Ax
					var mn = timecellarr[1].substr(0,timecellarr[1].indexOf("A"));
					//var xm = timecellarr[1].substr(timecellarr[1].indexOf("A"));
					var xm = "AM";
					
					//check to see if mn is a number
					var ValidChars = "0123456789.";
					var IsNumber=true;
					var Char;
					for (i = 0; i < mn.length && IsNumber == true; i++) { 
						Char = mn.charAt(i); 
						if (ValidChars.indexOf(Char) == -1) {
							IsNumber = false;
						}
					}
					
					if(IsNumber == false){
						mn = 00;
					}
				}
			} else if (strCell.search("P") != -1) {//if there is a P in the string			
				if(timecellarr[1].indexOf("P") == 0){
					var mn = "00";
					var xm = "PM";
				} else {
					var mn = timecellarr[1].substr(0,timecellarr[1].indexOf("P"));
					//var xm = timecellarr[1].substr(timecellarr[1].indexOf("P"));
					var xm = "PM";
					
					//check to see if mn is a number
					var ValidChars = "0123456789.";
					var IsNumber=true;
					var Char;
					for (i = 0; i < mn.length && IsNumber == true; i++) { 
						Char = mn.charAt(i); 
						if (ValidChars.indexOf(Char) == -1) {
							IsNumber = false;
						}
					}
					
					if(IsNumber == false){
						mn = 00;
					}
				}
			} else {//if there is no A or P in the string
				var mn = timecellarr[1];//treat as 24 hour time
				//check to see if mn is a number
					var ValidChars = "0123456789.";
					var IsNumber=true;
					var Char;
					for (i = 0; i < mn.length && IsNumber == true; i++) { 
						Char = mn.charAt(i); 
						if (ValidChars.indexOf(Char) == -1) {
							IsNumber = false;
						}
					}
					
					if(IsNumber == false){
						mn = 00;
					}
			}			
//alert ("after there is no space in the string, mn:"+mn+" xm:"+xm);		
		}
	} else {//there is no : in the string
//LEFT OFF HERE -- need to get these other options working, or omit them all together, and let it bomb if there is no : in the time
//var timecell = strCell.toUpperCase();
//var timecelllen =timecell.length;	
		//below works for correctly formated "hhmm X(M)", "hhmmX(M)", "hh", "hh X(M)", "hhX(M)", "hh mmX(M)", "hh mm X(M)"
		//"hhmm","hh mm"(treat as 24hour time)
		if (timecell.search(" ") != -1) {//if there is a " " in the string
			//var timecellarr = timecell.split(" ");
			//var hr = timecellarr[0];
			//if(timecell.indexOf(" ") == 0){//space is the first character
			//} else 
			if(timecell.indexOf(" ")  == 1 || timecell.indexOf(" ")  == 2){//index values 1,2
			  //first space after 1/2 chars (h mm,hh mm,hh mmXM,hh XM)
			  //AND more than on space: hh mm XM
				//var timecellarr = timecell.split(" ");
				//var hr = timecellarr[0];
				var hr = timecell.substr(0,timecell.indexOf(" "));//example "h " or "hh "

				var mn_xm = timecell.substr(timecell.indexOf(" "));//example "mm" or "mmxm" or "mm xm"
				if (mn_xm.length == 0){//minute and a/pm omitted, treated as 24 hour time
					var mn = "00";
					var xm = ""; 
				} else if(mn_xm.indexOf(" ") > 1){//if there is additional spaces in the string //mm XM					
					if(mn_xm.indexOf(" ") == 0){//the first char after the space is a space
						if (mn_xm.search("A") != -1) {//if there is an A in the string
							if(mn_xm.indexOf("A") == 1){//example 8: Ax
								var mn = "00";
								var xm = "AM";
							} else {//example "8: 30 Ax" or "8: 30Ax"
								var mn = mn_xm.substr(0,mn_xm.indexOf("A"));
								//var xm = mn_xm.substr(mn_xm.indexOf("A"));
								var xm = "AM";
					
								//check to see if mn is a number
								var ValidChars = "0123456789.";
								var IsNumber=true;
								var Char;
								for (i = 0; i < mn.length && IsNumber == true; i++) { 
									Char = mn.charAt(i); 
									if (ValidChars.indexOf(Char) == -1) {
										IsNumber = false;
									}
								}
					
								if(IsNumber == false){
									mn = 00;
								}
							}
						} else if (mn_xm.search("P") != -1) {//if there is a P in the string			
							if(mn_xm.indexOf("P") == 1){
								var mn = "00";
								var xm = "PM";
							} else {
								var mn = mn_xm.substr(0,mn_xm.indexOf("P"));
								//var xm = mn_xm.substr(mn_xm.indexOf("P"));
								var xm = "PM";
							
								//check to see if mn is a number
								var ValidChars = "0123456789.";
								var IsNumber=true;
								var Char;
								for (i = 0; i < mn.length && IsNumber == true; i++) { 
									Char = mn.charAt(i); 
									if (ValidChars.indexOf(Char) == -1) {
										IsNumber = false;
									}
								}
							
								if(IsNumber == false){
									mn = 00;
								}
							}
						} else {//if there is no A or P in the string
							var mn_xmArr = mn_xm.split(" ");//removes the space, treats this as 24 hour time.
							//check to see if mn is a number
								var ValidChars = "0123456789.";
								var IsNumber=true;
								var Char;
								for (i = 0; i < mn.length && IsNumber == true; i++) { 
									Char = mn.charAt(i); 
									if (ValidChars.indexOf(Char) == -1) {
										IsNumber = false;
									}
								}
					
								if(IsNumber == false){
									mn = 00;
							}
						}
					} else {//there is info before and after the space -->--> error checking???											
						var mn = mn_xm.substr(0,mn_xm.indexOf(" "));//example "mm " or "mm "
						var xm = mn_xm.substr(mn_xm.indexOf(" "));//example "xm" or " xm"
		
					}
					//var mn = mn_xmarr.substr(0,mn_xmarr.indexOf(" "));
					//var xm = mn_xmarr.substr(mn_xmarr.indexOf(" "));
				} else {//only one space in string //(hh mmXM,hh XM)
					//how to split time from XM
				}
		  	} else if (timecell.indexOf(" ") > 2){//index values higher than 2
		  	//first space after 3/4 chars (hmm xx,hhmm xx)
		  			//how to split hh from mm
			}

		//no spaces at all (h,hh,hhmm,hhXM,hhmmXM)
		} else {//there are NO spaces in the string	
			//if (timecell.length > 2){//minute and a/pm omitted, treated as 24 hour time
				//AND value is only numbers example: 8 or 08 or 10 -- else could be 8A,8P
			//	var mn = "00";
			var xm = ""; 
			//}
		//need to figure out a way to tell if there are no spaces: how to tell which are the first 2 digits -->missing leading zero? example: 810AM -NOT= hh-81 mm 0A xm M
/*
			if (strCell.search("A") != -1) {//if there is an A in the string
				if(timecellarr[1].indexOf("A") == 0){//example 8:Ax
					var mn = "00";
					var xm = "AM";
				} else {//example 8:30Ax
					var mn = timecellarr[1].substr(0,timecellarr[1].indexOf("A"));
					//var xm = timecellarr[1].substr(timecellarr[1].indexOf("A"));
					var xm = "AM";
					
					//check to see if mn is a number
					var ValidChars = "0123456789.";
					var IsNumber=true;
					var Char;
					for (i = 0; i < mn.length && IsNumber == true; i++) { 
						Char = mn.charAt(i); 
						if (ValidChars.indexOf(Char) == -1) {
							IsNumber = false;
						}
					}
					
					if(IsNumber == false){
						mn = 00;
					}
				}
			} else if (strCell.search("P") != -1) {//if there is a P in the string			
				if(timecellarr[1].indexOf("P") == 0){
					var mn = "00";
					var xm = "PM";
				} else {
					var mn = timecellarr[1].substr(0,timecellarr[1].indexOf("P"));
					//var xm = timecellarr[1].substr(timecellarr[1].indexOf("P"));
					var xm = "PM";
					
					//check to see if mn is a number
					var ValidChars = "0123456789.";
					var IsNumber=true;
					var Char;
					for (i = 0; i < mn.length && IsNumber == true; i++) { 
						Char = mn.charAt(i); 
						if (ValidChars.indexOf(Char) == -1) {
							IsNumber = false;
						}
					}
					
					if(IsNumber == false){
						mn = 00;
					}
				}
			} else {//if there is no A or P in the string
				var mn = timecellarr[1];//treat as 24 hour time
				//check to see if mn is a number
					var ValidChars = "0123456789.";
					var IsNumber=true;
					var Char;
					for (i = 0; i < mn.length && IsNumber == true; i++) { 
						Char = mn.charAt(i); 
						if (ValidChars.indexOf(Char) == -1) {
							IsNumber = false;
						}
					}
					
					if(IsNumber == false){
						mn = 00;
					}
			}			
*/
		}

	}
	
//alert ("hr: "+hr+" mn:"+mn+" xm:"+xm);
	
	if(xm == "AM" || xm == "A") { 
		if (hr == 12){
			hr = 0;
		}//else { hr = hr; }
//alert ("after am check: hr: "+hr+" mn:"+mn+" xm:"+xm);
	} else if(xm == "PM" || xm == "P") {
		if(hr < 12){//so noon doesn't become midnight
    		hr = parseInt(hr) + 12;
		}
	} //else if am/pm is left out, look at hour and act as if this was entered as 24 hour time

//alert ("after pm check: hr: "+hr+" mn:"+mn+" xm:"+xm);

	var timecell12 = hr+':'+mn+':00';
//alert ("hr: "+hr+" mn:"+mn+" xm:"+xm+"\ntimecell12: "+timecell12);
		
	strCell = timecell12;
	//dateFormat(strCell, "HH:MM:ss")
	
	strCell = strCell.replace(/&/g,"%26");
	strCell = strCell.replace(/"/g,'\\"');
	//strCell = strCell.replace(/'/g,"\\'");
	var strParams="auth="+auth+"&bmethod=put&rowid="+id+"&putdata="+strCell;
	var req = getXMLHTTP();

	if (req) {
		req.open("POST", strURL, true);
		//Send the proper header information along with the request
		req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		
		req.onreadystatechange = function() {
			if (req.readyState == 4) {
				// only if "OK"
				if (req.status == 200) {
					//NOTE:req.responseText for get,req.statusText for post
				} else {
					alert("There was a problem while using XMLHTTP:\n" + req.statusText);
				}
			}				
		}			
		req.send(strParams);
	}			
}
function bananafresh(auth,id,editrow,inout,eachcell,row,returndata) {		
	bananarefresh(auth,id,editrow[eachcell+1],inout);
	row.deleteCell(eachcell);
	editrow[eachcell].style.display='';

	//REARM onclick handler event trap
	if (inout) {
		editrow[eachcell].onclick=function(){ editinline(auth,id,this,inout);};
	} else {
		editrow[eachcell].onclick=function(){ editinline(auth,id,this);};
	}
}
function bananarefresh(auth,id,cell,inout) {
	var strURL="pma-ajaxcell.php";
	var strParams="auth="+auth+"&bmethod=get&rowid="+id;
	var req = getXMLHTTP();
		
	if (req) {
		req.open("POST", strURL, true);
		//Send the proper header information along with the request
		req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		
		req.onreadystatechange = function() {
			if (req.readyState == 4) {
				// only if "OK"
				if (req.status == 200) {
					var celdata = eval('(' + req.responseText + ')');
					//var oldceldata = cell.innerHTML;					
					cell.innerHTML=celdata[0];
					if (inout) { //if inout is specified (not undefined) call a local function to do whatever follow up is needed --used to change other cells based on the change done here.
						//editinlinelocal(auth,id,cell,inout); 
						<?
						echo $editinlinelocal;
						?>
					}
				} else {
					alert("There was a problem while using XMLHTTP:\n" + req.statusText);
				}
			}				
		}			
		req.send(strParams);
	}			
}
function bananarefresh12to24(auth,id,cell,inout) {
	var strURL="pma-ajaxcell.php";
	var strParams="auth="+auth+"&bmethod=get&rowid="+id;
	var req = getXMLHTTP();
		
	if (req) {
		req.open("POST", strURL, true);
		//Send the proper header information along with the request
		req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		
		req.onreadystatechange = function() {
			if (req.readyState == 4) {
				// only if "OK"
				if (req.status == 200) {
					var celdata = eval('(' + req.responseText + ')');
					var oldceldata = cell.innerHTML;
					//CODE TO DO 24 to 12 Conversion display here...
					//What to do if it isn't stored correctly? just dump stored data? -- Note that calculation will not work properly -- may need to add error checking to that code				
					var timecell = celdata[0];
					var timecellarr = timecell.split(":");
					var hr = timecellarr[0];
					var mn = timecellarr[1];
					//var msec = timecellarr[2];
					var xm;//for am/pm
					if(hr > 12) {
					    hr = hr - 12; xm="PM";
					} else {
						xm="AM";
					}
					if(hr == 12) { xm="PM" }
					if(hr == 00) { hr = 12; }
					var timecell12 = hr+':'+mn+' '+xm;
					
					//cell.innerHTML=celdata[0];
					cell.innerHTML = timecell12;
					//cell.innerHTML=dateFormat(celdata[0], "h:MM TT");
					if (inout) { //if inout is specified (not undefined) call a local function to do whatever follow up is needed --used to change other cells based on the change done here.
						//editinlinelocal(auth,id,cell,inout); 
						<?
						echo $editinlinelocal;
						?>
					}
				} else {
					alert("There was a problem while using XMLHTTP:\n" + req.statusText);
				}
			}				
		}			
		req.send(strParams);
	}			
}
		
function pulldownunbanana(auth,id,cell,inout) {	//modify this to reset the cell.innerHTML back to text --> ment for focus change with no value change	
		var cellidx = cell.cellIndex;    
		//alert ("cellidx: "+cellidx);     
		var row = parentByTag(cell,'TR');
		//alert ("row: "+cellidx);     
		var tbl = parentByTag(row,'TABLE');
		//alert ("tbl: "+cellidx);     
		var editrow = row.cells;
		//alert ("editrow: "+cellidx);     
		
		for(eachcell=0; eachcell < editrow.length; eachcell++) {
			if(eachcell==cellidx){	
				//compare new data to original data and determine if sql post call is needed
//				if(editrow[eachcell].firstChild.value!=editrow[eachcell+1].innerHTML){//NOTE editrow[eachcell+1] is hidden cell with orginal value
				//if data has changed
//					bananapost(auth,id,editrow[eachcell]);
//					editrow[eachcell].innerHTML = "Posting...";
					//alert('id: '+id);
//					bananarefresh(auth,id,editrow[eachcell+1],inout);
//					row.deleteCell(eachcell);
//					editrow[eachcell].style.display='';
//				} else {
				//else put original cell innerHTML back
				//data wont have changed, with pulldown version of function, onchange is used if there was a change				
					editrow[eachcell+1].innerHTML= "<span style=\"visibility:hidden\">"+document.getElementById(id).options[document.getElementById(id).selectedIndex].value+"</span>"+ document.getElementById(id).options[document.getElementById(id).selectedIndex].text;
//LEFT OFF HERE: -- Fix why does this not delete the Cell with the pulldown in it?
					row.deleteCell(eachcell);
					editrow[eachcell].style.display='';
//				}
				//REARM onclick handler event trap
				if (inout) {
					//editrow[eachcell].onclick=function(){ editinline(auth,id,this,inout);};
				} else {
					//editrow[eachcell].onclick=function(){ editinline(auth,id,this);};
				}
			}
		}	
}

function epulldowninline(auth,id,src,cell,inout) {		
//epulldowninline       ('0', 'id.hrscheds.name.NULL.121','Contact_Info.Full_Name.50.Status=\"C\"' this)
		var cellidx = cell.cellIndex;
		var row = parentByTag(cell,'TR');
		var tbl = parentByTag(row,'TABLE');
		var editrow = row.cells;

		for(eachcell=0; eachcell < editrow.length; eachcell++) {
			if(eachcell==cellidx){
				//editrow[eachcell].innerHTML="banana cell";
				editrow[eachcell].onclick='';
				editrow[eachcell].style.display='none';
				var newbanana=row.insertCell(eachcell);
				if (editrow[eachcell+1].rowSpan == 2){
				newbanana.rowSpan=editrow[eachcell+1].rowSpan;
				}
				//NOTE: newbanana now = editrow[eachcell], the old cell content is now in editrow[eachcell+1]
				//newbanana.bgColor=editrow[eachcell+1].bgColor;
				editrow[eachcell].bgColor=editrow[eachcell+1].bgColor;
				//var bananapulldown=editrow[eachcell].innerHTML=document.createElement('select');
				var bananapulldown=document.createElement('select');
				bananapulldown.setAttribute('id', id);
//NOTE:LEFT OFF HERE -- need to write pulldownunbananapost and pulldownunbanana -- they don't exisit yet!, and they must come BEFORE this function in the code.

				editrow[eachcell].appendChild(bananapulldown);

				var bananaOption = new Array();
			
				var strURL="pma-ajaxpulldown.php";
				//replace & or " so it doesn't break URL call
				var strCell = editrow[eachcell+1].innerHTML;
				strCell = strCell.replace(/&/g,"%26");
				strCell = strCell.replace(/"/g,'\\"');
				//strCell = strCell.replace(/'/g,"\\'");
				var strParams="auth="+auth+"&bmethod=put&rowid="+id+"&pullsrc="+src+"&putdata="+strCell;
				//alert ("strCell pre-replace: "+editrow[eachcell+1].innerHTML+"<br>strCell post-replace: "+strCell+"<br>strParams: "+ strParams);
				var req = getXMLHTTP();
				if (req) {
					req.open("POST", strURL, true);
					//Send the proper header information along with the request
					req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		
					req.onreadystatechange = function() {
						if (req.readyState == 4) {
							// only if "OK"
							if (req.status == 200) {
								//NOTE:req.responseText for get,req.statusText for post
								var celdata = eval('(' + req.responseText + ')');
								//#var oldceldata = cell.innerHTML;					
								//alert (celdata[0]);
								for (eachbanana in celdata){
									//alert (celdata[eachbanana]);
									bananaOption[eachbanana] = document.createElement('option');
									bananaOption[eachbanana].text = (celdata[eachbanana].split("</span>",2))[1];//Last, First
									//bananaOption[eachbanana].text = ((celdata[eachbanana].split("</span>",2))[0]).split("<span style=\"visibility:hidden\">",2)[1];//Last, First
									//bananaOption[eachbanana].text = celdata[eachbanana];//Last, First
									bananaOption[eachbanana].value = ((celdata[eachbanana].split("</span>",2))[0]).split("<span style=\"visibility:hidden\">",2)[1];//ID
									bananapulldown.add(bananaOption[eachbanana]);
									if ( ((celdata[eachbanana].split("</span>",2))[0]).split("<span style=\"visibility:hidden\">",2)[0] == "@") {
										bananapulldown.selectedIndex = eachbanana;
									}
								}
								
							} else {
								alert("There was a problem while using XMLHTTP:\n" + req.statusText);
							}
						}				
					}			
					req.send(strParams);
				}

					//document.getElementById(id).onblur = function() { alert("I hear you");/*pulldownunbananapost(auth,id,src,cell,inout);*/ };

				if(inout){
					document.getElementById(id).onblur = function() { /*alert("I hear you");*/pulldownunbanana(auth,id,cell,inout); };
					//document.getElementById(id).addEventListener ("onblur", function() { alert("I hear you");/*pulldownunbananapost(auth,id,src,cell,inout);*/ }, false);
					//editrow[eachcell].firstChild.addEventListener ("onchange", function() { pulldownunbananapost(auth,id,src,cell,inout); }, false);
					//bananapulldown.addEventListener ("onchange", function() { pulldownunbananapost(auth,id,src,cell,inout); }, false);
					//bananapulldown.addEventListener ("onblur", function() { pulldownunbanana(auth,id,src,cell,inout); }, false);
						//'"unbanana('+"'"+auth+"','"+id+"'"+',this.parentNode,'+"'"+inout+"'"+');">'
				} else {
					document.getElementById(id).onblur = function() { /*alert("I hear you");*/pulldownunbanana(auth,id,cell); };
					//document.getElementById(id).addEventListener ("onblur", function() { alert("I hear you");/*pulldownunbananapost(auth,id,src,cell);*/ }, false);
					//editrow[eachcell].firstChild.addEventListener ("onchange", function() { pulldownunbananapost(auth,id,src,cell); }, false);
					//bananapulldown.addEventListener ("onchange", function() { pulldownunbananapost(auth,id,src,cell); }, false);
					//bananapulldown.addEventListener ("onblur", function() { pulldownunbanana(auth,id,src,cell); }, false);
					//editrow[eachcell].innerHTML='<textarea name="'+id+'" onblur="unbanana('+"'"+auth+"','"+id+"'"+',this.parentNode);">'+editrow[eachcell+1].innerHTML+"</textarea>";
				}				
				editrow[eachcell].firstChild.focus();
			    //editrow[eachcell].firstChild.innerHTML="Banana";
				
				//alert ("firstChild is:"+editrow[eachcell].innerHTML);
			}
		}
}

</script>
Return current item: phpMyAccess