Member Avatar for jpknoob

Hello all, afetr receiving such excellent help regarding my first ajax file, i have received an error in my code that i have not encountered before.

I have created a form with input fields and when the button is clicked, three functions are run, the first is an ajax call to a php file that creates and populates a table based on values from the database, the second executes the calculation function, the third takes the calculation results and inserts them into the table created from the ajax call.

After all my tests, i found the error lies in the calculation.js file, the following code works;

function multiply()	{

document.getElementById("A").value = (calculation) ;
			
document.getElementById("B").value = (another_calculation) ;
				
document.getElementById("C").value = (another_calculation) ;

document.getElementById("D").value = (another_calculation) ;

alert("Calculation done");
}

//POPULATE ORDER TABLE WITH RECOMMENDED VALUES

function fillOrder()	{
document.getElementById("A_order").value = document.getElementById("A").value;
document.getElementById("B_order").value = document.getElementById("B").value;
document.getElementById("C_order").value = document.getElementById("C").value;
document.getElementById("D_order").value = document.getElementById("D").value;

alert("Orders values added");
}

However, when i remove the alerts, i get an error in the javascript saying antibody_order is null.

Member Avatar for diafol

As ajax is asynchronous, are you running the 2 non-ajax functions before the ajax call has completed and created the table ids? How about running the two functions from inside the 'success' function of the ajax call?

I can only assume that the element with id="antibody_order" does not (yet) exist when fillOrder() is executed.

It's impossible to say for certain by looking at just these two functions but I would suggest that either:

  • there's a typo in the HTML or javascript
  • there's a "race effect" - fillOrder() depends on the AJAX response but executes before it arrives.

Airshow

Member Avatar for jpknoob

Thanks for the comments, i will try execute the JS after the ajax call.

Member Avatar for jpknoob

What would be the best way to execute this? What i am trying to do is run the ajax call first so that it retrieves information from the database and builds the table. The second script should be the calculations, and finally, the final script should take the calculation values and insert them to the new table created. I have been looking at callback, but have no idea how to use them

From your original post, you appeared to have written the function that performs the ajax call and handles its response, though you didn't actually include it in the post.

If this is not the case then you need to make an attempt at writing it. Lots of tutorials and other advice exist on the web to help with this.

When you have it working enough to build out your table then you need to do exactly what my old friend Ardav says - call the other two functions from inside the ajax response handler.

If you have problems with it, then post the code here.

Airshow

Member Avatar for jpknoob

sorry, here is my html code;

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
		<link rel="stylesheet" href="style.css" type="text/css" />
		<title>Calculator</title>
		
		<!-- INCLUDE AJAX FUNCTIONS -->
		<script type="text/javascript" src="ajaxFunctions.js"></script>
		
		<!-- Include Calculation script -->
		<script type="text/javascript" src="calculations.js"></script>
		
	</head>
	
	<body onload="populate();">

		<div id="drop_down"></div>
				
		<form id="input">
			<fieldset>
			
				<!-- Input table -->
				
				<!-- Execute calculation function on click and reset -->
				<input type="button" class="calc" onclick="processInput(), multiply(), fillOrder();"/>
				<input type="button" class="reset" onclick="formReset()"/>
				
				<br />
				<br />
			
				<!-- Results Table -->
				
			
			</fieldset>
		</form>

My ajax functions;

//POPULATE DROP DOWN FROM DATABASE
function populate() {
	var xmlhttp; 
	
	if (window.XMLHttpRequest) {
		// code for IE7+, Firefox, Chrome, Opera, Safari
		xmlhttp=new XMLHttpRequest();
	}
	
	// code for IE6, IE5
	else {
		xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
	}
	 
	xmlhttp.onreadystatechange=function() {
		if (xmlhttp.readyState==4 && xmlhttp.status==200) {
		document.getElementById("drop_down").innerHTML=xmlhttp.responseText;
		}
	}
	 
	xmlhttp.open("GET","populate.php",true);
	xmlhttp.send();
}


//FILL THE CUSTOMER ORDER TABLE 
function processInput(var1) {
	var xmlhttp; 
	
	var1 = document.getElementById("kinase_selection").value;
	
	if (var1=="") {
		document.getElementById("orderTable").innerHTML="";
		return;
	}
	 
	if (window.XMLHttpRequest) {
		// code for IE7+, Firefox, Chrome, Opera, Safari
		xmlhttp=new XMLHttpRequest();
	}
	
	// code for IE6, IE5
	else {
		xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
	}
	 
	xmlhttp.onreadystatechange = function() {
		if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
		document.getElementById("orderTable").innerHTML = xmlhttp.responseText;
		}
	}
	 
	xmlhttp.open("GET","processInput.php?kinase_selection="+var1,true);
	xmlhttp.send();
}

