AJAX/DOM - Works in FF but not IE?

A

adam

Hey All,

I'm relatively new to all this and any help would be appreciated.
What I'm aiming to do is create a few requests, to
1. Search for a Student against XML created from the database
2. If more than one student, list all students using DOM
3. Finally, return individual student and enrolments.

Heres the code (sorry it's going to be a long one):
request.php
------------------------------------------------------
<html>
<head>
<title>AJAX Request Test</title>
<script language="javascript">
<!--
function createRequestObject() {
var ro;
var browser = navigator.appName;
if(browser == "Microsoft Internet Explorer"){
ro = new ActiveXObject("Microsoft.XMLHTTP");
}
else {
ro = new XMLHttpRequest();
}
return ro;
}

http = createRequestObject();

function searchStudents() {
updateStatus('show', 'Searching for students...', 'working');

var params = "";
var search_adno = document.getElementById('search_adno').value;
var search_forenames =
document.getElementById('search_forenames').value;
var search_surname = document.getElementById('search_surname').value;
var search_dob = document.getElementById('search_dob').value;

if (search_adno != "") params += 'student_studentreference='+
search_adno;

if (search_forenames != "") {
if (params != "") params += '&student_forenames='+ search_forenames;
else params += 'student_forenames='+ search_forenames;
}
if (search_surname != "") {
if (params != "") params += '&student_surname='+ search_surname;
else params += 'student_surname='+ search_surname;
}
if (search_dob != "") {
if (params != "") params += '&student_dob='+ search_dob;
else params += 'student_dob='+ search_dob;
}

if (params != "") {
http.open('post', 'student.xml');
//http.overrideMimeType('text/xml');
http.onreadystatechange = listStudents;
http.send(params);
}
else {
alert('You must enter search criteria');
}
}

function listStudents() {
if(http.readyState == "4"){
updateStatus('hide');

var response = http.responseXML.documentElement;
var div = document.getElementById('results');
var string = "";

var results = response.getElementsByTagName('student').length;

document.getElementById('totalStudents').innerHTML =
response.getElementsByTagName('student').length;
document.getElementById('results-outer').style.display = "";

if (results == 1) {
getIndividualStudent(response.getElementsByTagName('student')
[0].getAttribute('id'));
}
else if (results > 0) {
string = '<ul>';

for (i=0; i<response.getElementsByTagName('student').length; i++) {
string += '<li>';
string += '<a href="javas'+'cript:getIndividualStudent(\''+
response.getElementsByTagName('student').getAttribute('id')
+'\')">';
string += response.getElementsByTagName('adno')
.firstChild.nodeValue;
string += ' - ';
string += response.getElementsByTagName('forenames')
.firstChild.nodeValue;
string += ' ';
string += response.getElementsByTagName('surname')
.firstChild.nodeValue;
string += '</a>';
string += '</li>';
}

string += '</ul>';

div.innerHTML = string;
}
}
}

function getIndividualStudent(id) {
updateStatus('show', 'Getting Student...', 'working')


// Hide old Div's
document.getElementById('search').style.display = "none";
document.getElementById('results-outer').style.display = "none";
document.getElementById('amendments').style.display = "";

// Get Student and Populate Form
http.open('post', 'individual.xml');
http.onreadystatechange = populateStudentAmendmentForm;
http.send('student_id='+id);

}

function populateStudentAmendmentForm() {
if(http.readyState == 4){
updateStatus('show', 'Populating Form...', 'working')

var response = http.responseXML.documentElement;

document.getElementById('a_id').value =
response.getElementsByTagName('student')[0].getAttribute('id');
document.getElementById('a_forenames').value =
response.getElementsByTagName('forenames')[0].firstChild.nodeValue;
document.getElementById('a_surname').value =
response.getElementsByTagName('surname')[0].firstChild.nodeValue;
document.getElementById('a_adno').value =
response.getElementsByTagName('adno')[0].firstChild.nodeValue;
document.getElementById('a_dob').value =
response.getElementsByTagName('dob')[0].firstChild.nodeValue;

document.getElementById('a_address').value =
response.getElementsByTagName('address')[0].firstChild.nodeValue;
document.getElementById('a_postcode').value =
response.getElementsByTagName('postcode')[0].firstChild.nodeValue;
document.getElementById('a_email').value =
response.getElementsByTagName('email')[0].firstChild.nodeValue;
document.getElementById('a_telephone').value =
response.getElementsByTagName('telephone')[0].firstChild.nodeValue;
document.getElementById('a_email').value =
response.getElementsByTagName('email')[0].firstChild.nodeValue;
document.getElementById('a_mobile').value =
response.getElementsByTagName('mobile')[0].firstChild.nodeValue;

http.open('post', 'enrolments.xml');
http.onreadystatechange = updateEnrolments;
http.send('student_id='+response.getElementsByTagName('student')
[0].getAttribute('id'));
}
}

function updateEnrolments() {
if(http.readyState == 4){
var response = http.responseXML.documentElement;
var div = document.getElementById('results');
var string = "";

var results = response.getElementsByTagName('enrolment').length;

if (results == 0) {
// Add Row with 'No Enrolments'
tbl = document.getElementById('enrolment');
var lastrow = tbl.rows.length;

var row = tbl.insertRow(lastrow);
var ne_cell = row.insertCell(0);

ne_cell.colSpan = 4;
var text = document.createTextNode('No Current Enrolments...');

ne_cell.appendChild(text);
}
else {
for (i=0; i<response.getElementsByTagName('enrolment').length; i++)
{
var id = response.getElementsByTagName('enrolment')
.getAttribute('id');
var code = response.getElementsByTagName('code')
.firstChild.nodeValue;
var title = response.getElementsByTagName('title')
.firstChild.nodeValue;
var status = response.getElementsByTagName('status')
.firstChild.nodeValue;

addEnrolmentTableRow(id, code, title, status);
}
}

updateStatus('hide');
}
}

function addEnrolmentTableRow(id, code, title, status) {
tbl = document.getElementById('enrolments');
var lastrow = tbl.rows.length;

var iteration = lastrow - 1;

var row = tbl.insertRow(lastrow);

// Add Hidden ID
id_input = document.createElement('input');
id_input.type = 'hidden';
id_input.name = 'enrolment[' + lastrow + '][id]';
id_input.value = id;

document.getElementById('amendments').appendChild(id_input);

// Numbered Cell
var numbered_cell = row.insertCell(0);
var textNode = document.createTextNode(iteration);
numbered_cell.appendChild(textNode);

// Add Code Cell with Input Box
var code_cell = row.insertCell(1);

var code_input = document.createElement('input');
code_input.type = 'text';
code_input.name = 'enrolment[' + lastrow + ']
Code:
';
code_input.size = 8;
if (code != null) {
code_input.value = code;
code_input.disabled = true;
}

code_cell.appendChild(code_input);

// Add Title Cell with Input Box
var title_cell = row.insertCell(2);

var title_input = document.createElement('input');
title_input.type = 'text';
title_input.name = 'enrolment[' + lastrow + '][title]';
title_input.size = 15;
if (title != null) {
title_input.value = title;
title_input.disabled = true;
}

title_cell.appendChild(title_input);


// Add Status Cell with Status Select
var status_cell = row.insertCell(3);

var status_select = document.createElement('select');

status_select.name = 'enrolment[' + lastrow + '][status]';
status_select.options[0] = new Option('Pre-Enrolled', '0');
status_select.options[1] = new Option('Current', '1');
status_select.options[2] = new Option('Completed', '2');
status_select.options[3] = new Option('Withdrawn', '3');
status_select.options[4] = new Option('Transferred', '4');
status_select.options[5] = new Option('Never Attended', 'W');

switch (status) {
case (status = "Current"):
status_select.selectedIndex = 1;
break;
case "Completed":
status_select.selectedIndex = 2;
break;
case "Withdrawn":
status_select.selectedIndex = 3;
break;
case "Transferred":
status_select.selectedIndex = 4;
break;
case "Never Attended":
status_select.selectedIndex = 5;
break;
default:
status_select.selectedIndex = 0;
break;
}

status_cell.appendChild(status_select);

// Add Date Cell with Input Box
var date_cell = row.insertCell(4);

var date_input = document.createElement('input');
date_input.type = 'text';
date_input.name = 'enrolment[' + lastrow + '][date]';
date_input.size = 6;

date_cell.appendChild(date_input);
}

function updateStatus(showhide, text, image) {
if (showhide == "show")
document.getElementById('status').style.display="";
else if (showhide = "hide")
document.getElementById('status').style.display="none";

status_image = document.getElementById('status-image');
status_text = document.getElementById('status-text');

if (text != null) status_text.innerHTML = text;
if (image != null) status_image.innerHTML = '<img src="'+ image
+'.gif" border="0" alt="Status Image" height="16" />';
}
//-->
</script>

</head>
<body>

<div id="status">
<span id="status-image"></span>
<span id="status-text"></span>
</div>

<h1>Student Amendment Form</h1>

<div id="search">
<h2>Search For Student</h2>
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<caption>Search for Student</caption>
</tr>
<tr>
<td class="field">Ad No:</td>
<td><input type="text" name="search_adno" id="search_adno"
size="6" /></td>
</tr>
<tr>
<td class="field">Surname:</td>
<td><input type="text" name="search_surname"
id="search_surname" /></td>
</tr>
<tr>
<td class="field">Forenames:</td>
<td><input type="text" name="search_forenames"
id="search_forenames" /></td>
</tr>
<tr>
<td class="field">Date of Birth:</td>
<td><input type="text" name="search_dob" id="search_dob" /></td>
</tr>
<tr>
<td colspan="2"><input type="button" value="Get Results"
onClick="javascript:searchStudents();" /></td>
</tr>
</table>
</div>

<div id="results-outer" style="display: none">
<h2>Results</h2>
<b>Total Students:</b> <span id="totalStudents">&nbsp;</span>
<div id="results">&nbsp;</div>
</div>

<form action="post.php" method="post" id="amendments" style="display:
none">
<input type="hidden" name="id" id="a_id" />
<h2>Amendments</h2>

<table border="0" cellspacing="2" cellpadding="1">
<tr>
<caption>Personal Details</caption>
</tr>
<tr>
<td class="field">Ad No:</td>
<td><input type="text" name="adno" id="a_adno" disabled /></td>
</tr>
<tr>
<td class="field">Surname:</td>
<td><input type="text" name="surname" id="a_surname" /></td>
</tr>
<tr>
<td class="field">Forenames:</td>
<td><input type="text" name="forenames" id="a_forenames" /></td>
</tr>
<tr>
<td class="field">Date of Birth:</td>
<td><input type="text" name="dob" id="a_dob" /></td>
</tr>
</table>

<table border="0" cellspacing="2" cellpadding="1">
<tr>
<caption>Contact Details</caption>
</tr>
<tr>
<td class="field">Address:</td>
<td><textarea name="address" id="a_address"></textarea></td>
</tr>
<tr>
<td class="field">Post Code:</td>
<td><input type="text" name="postcode" id="a_postcode" /></td>
</tr>
<tr>
<td class="field">E-Mail:</td>
<td><input type="text" name="email" id="a_email" /></td>
</tr>
<tr>
<td class="field">Telephone:</td>
<td><input type="text" name="telephone" id="a_telephone" /></td>
</tr>
<tr>
<td class="field">Mobile:</td>
<td><input type="text" name="mobile" id="a_mobile" /></td>
</tr>
</table>


<table border="0" cellspacing="0" cellpadding="0" id="enrolments">
<tr>
<caption>Enrolments</caption>
</tr>
<tr>
<th>&nbsp;</th>
<th>Code</td>
<th>Course Title</td>
<th>Status</td>
<th>Date</td>
</tr>
</table>
<div align="right"><a href="javascript:addEnrolmentTableRow();">Add
New Enrolment</a></div>

<input type="submit" name="Submit" value="Update" />

</form>

</body>
</html>

XML Formats:

Student.xml
<students>
<student id="93000001061744">
<adno>xxx</adno>
<forenames>xxx</forenames>
<surname>xxx</surname>
<title>Mr</title>
<gender>Male</gender>
</student>
<student id="93000001061745">
<adno>xxx</adno>
<forenames>New</forenames>
<surname>Person</surname>
<title>Mr</title>
<gender>Male</gender>
</student>
</students>

Enrolment.xml:
<enrolments>
<enrolment id="11938913" student="93000001061744">
<code>xxx</code>
<title>xxx</title>
<start>03-OCT-00</start>
<end>15-JUN-00</end>
<status>Completed</status>
</enrolment>
<enrolment id="12128794" student="93000001061744">
<code>xxx</code>
<title>HND Computing Full Time</title>
<start>03-OCT-00</start>
<end>15-JUN-00</end>
<status>Current</status>
</enrolment>
<enrolment id="12754637" student="93000001061744">
<code>xxx</code>
<title>xxx</title>
<start>03-OCT-00</start>
<end>15-JUN-00</end>
<status>Current</status>
</enrolment>
</enrolments>

This all works fine in Firefox, but when it comes to IE it returns a
'null' is null or not an object error on the line:
var results = response.getElementsByTagName('student').length;

Is there anything glarinly obvious that I'm missing or am I using bad
practices?  I'm finding it really hard to find anything on responseXML
anywhere!

Thanks in advance
 
I

Ian Collins

Hey All,

I'm relatively new to all this and any help would be appreciated.
What I'm aiming to do is create a few requests, to
1. Search for a Student against XML created from the database
2. If more than one student, list all students using DOM
3. Finally, return individual student and enrolments.
This all works fine in Firefox, but when it comes to IE it returns a
'null' is null or not an object error on the line:
var results = response.getElementsByTagName('student').length;

Is there anything glarinly obvious that I'm missing or am I using bad
practices? I'm finding it really hard to find anything on responseXML
anywhere!

Make sure your Content-Type HTTP response headers are correct
(text/xml), FF doesn't care too much and will accept XML even if this
isn't set. IE will treat XML as text if Content-Type isn't correct.

Also bear in mind that you can't add elements form the response XML into
the page DOM in IE.
 
A

adam

Make sure your Content-Type HTTP response headers are correct
(text/xml), FF doesn't care too much and will accept XML even if this
isn't set. IE will treat XML as text if Content-Type isn't correct.

Also bear in mind that you can't add elements form the response XML into
the page DOM in IE.

Funnily enough I've got the overrideMimeType('text/xml') commented out
because IE didn't like it when I first started. I can't get to the
XML file to set the content-type header so that could be a problem.
Would this be where the problem stems from?
 
D

Dylan Parry

function createRequestObject() {
var ro;
var browser = navigator.appName;
if(browser == "Microsoft Internet Explorer"){
ro = new ActiveXObject("Microsoft.XMLHTTP");
}
else {
ro = new XMLHttpRequest();
}
return ro;
}

This function really isn't the best way of doing it. Don't check to see
what browser it is, but check to see if the browser supports the objects
you are trying to create. It's possible that MSIE isn't even getting a
object to work with here.

Try something like this (from http://ajaxcookbook.org/xmlhttprequest/):

function createXMLHttpRequest() {
if (typeof XMLHttpRequest != "undefined") {
return new XMLHttpRequest();
} else if (typeof ActiveXObject != "undefined") {
return new ActiveXObject("Microsoft.XMLHTTP");
} else {
throw new Error("XMLHttpRequest not supported");
}
}

This doesn't rely on browser sniffing, which is what your code appears
to be doing.

--
Dylan Parry
http://electricfreedom.org | http://webpageworkshop.co.uk

The opinions stated above are not necessarily representative of
those of my cats. All opinions expressed are entirely your own.
 
I

Ian Collins

*Please* don't quote signatures.
Funnily enough I've got the overrideMimeType('text/xml') commented out
because IE didn't like it when I first started. I can't get to the
XML file to set the content-type header so that could be a problem.
Would this be where the problem stems from?
I'm sure IE requires the correct Content-Type header. Otherwise it
won't even attempt to parse the XML, it just returns text.
 
A

adam

*Please* don't quote signatures.


I'm sure IE requires the correct Content-Type header. Otherwise it
won't even attempt to parse the XML, it just returns text.

Thanks Dylan, you're right that is a much better way to do it.

So without setting the headers in the source file this isn't going to
work? But surely this can't be the problem, I'm testing using local
xml files - I've put in the <?xml version="1.0" encoding="UTF-8"?>
header at the start of the XML and still no dice.

I really can't find anything tutorial wise on the internet that does
what I need it to do.

If different to what I've got, how would you work out the number of
nodes in an XML file and return the relevent details?

Thanks in advance
 
D

Dylan Parry

So without setting the headers in the source file this isn't going to
work? But surely this can't be the problem, I'm testing using local
xml files - I've put in the <?xml version="1.0" encoding="UTF-8"?>
header at the start of the XML and still no dice.

When you're doing stuff with XMLHttpRequest() objects the XML and the
page using it *must* be on the same domain. Are you trying to test this
on a locally installed server (local host) or are you just loading the
files up in your browser from the local filesystem? The latter won't work...

--
Dylan Parry
http://electricfreedom.org | http://webpageworkshop.co.uk

The opinions stated above are not necessarily representative of
those of my cats. All opinions expressed are entirely your own.
 
I

Ian Collins

*I did ask you politely not to quote signatures, please don't.*
So without setting the headers in the source file this isn't going to
work? But surely this can't be the problem, I'm testing using local
xml files - I've put in the <?xml version="1.0" encoding="UTF-8"?>
header at the start of the XML and still no dice.
I didn't say the source file, I said the HTTP Content-Type response
header sent from the server.
 
A

adam

Dylan, I have the a copy of the generated XML file that will be
deployed from the server stored locally for development and testing,
the student.xml and enrolment.xml are generated by a file from the
server, but once I've finished the files I'm calling to will change
but will be relative to the html.

Ian, So to clarify - the server header sent from the XML file? I'm
self taught so I really don't know technical terms.

I have tried returning the content type
using .getResponseHeader("Content-Type") - but comes back
blank. .status also doesn't return 200, but 0 - is this also a
problem?

Would you also suggest JSON? XML is the preferred choice because I
could then use it to integrate with other systems but would you
recommend taking a different route?
 
I

Ian Collins

Ian, So to clarify - the server header sent from the XML file? I'm
self taught so I really don't know technical terms.
NO, the header is part of the HTTP response packet sent back to the
browser from the web server. You realy should be testing this with a
proper server, not local files. As Dylan made clear, the behaviour is
quite different.
Would you also suggest JSON? XML is the preferred choice because I
could then use it to integrate with other systems but would you
recommend taking a different route?

That depends of a number of factors, as you have found browser
differenced are a pain in the arse with XML (mainly because you can't do
much with the response on IE). JSON is much easier to work with in a
pure browser to server application.
 
L

-Lost

Dylan Parry said:
When you're doing stuff with XMLHttpRequest() objects the XML and the
page using it *must* be on the same domain. Are you trying to test this
on a locally installed server (local host) or are you just loading the
files up in your browser from the local filesystem? The latter won't work...

That is not entirely true. Only HTTP dependent items will be unavailable if tested
locally. For example:

onprogress - there is no downloading of any document, therefore no position or totalSize
will be available either.

status - there is no HTTP status if not viewed over HTTP. Status will always be 0 when
tested on a local file.

-Lost
 
L

-Lost

Dylan, I have the a copy of the generated XML file that will be
deployed from the server stored locally for development and testing,
the student.xml and enrolment.xml are generated by a file from the
server, but once I've finished the files I'm calling to will change
but will be relative to the html.

Ian, So to clarify - the server header sent from the XML file? I'm
self taught so I really don't know technical terms.

I have tried returning the content type
using .getResponseHeader("Content-Type") - but comes back
blank. .status also doesn't return 200, but 0 - is this also a
problem?

You cannot view headers if not viewed over HTTP, also, not without a minimum readyState of
3.

status returns 0 when retrieved locally.

-Lost
 
L

-Lost

-Lost said:
That is not entirely true. Only HTTP dependent items will be unavailable if tested
locally. For example:

onprogress - there is no downloading of any document, therefore no position or totalSize
will be available either.

status - there is no HTTP status if not viewed over HTTP. Status will always be 0 when
tested on a local file.

I forgot statusText which retrieves status as a string. It will not be available locally
either.

-Lost
 
A

adam

I forgot statusText which retrieves status as a string. It will not be available locally
either.


So that explains the status, I'll try and get it on the server to test
and hopefully this will sort it out. Thanks to all three of you.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,284
Latest member
NicholeDum

Latest Threads

Top