-1

I originally set out to do an XML parse (single node) using jQuery, but had no luck so I ended up using plain Javascript instead. The code is found in this thread: Parse XML using JS

Now I can see that the way I use XMLhttpRequest function is deprecated and might be removed in the future, which would ruin quite a lot on my homepage XMLhttpRequest and Google inspector also reports

Synchronous XMLHttpRequest outside of workers is in the process of being removed from the web platform as it has detrimental effects to the end user's experience

I would like to re-open the original question, and get help rewriting the below to load my XML without using the async=false in my code

xhttp.open("GET",filename,false);

The code is being invoked about 9/10 down in my HMTL-code, but simply changing "false" to "true" is no good, as nothing loads at all (I guess the code moves on before it has a chance to insert the XML-data?). With my weak abilities in JS I had to google to find some answers that points to: W3C on send/get

How would I change my code to avoid using the "false" statement?

The XML would look like:

<scoreresults>
<topscorePicture>100</topscorePicture>
<topscoreFeature>100</topscoreFeature>
<topscoreUI>100</topscoreUI>
<item>
<title>
<![CDATA[ Test sample 1 ]]>
</title>
<link>    Somelink    </link>
<guid isPermaLink="true">   Somelink      </guid>
<scorePicture>82</scorePicture>
<scoreFeature>90</scoreFeature>
<scoreUI>85</scoreUI>
<measurePowerOTB>180</measurePowerOTB>
<measurePowerCAL>160</measurePowerCAL>
<measurePowerSTANDBY>0.2</measurePowerSTANDBY>
<measureContrastOTB>2000</measureContrastOTB>
<measureContrastCAL>2200</measureContrastCAL>
<measureBrightnessOTB>210</measureBrightnessOTB>
<measureBrightnessCAL>130</measureBrightnessCAL>
</item>
</scoreresults>

The script reads:

