Search code examples
javascriptxmlxmlhttprequest

attempting to create a button which runs a script however the H1 and button disappear onClick


I hope you can read my code, I have an XML file on my localhost and I would like it to pull the title and year from that file (it currently has Title, Year, Artist, Price, and Country) while maintaining the H1 and button on the page.

The H1 text and button disappear onClick and I would like it to remain on the same page as the results.

  <h1>Show the Album list</h1>  
   <script>  
   xmlhttp=new XMLHttpRequest();  

   xmlhttp.open("GET","cd_catalog.xml",false);  
   xmlhttp.send();  
   xmlDoc=xmlhttp.responseXML;  
   function CdCatalog()  
    {
       document.write("<table border='1'><th>TITLE</th><th>YEAR</th>");
       var x=xmlDoc.getElementsByTagName("CD");  
       for (i=0;i<x.length;i++)
    {
   document.write("<tr><td>");
   document.write(x[i].getElementsByTagName("TITLE")[0].childNodes[0].nodeValue);
   document.write("</td><td>");
   document.write(x[i].getElementsByTagName("YEAR")[0].childNodes[0].nodeValue);
   document.write("</td></tr>");
    }
       document.write("</table>");
    }
   </script>


Solution

  • The problem is that you're using document.write for a button's click event, which is after the document's been closed...which means it overwrites everything. Since your page is simple and only has an <h1> and button, it looks like only those things are being hidden, but it would be everything on the page (if you had more).

    The solution is to use .appendChild and/or .innerHTML to add the content dynamically. I'll provide a solution in a minute :)

    UPDATE:

    Since you're using tables, you might as well use the native methods .insertRow and .insertCell that make table creation much easier. Here's an example of what you could use overall:

    function CdCatalog(xmlDoc) {
        var table = document.createElement("table");
        var thead = table.createTHead();    // Where "header" rows go
        // `insertRow` creates a <tr> element and appends it to `thead` automatically, returning the element
        var tr = thead.insertRow(-1);
        var td = document.createElement("th");  // No special method for creating "th" elements
        td.innerHTML = "TITLE";  // Set its inner content
        tr.appendChild(th);  // Add it to the row (which is in the header)
        td = document.createElement("td");
        td.innerHTML = "YEAR";
        tr.appendChild(td);
    
        var x = xmlDoc.getElementsByTagName("CD");
        // "tbody" is where a table's content goes, whether you do this explicitly or not
        var tbody = table.tBodies[0];
        for (var i = 0; i < x.length; i++) {
            tr = tbody.insertRow(-1);
            // `insertCell` creates a <td> element and appends it to `tr` automatically, returning the element
            td = tr.insertCell(-1);
            td.innerHTML = x[i].getElementsByTagName("TITLE")[0].childNodes[0].nodeValue;
            td = tr.insertCell(-1);
            td.innerHTML = x[i].getElementsByTagName("YEAR")[0].childNodes[0].nodeValue;
        }
        // Actually add the table to the DOM (the <body> element in this case)...you can specify where else to put it
        document.body.appendChild(table);
    }
    
    // Make sure DOM is ready for manipulation
    window.onload = function () {
        var btn = document.getElementById("button_id");  // Whatever your button is
        // Bind the "click" event for the button
        btn.onclick = function () {
            // Make your AJAX request
            var xmlhttp = new XMLHttpRequest();
            xmlhttp.open("GET", "cd_catalog.xml", false);
            xmlhttp.send();
            xmlDoc = xmlhttp.responseXML;
            // Pass the result to the function, instead of making everything global and sharing
            CdCatalog(xmlDoc);
        };
    };
    

    And unless I'm mistaken, you can't nest <td> inside of <table>...you must nest them in <tr>...which are nested in <table>