Steevo
Steevo

Reputation: 3

Loop through XML files jQuery

I am a bit stuck with the following problem.

I have several XML files tagged by an ID (every XML is id'd by a value). I am now trying to loop through these files and output its contents to HTML.

However it starts the loop before it does the call back

Loop0 Loop1 Loop2 Callback0 Callback1 Callback2

I would need Loop0 Callback0 Loop1 Callback1

As I need to control the results at some point.

        var allContent=["xmlfile1","xmlfile2","xmlfile3","xmlfile4"];
        var totalSearch = 0;
        var countSearch = 0;

        function doSearch() {

            var oldContentID = contentID;

            for (iSearch=0;iSearch<allContent.length;iSearch++) {
                totalSearch = totalSearch + countSearch;
                contentID = allContent[iSearch];
                defineContent();

                getXML();

            }
        } 

        function getXML() {
            $.ajax({
                type: "GET",
                url: langFile,
                dataType: "xml",
                beforeSend: function(){

                    $('#results-list').empty();
                    $('#results-list').hide();
                    $('#loading').addClass('loading');
                },
                success: function(xml) {

                    var totalElements;
                    var intSearch = 0;
                    totalSearch = totalSearch + countSearch;
                    countSearch = 0;
                    var searchText = $('#text').val().toLowerCase();

                    totalElements = $(xml).find('news').length;


                    while (intSearch < totalElements) {
                        oFeed = $(xml).find('news:eq('+intSearch+')');
                        var headline = oFeed.find('headline').text();
                        var newsText = oFeed.find('detail').text();
                        var section = oFeed.find('section').text();
                        var category = oFeed.attr('category');

                        var stripEnters = newsText.match(/\r?\n|\r/gi);
                        if (stripEnters != null) {
                            for (var s = 0; s < stripEnters.length ; s++ ){
                                newsText = newsText.replace(stripEnters[s],'');
                            }
                        }

                        var newsText2 = $.htmlClean(newsText, {format:true});
                        var newsText3 = $(newsText2)
                        var newsText4 = $(newsText3).text();
                        var newsText5 = newsText4.replace( /\W/gi, "" );

                        if (section.toLowerCase() == "news" || section.toLowerCase() == "featured") {
                            if (headline.toLowerCase().indexOf(searchText) >= 0) {
                                $('<dt></dt>').html(headline).appendTo('#results-list');
                                $('<dd></dd>').html(newsText).appendTo('#results-list');
                                countSearch++;
                            }//end if
                            else if (newsText5.toLowerCase().indexOf(searchText) >= 0) {
                                $('<dt></dt>').html(headline).appendTo('#results-list');
                                $('<dd></dd>').html(newsText).appendTo('#results-list');
                                countSearch++;
                            }
                        }
                        intSearch++;
                    }           

                }   
            }); 
        }

At the end of the call backs I need to run the following, however it now executes this function before it finishes all call backs.

        function displayResults() {
            if (totalSearch == 0)
            {
                alert("No results found");
                $('#loading').removeClass('loading');
                $('#main').fadeIn(1000);
            }
            else {
                dynamicFaq();
                $('<p></p>').html(totalSearch + ' Results found').prependTo('#results-list');
                $('#results-list').fadeIn(1000);
                $('#loading').removeClass('loading');
            }   
        }

Upvotes: 0

Views: 467

Answers (3)

Sudhanshu Yadav
Sudhanshu Yadav

Reputation: 2333

Maintain a ajax queue so thos ajax call will be done one by one. plus maintain a global variable searchedCount which will maintain how main xml are proccessed.

In complete callback of ajax check for the searchedCount and call displayResults function .

var allContent = ["xmlfile1", "xmlfile2", "xmlfile3", "xmlfile4"];
var totalSearch = 0;
var countSearch = 0;
var searchedCount = 0;

var ajaxQueue = $({});
$.ajaxQueue = function (ajaxOpts) {
    // Hold the original complete function.
    var oldComplete = ajaxOpts.complete;
    // Queue our ajax request.
    ajaxQueue.queue(function (next) {
        // Create a complete callback to fire the next event in the queue.
        ajaxOpts.complete = function () {
            // Fire the original complete if it was there.
            if (oldComplete) {
                oldComplete.apply(this, arguments);
            }
            // Run the next query in the queue.
            next();
        };
        // Run the query.
        $.ajax(ajaxOpts);
    });
};

function doSearch() {

    var oldContentID = contentID;
    searchedCount = 0;
    for (iSearch = 0; iSearch < allContent.length; iSearch++) {
        totalSearch = totalSearch + countSearch;
        contentID = allContent[iSearch];
        defineContent();
        searchedCount++;
        getXML();

    }
}

function getXML() {
    $.ajaxQueue({
        type: "GET",
        url: langFile,
        dataType: "xml",
        beforeSend: function () {

            $('#results-list').empty();
            $('#results-list').hide();
            $('#loading').addClass('loading');
        },
        success: function (xml) {

            //your code 

        },
        complete: function () {
            if (searchedCount == allContent.length) {
                displayResults()
            }
        }
    });
}

Upvotes: 0

Eich
Eich

Reputation: 3788

If I understood you correctly, you want to load 1 xml file, loop, and then start to load the next xml file. If so, here is a little pseudo code:

function doSearch(int xmlFileIterator){
    if (xmlFileIterator < allContent.length) {
        ...
        contentID = allContent[xmlFileIterator];
        ...
        getXml(xmlFileIterator);
    } else {
        //no more xml files left
        displayResults();
    }
}

function getXml(int xmlFileIterator) {
    ...
        success: function() {
            ...
            doSearch(++xmlFileIterator);
        }
}

The first call is doSearch(0) which loads the first xml file. After the file is loaded and the loop is done (in success) you can call the doSearch function again with a higher number (iterator).

Upvotes: 1

IndoKnight
IndoKnight

Reputation: 1864

I see your AJAX call is Asynchronous. Try using

            ....
            type: "GET",
            url: langFile,
            async: false,
            dataType: "xml",
            .....

Upvotes: 0

Related Questions