AJAX/DOM - Works in FF but not IE?

Discussion in 'Javascript' started by adam, Apr 2, 2007.

  1. adam

    adam Guest

    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 (Text):
    ';
    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
     
    adam, Apr 2, 2007
    #1
    1. Advertisements

  2. adam

    Ian Collins Guest

    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.
     
    Ian Collins, Apr 2, 2007
    #2
    1. Advertisements

  3. adam

    adam Guest

    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?
     
    adam, Apr 2, 2007
    #3
  4. adam

    Dylan Parry Guest

    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.
     
    Dylan Parry, Apr 2, 2007
    #4
  5. adam

    Ian Collins Guest

    *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.
     
    Ian Collins, Apr 2, 2007
    #5
  6. adam

    adam Guest

    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
     
    adam, Apr 3, 2007
    #6
  7. adam

    Dylan Parry Guest

    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.
     
    Dylan Parry, Apr 3, 2007
    #7
  8. adam

    Ian Collins Guest

    *I did ask you politely not to quote signatures, please don't.*
    I didn't say the source file, I said the HTTP Content-Type response
    header sent from the server.
     
    Ian Collins, Apr 3, 2007
    #8
  9. adam

    adam Guest

    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?
     
    adam, Apr 3, 2007
    #9
  10. adam

    Ian Collins Guest

    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.
    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.
     
    Ian Collins, Apr 3, 2007
    #10
  11. adam

    -Lost Guest

    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
     
    -Lost, Apr 3, 2007
    #11
  12. adam

    -Lost Guest

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

    status returns 0 when retrieved locally.

    -Lost
     
    -Lost, Apr 3, 2007
    #12
  13. adam

    -Lost Guest

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

    -Lost
     
    -Lost, Apr 3, 2007
    #13
  14. adam

    adam Guest


    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.
     
    adam, Apr 4, 2007
    #14
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.