I am trying to write a script that will update my database(s) without the user having to click any buttons. I also want the update to occur whenever a field is modified in the form.

So here is an example form

<form>
<input type="text" name="fieldone" value="currentvalfromdb" onChange="updateDB()" />
<select name="selectone" onChange="updateDB()">
<option value="currentvalfromdb">currentvalfromdb</option>
<option value="1">1</option>
...
</select>
<textarea name="textarea1" onChange="updateDB()">currentvalfromdb</textarea>
</form>

Now whenever a user changes a value on any one of the fields, the field is updated in the DB and a confirmation is printed below the field saying "Data Updated" or something to that effect.

Now using ajax I've been able to update a single field. But the script I'm using assigns the updated value to the same variable every time (in this case it's 'q').

the javascript looks like this (I found this on the web all over the place)

var xmlHttp;

function updateDB(str)
{ 
xmlHttp=GetXmlHttpObject();
if (xmlHttp==null)
 {
 alert ("Browser does not support HTTP Request");
 return;
 }
var url="scripts/ajaxProcess.php";
url=url+"?q="+str;
//url=url+"&sid="+Math.random();
xmlHttp.onreadystatechange=stateChanged;
xmlHttp.open("GET",url,true);
xmlHttp.send(null);
}

function stateChanged() 
{ 
if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete")
 { 
 document.getElementById("txtHint").innerHTML=xmlHttp.responseText;
 } 
}

function GetXmlHttpObject()
{
var xmlHttp=null;
try
 {
 // Firefox, Opera 8.0+, Safari
 xmlHttp=new XMLHttpRequest();
 }
catch (e)
 {
 //Internet Explorer
 try
  {
  xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
  }
 catch (e)
  {
  xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
 }
return xmlHttp;
}

I see why the variable 'q' ends up being what is passed to the db update script. What I need is for this variable to be dynamic, that is to say, that the variable name changes per field. I 'could' just assign a var for each variable in the script, but problem a: there are 6 different tables involved in this update and problem b: there are almost 50 fields to work with and they may change from time to time; I don't what to have to do extra work if I don't have to.

Is there a way to write the script so that it will dynamically figure out the field name (I will use the database field name as the form field name, to keep it simple) and assign THAT field name to the $_GET's name? A bit more simple, but I would also include the table name in the field name (so something like table|fieldname as the field name) so when the variable is sent to be processed, it'll know which table to query, which field, and what the new value is. I suppose I'll also have to send the old value (or the id for the row of that table being updated) so it may need to be something like "table|row|fieldname"

If I can get assistance with the first part (dynamic variable name), I can figure out the second half pretty easily.

Thanks!!

Recommended Answers

All 2 Replies

Petrakid,

There are various ways to do this. Here's one:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style>
</style>

<script type='text/javascript'>
function GetXmlHttpObject() {
  var xmlHttp = null;
  try {
    // Firefox, Opera 8.0+, Safari
    xmlHttp=new XMLHttpRequest();
  }
  catch (e) {
    //Internet Explorer
    try {
      xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch (e) {
      xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
  }
  return xmlHttp;
}

function updateDB(formElement, elementType, txtHint, xmlHttp, tim) {
  clearTimeout(tim);
  xmlHttp.abort();//abort any incomplete request for this request object that is currently in progress.
  var val = null, timeoutVal = 5000;
  switch(elementType) {
    case 'select':
      val = formElement[formElement.selectedIndex].value;
    break;
	//possibly add further cases for other formElement types here
    default:
      val = formElement.value;
    break;
  }
  if (val !== null) {
    var url = "scripts/ajaxProcess.php?" + formElement.name + '=' + val;
    url += "&sid=" + new Date().getTime();//good idea to avoid the consequences of cacheing
    txtHint.innerHTML = 'updating...';
    tim = setTimeout(function(){
	  if(txtHint){
        xmlHttp.abort();
        if(txtHint) { txtHint.innerHTML = 'timeout'; }
	  }
    }, timeoutVal);
    xmlHttp.onreadystatechange = function() {
      if (xmlHttp.readyState==4) {
        clearTimeout(tim);
        if (xmlHttp.status==200) {//success
          if(txtHint) { txtHint.innerHTML = xmlHttp.responseText; }//or something based on xmlHttp.responseText
        }
        else {//error
          if(txtHint) { txtHint.innerHTML = "update failed (" + xmlHttp.status + ")"; }
	    }
      }
    };
    xmlHttp.open("GET", url, true);
    xmlHttp.send(null);
  }
}

function updateDB_closure(formElement, elementType) {//formElement and elementType are trapped in the closure and are reused
	var xmlHttp = GetXmlHttpObject();//xmlHttp is trapped in the closure and is reused
	if (xmlHttp==null) {
		alert ("Browser does not support HTTP Request");
		return;
	}
    var txtHint = document.getElementById(formElement.getAttribute("txtHintID"));//txtHint is trapped in the closure and is reused
	var tim;
	return function(evt) {//this retuned function becomes the handler for the designated event
		updateDB(formElement, elementType, txtHint, xmlHttp, tim);//use of the variables here causes a closure to be formed.
	};
}

onload = function(){
	var i;
	var elements = document.getElementsByTagName('input');
	for(i=0; i<elements.length; i++){
		if(elements[i].className.indexOf('updateDB') > -1){
			elements[i].onblur = updateDB_closure(elements[i], 'input');
		}
	}
	elements = document.getElementsByTagName('select');
	for(i=0; i<elements.length; i++){
		if(elements[i].className.indexOf('updateDB') > -1){
			elements[i].onchange = updateDB_closure(elements[i], 'select');
		}
	}
	elements = document.getElementsByTagName('textarea');
	for(i=0; i<elements.length; i++){
		if(elements[i].className.indexOf('updateDB') > -1){
			elements[i].onblur = updateDB_closure(elements[i], 'textarea');
		}
	}
	//attach event handlers for further types of form element here.
}
</script>
</head>

<body>

<form>
<input class="updateDB" type="text" name="fieldone" txtHintID="txthint_1" value="currentvalfromdb" />
<span id="txthint_1"></span><br/>

<select class="updateDB" name="selectone" txtHintID="txthint_2">
<option value="currentvalfromdb">currentvalfromdb</option>
<option value="1">1</option>
<option value="2">2</option>
...
</select>
<span id="txthint_2"></span><br/>

<textarea class="updateDB" name="textarea1" txtHintID="txthint_3">currentvalfromdb</textarea>
<span id="txthint_3"></span><br/>

</form>

</body>
</html>

Notes:

  • onblur/onchange handlers are attached in javascript, not in HTML.
  • updateDB behaviour is determined by presence of class="updateDB";
  • GetXmlHttpObject() is only called once per form element. Associated variables are also established once per form element.
  • Error conditions, including timeout, are appropriately handled.
  • A bonus of a reusable xmlHttp object is that we can .abort() a previous request before issuing a new one (and clear the timeout).

Airshow

Thanks! I see what you did here and I'll give it a shot!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.