-1

I am working on an asp.net web application, and inside it i am trying to do the following :-

  1. call 2 rest API
  2. show an ajax loading image
  3. build a list of the result
  4. hide the loading image

here is my code:-

<script type="text/javascript">
var htmlinit = "";
htmlinit = "<image  id= 'customloader' src= '/resources/ajax-loader.gif'></image>";
$(".ms-core-listMenu-root>li:contains('Projects')").before(htmlinit);
$(function () { 
function getAssetsListItems(){

    var results="";
    var url = "/_api/web/lists/getbytitle('Projects')/items?$filter=SiteAutomaticallyCreated eq 'Yes'&$select=ID,Title,ProgrammeRevissionId&$orderby= Title asc";
    $.ajax({
     url: url,
     method: "GET",
     async: false,
     headers: { "Accept": "application/json; odata=verbose" },
     success: function (data) {
        if(data.d.results.length>0){
            results = data.d.results;

        }
     },
     error: function (data) {       
     }
    });
    return results;
}

    var assets=getAssetsListItems();    
    var url = "/_api/web/lists/getbytitle('Programme or Version Release')/items?$select=ID,Title&$orderby= Title asc";
    var html="";
    $.ajax({
     url: url,
     method: "GET",   
     headers: { "Accept": "application/json; odata=verbose" },
     success: function (data) {
        if(data.d.results.length>0){

            var items=data.d.results;
            for(var i=0;i<items.length;i++){
                html+="<li class='static'>"
                +"<span tabindex='0' class='static menu-item ms-core-listMenu-item ms-displayInline ms-navedit-linkNode'>"
                +"<span class='additional-background ms-navedit-flyoutArrow'><span class='menu-item-text' style='color:#00AEEF;font-weight:bold'>"
                +items[i].Title+"</span></span></span>";
                html+="<ul class='static'>";

                for(var j=0;j<assets.length;j++){

                    if(assets[j].ProgrammeRevissionId==items[i].ID){
                    var idd = assets[j].ID.toString();
                    var ntitle = assets[j].Title;
                        html+="<li class='static'>"
                            +"<a tabindex='0' class='static menu-item ms-core-listMenu-item ms-displayInline ms-navedit-linkNode'" 
                            +"href=/businessfunctions/PMO/Projects/"+idd+">";
                    }
                }               
                html+="</ul></li>";
            }
            $(".ms-core-listMenu-root>li:contains('Projects')").after(html);
            $("#customloader").hide();
        }
     },
     error: function (data) {       
     }
    });
});

</script>

the problem i am facing is that the loading image will not be hidden. so this line of code:-

$("#customloader").hide();

is not working as expected, although i will get my HTML result created correctly. so currently the loading image will be shown, then the result will be rendered, but the loading image will stay loading on the screen...

Thanks