and my calculations;

//CALCULATE INPUT VALUES

function multiply()	{

document.getElementById("antibody").value = 
	((parseFloat(document.getElementById("wells").value) * 
		parseFloat(document.getElementById("assay").value) * 
			parseFloat(document.getElementById("antibody_concentration").value) * 150) / 1000000) ;
			
document.getElementById("kinase").value = 
	((parseFloat(document.getElementById("wells").value) * 
		parseFloat(document.getElementById("assay").value) * 
			parseFloat(document.getElementById("kinase_concentration").value) * 
				parseFloat(document.getElementById("kinase_weight").value)) / 1000000) ;
				
document.getElementById("tracer").value = 
	((1000000 / parseFloat(document.getElementById("tracer_concentration2").value)) * 
		(parseFloat(document.getElementById("wells").value) * 
			parseFloat(document.getElementById("assay").value) * 
				parseFloat(document.getElementById("tracer_concentration").value) / 1000000) / 1000) ;

document.getElementById("buffer").value = 
	(parseFloat(document.getElementById("wells").value) * 
		parseFloat(document.getElementById("assay").value) / 5000) ;

}

//POPULATE ORDER TABLE WITH RECOMMENDED VALUES

function fillOrder()	{

document.getElementById("antibody_order").value = document.getElementById("antibody").value;
document.getElementById("kinase_order").value = document.getElementById("kinase").value;
document.getElementById("tracer_order").value = document.getElementById("tracer").value;
document.getElementById("buffer_order").value = document.getElementById("buffer").value;

alert("Table updated!");
}

Lines 47-51 in processInput() appear to be the ajax response handler in question.

Try calling multiply() and fillOrder() immediately after line 49.

Airshow

Member Avatar for jpknoob

Unfortunately that didn't work.

I have added alerts after each function called first, second and third step, so I can attempt to track the execution, however, in firefox and chrome, I get all 3 alerts in order, the code works only in firefox and in Safari, I only get 2 alerts! very confusing.

jp,

First, relax the !Doctype from strict to transitional.

Second, have you addressed this line?

<input type="button" class="calc" onclick="processInput(), multiply(), fillOrder();"/>

It may be giving an error due to the commas (should be semi-colons) but in any case should now be reduced to:

<input type="button" class="calc" onclick="processInput();" />

Third, do you see error messages in the browsers' javascript error consoles? If so, they should lead you to the problem line(s).

It is most likely that the code is trying to address an element by id, that doesn't exist. For example, document.getElementById("xxx").value will throw an error if an element with id="xxx" does not exist.

The safe way to do this is to separate out node discovery from node usage, and wrap the node usage in some safety, as follows:

var xxx = document.getElementById("xxx");
var yyy = document.getElementById("yyy");
if(xxx && yyy) {
    xxx.value = yyy.value;
}

For debugging purposes, you can add else{...} clauses to the safety, to provide alerts (or console.log messages). Again, these should help lead you to the problem line(s).

Airshow

Member Avatar for jpknoob

Thanks for the help Airshow, it is greatly appreciated.

I have changed the doctype and I had previously tried the ';' option, but to no avail.

I have this in my ajax calls;

if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
		document.getElementById("orderTable").innerHTML = xmlhttp.responseText;
		multiply();
		fillOrder();
		}
	}

When I run this, I don't get any error messages or alerts from the javascript functions, have I done this the wrong way?

When the code is run with my original script, it just says;

49TypeError: 'null' is not an object (evaluating 'document.getElementById("antibody_order").value = document.getElementById("antibody").value')

Have you tried alerting out xmlhttp.responseText ?
Does the server provide exactly what you expect?
Are all the necessary ids correctly in place?

Airshow

Member Avatar for jpknoob

I tried alerting out the xmlhttp.responseText and i get exactly what i expect, a table with values from the database and correct id's

What type of element is "orderTable"?

Member Avatar for jpknoob

Plain old div

Mmmm, I'm out of ideas for now.

Can you set up a jsfiddle so I can play with it.

Back later - must go to work now.

Airshow

Member Avatar for jpknoob

Sure, never used it before, but will get it setup.

Again, much appreciated!

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.