function loadXMLDoc(filename)
{
if (window.XMLHttpRequest)
  {
  xhttp=new XMLHttpRequest();
  }
else // code for IE5 and IE6
  {
  xhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xhttp.open("GET",filename,false);
xhttp.send();
return xhttp.responseXML;
}



function showTVscore(testNo) {

    //Load the XML
    xmlDoc = loadXMLDoc("/testscores.xml");

    //Extract the highest score for picture
    tsp = xmlDoc.getElementsByTagName("topscorePicture")[0];
    topspvalue = tsp.childNodes[0];

    //Extract highest score for features
    tsf = xmlDoc.getElementsByTagName("topscoreFeature")[0];
    topsfvalue = tsf.childNodes[0];

    //Extract highest score for UI
    tsui = xmlDoc.getElementsByTagName("topscoreUI")[0];
    topsuivalue = tsui.childNodes[0];

    //Extract  picture score for the specific test no.
    sp = xmlDoc.getElementsByTagName("scorePicture")[testNo];
    spvalue = sp.childNodes[0];

    //Extract Feature score for the specific test no.
    sf = xmlDoc.getElementsByTagName("scoreFeature")[testNo];
    sfvalue = sf.childNodes[0];

    //Extract UI score for the specific test no.
    sui = xmlDoc.getElementsByTagName("scoreUI")[testNo];
    suivalue = sui.childNodes[0];

    //Calculate current scores
    scorePicture = Math.round(Number(spvalue.nodeValue) / Number(topspvalue.nodeValue) * 100);
    scoreFeature = Math.round(Number(sfvalue.nodeValue) / Number(topsfvalue.nodeValue) * 100);
    scoreUI = Math.round(Number(suivalue.nodeValue) / Number(topsuivalue.nodeValue) * 100);
    scoreTotal = Math.round(0.5 * scorePicture + 0.25 * scoreFeature + 0.25 * scoreUI);

    //Set color of Picture scorebar
    switch (Math.round(scorePicture / 10)) {
        case 1:
            pictureColor = "#934F00";
            break;
        case 2:
            pictureColor = "#C36900";
            break;
        case 3:
            pictureColor = "#F28200";
            break;
        case 4:
            pictureColor = "C38D00";
            break;
        case 5:
            pictureColor = "#F2AF00";
            break;
        case 6:
            pictureColor = "#07ABFB";
            break;
        case 7:
            pictureColor = "#008ED3";
            break;
        case 8:
            pictureColor = "#006699";
            break;
        case 9:
            pictureColor = "#00537B";
            break;
        case 10:
            pictureColor = "#003F5D";
            break;
    };
    //Set color of Feature scorebar
    switch (Math.round(scoreFeature / 10)) {
        case 1:
            featureColor = "#934F00";
            break;
        case 2:
            featureColor = "#C36900";
            break;
        case 3:
            featureColor = "#F28200";
            break;
        case 4:
            featureColor = "C38D00";
            break;
        case 5:
            featureColor = "#F2AF00";
            break;
        case 6:
            featureColor = "#07ABFB";
            break;
        case 7:
            featureColor = "#008ED3";
            break;
        case 8:
            featureColor = "#006699";
            break;
        case 9:
            featureColor = "#00537B";
            break;
        case 10:
            featureColor = "#003F5D";
            break;
    };
    //Set color of UI scorebar
    switch (Math.round(scoreUI / 10)) {
        case 1:
            uiColor = "#934F00";
            break;
        case 2:
            uiColor = "#C36900";
            break;
        case 3:
            uiColor = "#F28200";
            break;
        case 4:
            uiColor = "C38D00";
            break;
        case 5:
            uiColor = "#F2AF00";
            break;
        case 6:
            uiColor = "#07ABFB";
            break;
        case 7:
            uiColor = "#008ED3";
            break;
        case 8:
            uiColor = "#006699";
            break;
        case 9:
            uiColor = "#00537B";
            break;
        case 10:
            uiColor = "#003F5D";
            break;
    };
    //Set color of total scorebar
    switch (Math.round(scoreTotal / 10)) {
        case 1:
            totalColor = "#934F00";
            break;
        case 2:
            totalColor = "#C36900";
            break;
        case 3:
            totalColor = "#F28200";
            break;
        case 4:
            totalColor = "C38D00";
            break;
        case 5:
            totalColor = "#F2AF00";
            break;
        case 6:
            totalColor = "#07ABFB";
            break;
        case 7:
            totalColor = "#008ED3";
            break;
        case 8:
            totalColor = "#006699";
            break;
        case 9:
            totalColor = "#00537B";
            break;
        case 10:
            totalColor = "#003F5D";
            break;
    };

    //Construct HTML
    HTMLchunkStart = "<div style=\"float: Right; text-align: right; width: 40px; font-weight: 500; padding-left: 20px; color: #666;\"><i class=\"fa fa-picture-o\"></i></div><div class=\"progress\" style=\"background-color:#E2E2E2\">";
    pictureBar = "<div class=\"progress-bar\" role=\"progressbar\" aria-valuenow=\"" + Number(spvalue.nodeValue) + "\" aria-valuemin=\"0\" aria-valuemax=\"" + Number(topspvalue.nodeValue) + "\" style=\"width:" + scorePicture + "%; background-color:" + pictureColor + ";\">" + scorePicture + "%</div>";
    HTMLchunk1 = "</div> <div style=\"float: Right; text-align: right; width: 40px; font-weight: 500; padding-left: 20px; color: #666;\"><i class=\"fa fa-cogs\"></i></div><div class=\"progress\" style=\"background-color:#E2E2E2\">";
    featureBar = "<div class=\"progress-bar\" role=\"progressbar\" aria-valuenow=\"" + Number(sfvalue.nodeValue) + "\" aria-valuemin=\"0\" aria-valuemax=\"" + Number(topsfvalue.nodeValue) + "\" style=\"width:" + scoreFeature + "%; background-color:" + featureColor + "\">" + scoreFeature + "%</div>";
    HTMLchunk2 = " </div><div style=\"float: Right; text-align: right; width: 40px; font-weight: 500; padding-left: 20px; color: #666;\"><i class=\"fa fa-user\"></i></div><div class=\"progress\" style=\"background-color:#E2E2E2\">";
    UIbar = "<div class=\"progress-bar\" role=\"progressbar\" aria-valuenow=\"" + Number(suivalue.nodeValue) + "\" aria-valuemin=\"0\" aria-valuemax=\"" + Number(topsuivalue.nodeValue) + "\" style=\"width:" + scoreUI + "%; background-color:" + uiColor + ";\">" + scoreUI + "%</div>";
    HTMLchunk3 = "</div> <div style=\"padding-top: 3px;float: Right; text-align: right; width: 40px; font-weight: 500; padding-left: 20px; color: #666;\"><i class=\"fa fa-star\"></i></div><div class=\"progress progress-lg\" style=\"background-color:#E2E2E2;height: 30px;\">";
    totalBar = "<div class=\"progress-bar progress-bar-info\" role=\"progressbar\" aria-valuenow=\"" + scoreTotal + "\" aria-valuemin=\"0\" aria-valuemax=\"100\" style=\"width:" + scoreTotal + "%; background-color:" + totalColor + ";font-size:1.1em;font-weight:600;\">Total: " + scoreTotal + "%</div></div>";

    //Write the HTML
    document.write(HTMLchunkStart + pictureBar + HTMLchunk1 + featureBar + HTMLchunk2 + UIbar + HTMLchunk3 + totalBar);
}
Community
  • 1
  • 1
  • Parsing XML and retrieving data through AJAX are different tasks. Which one do you have difficulties with? – Álvaro González May 15 '15 at 07:44
  • The above code works, but the function I use is being phased out. I was hoping to translate the above to jQuery instead e.g. by using $.get("testscores.xml", function(data) {... some code...} but I already tried getting there (see link in thread above) with no luck. I couldn't get jQuery to load the three global scores and neither simply exracting only one XML-item corresponding the whatever "testNo" is set to. – Torben Rasmussen May 15 '15 at 07:53
  • Simply put I would like to avoid being struck by browser phasing out XMLHttpRequest however possible. I just thought of jQuery as the obvious choice. – Torben Rasmussen May 15 '15 at 08:02
  • I've removed my answer since I failed to understand the question. I suggest you update the question and add an explanation of how exactly your code fails to work. – Álvaro González May 15 '15 at 11:21
  • Question updated as I realised the same. The code works, but I get a warning in the console of my browsers because of the "false" statement used to open my XML. – Torben Rasmussen May 15 '15 at 11:24
  • *«simply changing "false" to "true" is no good»*? Why isn't it good? Async requests make everything faster, trust me! If you decided to skip jQuery because you apparently found it too difficult to use, you shouldn't resort to plain JavaScript and tweak this kind of stuff. Whatetver, I'm afraid I can't do anything else without actual error messages (vague descriptions of error messages are not as good as actual error messsages) or a clear problem description. Sorry! – Álvaro González May 15 '15 at 12:49
  • There is no error. Just a warning that using "false" is deprecated. Switching to true just doesn't load anything, which I guess is because the HTML-code moves on and doesn't wait to have the above added through document.write(...) – Torben Rasmussen May 15 '15 at 13:19
  • @ÁlvaroG.Vicario — It isn't good because **simply** changing "false" to "true" causes the code that tries to read the response to run before the response has arrived. – Quentin May 15 '15 at 14:33

2 Answers2

0

Instead of returning a value from loadXMLDoc, pass it a callback function.

Add a readystatechange event handler and, when you have successfully loaded the data, call that function and pass it an argument.

function loadXMLDoc(filename, callback) {
  var xhr = new XMLHttpRequest();
  xhr.open("GET", filename);
  xhr.onreadystatechange = function () {
    if (this.readyState === 4 && this.status === 200) {
       callback(this.responseXML);  
    }
  };
  xhr.send();
}
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • Thank you for your reply. I might not have pointed out clearly enough how much I suck at this, but how would that play out in the above, if I remove my current load-function and replace it with yours? Something else would need to be changed as well I imagine? What does the "responseXML" refer to? – Torben Rasmussen May 15 '15 at 15:09
  • Yes. You'd need to move the code that depends on the data into the callback function. responseXML refers to exactly the same thing it does in your existing code. – Quentin May 15 '15 at 15:13
  • I apologize for being tad slow, but I have the showTVscore(var) that depends on the load, which writes the missing HTML code by document.write(...). So I move all of this code into the callback(...) brackets and instead of invoking the code by calling showTVscore(var) I would call the load function (and add the var I need to load the right node in the XML)? – Torben Rasmussen May 15 '15 at 15:18
0

OK, I figured out how to get things working with jQuery instead, so I will be using that method as all my other scripts use jQuery also.

Here is what I ended up with:

<script>
function showTVscore(x){
    // load the xml data. it is parsed by jquery
    $.get("testscores.xml", function(data) {
        var $xml = $(data);
        var y = $xml.find("item").length;
        topScorePic = parseInt($xml.find("topscorePicture").text());
        topScoreFeature = parseInt($xml.find("topscoreFeature").text());
        topScoreUI = parseInt($xml.find("topscoreUI").text());

        $xml.find("item").each(function(i, val) { // find the items in the xml and loop     
            // create an item object with all the necessary information out of the xml
            var $this = $(this),
                item = {
                    title: $this.find("title").text(),
                    link: $this.find("link").text(),
                    TopAward: $this.find("TopAward").text(),
                    RefAward: $this.find("RefAward").text(),
                    scorePic: parseInt($this.find("scorePicture").text(),10),
                    scoreFeature: parseInt($this.find("scoreFeature").text(),10),
                    scoreUI: parseInt($this.find("scoreUI").text(),10),
                    pricerunner: $this.find("pricerunnerLINK").text(),
                    year: $this.find("year").text(),
                };
            //Calculate scores relative to max values   
            scorePic = Math.round(item.scorePic / topScorePic*100);
            scoreFeature = Math.round(item.scoreFeature / topScoreFeature *100);
            scoreUI = Math.round(item.scoreUI / topScoreUI *100);           

            //Calculate total score
            totalScore = Math.round(0.5*item.scorePic + 0.25*(item.scoreFeature + item.scoreUI));

            // div with id "score" has the appropriate XML node added
            if(item.title == x){    
                $('#score').append($(
                    //HTML code that loads everything goes here...
                 ));
            }
            return i<(y-1); // (stop after y iterations)
        });
    });
};
</script>

And the code is then used on my page as

<div class="col-xs-12 col-sm-6">
    <div id="score">
    </div>
</div>
<script>showTVscore('title of node I want to load)');</script>