John John
  • 1
  • 72
  • 238
  • 501
  • 1
    You've two `success` callbacks it may should be called in the both of them. – Zakaria Acharki Dec 14 '16 at 17:48
  • Is there an error preventing that line from being reached? Is that line executed at all? When it is, what does `$("#customloader")` return? – David Dec 14 '16 at 17:49
  • @ZakariaAcharki but i want it to get hidden only on the second success,, any way i tried adding it on the first success also ,, but it did not work – John John Dec 14 '16 at 17:51
  • @David no errors at all – John John Dec 14 '16 at 17:52
  • @David to be sure that there is not any error , i added the $("#customloader").hide(); inside the 2 error functions.. but still the loading image will stay loading – John John Dec 14 '16 at 17:53
  • @johnG: How would that ensure there is no error in the code? Don't just randomly add lines of code and assume there is no error, debug the code and see if there is or is not an error. – David Dec 14 '16 at 17:54
  • @David i debug the code and there is not any error , also the results i am getting is correct – John John Dec 14 '16 at 17:56
  • @johnG: When you debug, what happens when you encounter the line `$("#customloader").hide();`? Does the selector find any elements? – David Dec 14 '16 at 17:57
  • @David now i add alert(123) instead of $("#customloader").hide(); ,, and the alert was shown correctly – John John Dec 14 '16 at 18:49
  • 1
    @johnG: This is sounding more and more like a good opportunity to familiarize yourself with debugging tools. If you use your browser's debugger, you can place a "breakpoint" in the code and pause its actual execution on that line. From there you can step through the code, line by line, as it executes. Pausing on any given line, you can observe the runtime values and execute arbitrary lines of code on the console. A key piece of information to examine here is what's returned by `$("#customloader")` when that line executes. The element may not exist at that time, or they may be multiple, etc. – David Dec 14 '16 at 18:56
  • Possible duplicate of [How do I return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Heretic Monkey Dec 14 '16 at 19:00
  • @MikeMcCaughan it is not a duplicate !!! we are talking about 2 different issues – John John Dec 15 '16 at 00:35
  • @David did not use any such technique before for debugging JavaScript. now i am using IE11 and i open the F12 developer tools. then under the Debugger tab i have a set of scripts.. but not sure if there is a way to copy/paste my above script code and breakpoint and then execute it to check for breakpoints... seems inside the debugger area i am unable to write or copy/paste my script code!! can you advice ? – John John Dec 15 '16 at 00:43
  • @johnG Calm down. Duplicates are not bad. The fact is, you're returning `results` from `getAssestsListItems` outside of the callback. `async: false` is a bad idea for many, many reasons. – Heretic Monkey Dec 16 '16 at 14:56

1 Answers1

0

I find a few things that you should change to make your code a little bit more readable at least.

First is put all your code inside the $(function () { });

Then change this part

var htmlinit = "";
htmlinit = "<image  id= 'customloader' src= '/resources/ajax-loader.gif'></image>";
$(".ms-core-listMenu-root>li:contains('Projects')").before(htmlinit);

to

var htmlinit = $("<image id='customloader' src='/resources/ajax-loader.gif'></image>");
$(".ms-core-listMenu-root>li:contains('Projects')").before(htmlinit);

After doing this, my suggestion is put the second ajax call inside a function, getTitles for example.

Now with the code in place, you can fix other two points.

I'm not sure, but I think the getAssetsListItems never returns the information, this is a common mistake when a AJAX call is made.

The AJAX is a asynchronous call, so the return at the end of getAssetsListItems function will occur before the AJAX call finishes.

To fix this you should put the getTitle function inside the success of the AJAX call.

The second thing is change the line $("#customloader").hide(); to htmlinit.hide();

I think this will help you to reach your objective.

This is the full code after all changes.

<script type="text/javascript">
$(function () { 
    var htmlinit = $("<image id='customloader' src='/resources/ajax-loader.gif'></image>");
    $(".ms-core-listMenu-root>li:contains('Projects')").before(htmlinit);

    getAssetsListItems();

    function getAssetsListItems(){
        var url = "/_api/web/lists/getbytitle('Projects')/items?$filter=SiteAutomaticallyCreated eq 'Yes'&$select=ID,Title,ProgrammeRevissionId&$orderby= Title asc";
        $.ajax({
            url: url,
            method: "GET",
            async: false,
            headers: { "Accept": "application/json; odata=verbose" },
            success: function (data) {
                if(data.d.results.length > 0){
                    getTitles(data.d.results);
                }
            },
            error: function (data) {       
            }
        });
    }

    function getTitles(assets){
        var url = "/_api/web/lists/getbytitle('Programme or Version Release')/items?$select=ID,Title&$orderby=Title asc";

        $.ajax({
            url: url,
            method: "GET",   
            headers: { "Accept": "application/json; odata=verbose" },
            success: function (data) {
                if(data.d.results.length>0){

                    var html="";
                    var items=data.d.results;

                    for(var i=0;i<items.length;i++){
                        html+="<li class='static'>"
                            +"<span tabindex='0' class='static menu-item ms-core-listMenu-item ms-displayInline ms-navedit-linkNode'>"
                            +"<span class='additional-background ms-navedit-flyoutArrow'><span class='menu-item-text' style='color:#00AEEF;font-weight:bold'>"
                            +items[i].Title+"</span></span></span>";

                        html+="<ul class='static'>";

                        for(var j=0;j<assets.length;j++){

                            if(assets[j].ProgrammeRevissionId==items[i].ID){
                                var idd = assets[j].ID.toString();
                                var ntitle = assets[j].Title;
                                html+="<li class='static'>"
                                    +"<a tabindex='0' class='static menu-item ms-core-listMenu-item ms-displayInline ms-navedit-linkNode'" 
                                    +"href=/businessfunctions/PMO/Projects/"+idd+">";
                            }
                        }

                        html+="</ul></li>";
                    }

                    $(".ms-core-listMenu-root>li:contains('Projects')").after(html);
                    htmlinit.hide();
                }
            },
            error: function (data) {       
            }
        });
    }
});

</script>

Best regards

roicp
  • 148
  • 7
  • I am not sure why you assume my code will not work. now the getAssetsListItems() function will return the results correctly, since i am getting the expected results .. also inside the getAssetsListItems() i define the following "async: false," this mean that the flow of the code will be correct .. – John John Dec 14 '16 at 18:45
  • @jonhG I'm sorry about that. I didn't notice the "async: false" – roicp Dec 14 '16 at 18:49
  • i also made my two ajax calls async: false, but this did not change anything ... btw how you assume htmlinit.hide(); should work ? you are hiding a variable not an html ? in all ways i tried htmlinit.hide(); but did not work also ? – John John Dec 14 '16 at 18:52
  • @jonhG This time is different because the first code change I susgested (`var htmlinit = $("");`), now "htmlinit" is a jQuery object. – roicp Dec 14 '16 at 19:02