jQuery/JSON processing order

jQuery/JSON processing order

I hope I've got enough code here. From what I can tell with my console logs, I am executing my javascript in the order I want. The problem arises that at console log 3, there is no data to process. I hope this is clear, as I am at my wits end trying to figure this out.

My html page calls retrieveData, passing in a path for the selected page. From there, I parse the data and most of the time it works, but sometimes No data gets appended to my page.

I need someone to show me how to structure my code so I can get step three to work all the time.

Order of operations (corresponds to console logs in code):

1. Retrieve data

2. Process Data

3. Process Each Data Item (10% of the time, it fails here and no data shows on my page. Whether this works or not, everything else seems to be fine, and in the order I want.)

4. Finish page load and setup

5 & 6. I don't think these are relevant to the problem, but included just in case.

  1. function retrieveData(path) {
        console.log("1. retrieve data");
  2.     $.getJSON(path, null, processData)
        .done(function (data) {
            if (!data) {
                return
            }
        })
        .fail(function (e) {
            alert("An error has occurred.");
        });
    }


  1. function processData(data) {
        console.log("2. process data");
  2.     $.when(processEachItem(data)).done(function (finishPageLoad) {
            console.log("4. Finished processing each data item...do page setup and load");
            $(document).on("click").unbind();
  3.         $(document).on("click", ".openLevelThree", function (e) {
                page = $(this).children('a').attr('href');
  4.             var level_three_page_name = page.substring(0, page.indexOf(".htm"));
  5.             level_three_breadcrumb_name = level_three_page_name + " " + e.currentTarget.innerText;
  6.             level_three_breadcrumb = "views/breadcrumbs/breadcrumb_link.html";
  7.             var href = window.location + "";
  8.             // Add the hash we want that will take us to the level three page.
                window.location.href += "/" + level_three_page_name;
  9.             e.preventDefault();
            });
  10.         $("#headerLevelTwoBreadcrumbLink").load("views/breadcrumbs/breadcrumb.html");
            $("#headerLevelThreeBreadcrumb").empty();
            $("#subheader").load("views/subheaders/subheader.html");
        });
    }


  1. function processEachItem(data) {
        console.log("3. process each item");
        var count = 0;
  2.     $.each(data.InternalInputs, function (i, val) {
            applyLinks("internalInput", count++, val);
        })
  3.     $.each(data.ExternalInputs, function (i, val) {
            applyLinks("externalInput", count++, val);
        });
  4.     $.each(data.Activities, function (i, val) {
            applyLinks("activity", count++, val);
        });
  5.     $.each(data.Reviews, function (i, val) {
            applyLinks("review", count++, val);
        });
  6.     $.each(data.InternalOutputs, function (i, val) {
            applyLinks("internalOutput", count++, val);
        });
  7.     $.each(data.ExternalOutputs, function (i, val) {
            applyLinks("externalOutput", count++, val);
        });
  8.     assignPopups('a');
    }
  9. var formatMappings = {
        Begin: function (count, url, popupText, filters, tailoring, linkName, beginendlink) {
            return '<div class="openLevelThree" data-filters="' + filters + '" data-tailoring="' + tailoring + '"><a id="a' + count + '" href="' + url + '" title="' + popupText + '">' + linkName + ' <i class="fa fa-play"></i></a></div>';
        },
        End: function (count, url, popupText, filters, tailoring, linkName) {
            return '<div class="openLevelThree" data-filters="' + filters + '" data-tailoring="' + tailoring + '"><a id="a' + count + '" href="' + url + '" title="' + popupText + '">' + linkName + ' <i class="fa fa-check-circle"></i></a></div>';
        },
        None: function (count, url, popupText, filters, tailoring, linkName) {
            return '<div class="openLevelThree" data-filters="' + filters + '" data-tailoring="' + tailoring + '"><a href="' + url + '" title="' + popupText + '">' + linkName + '</a></div>';
        },
    };


  1. function applyLinks(target, count, val) {
        var taskColumn = val.TaskColumn === undefined ? '' : val.TaskColumn;
        var id = '#' + target + val.Task + taskColumn;
  2.     $(id)
            .addClass('links')
            .append(formatMappings[val.SpanType](count, val.Url, val.PopupText, val.Filters, val.Tailoring, val.LinkName));
    };


Not sure if this code is needed for my problem. It is called from loading a page after console log item 5.

  1. var firstFilter;
  2. function populateFilters(path) {
        console.log("6. populate filters");
        $.getJSON(path)
        .done(function (data) {
            if (!data) {
                return
            }
  3.         $('#filterComboBox').empty();
  4.         $(data).each(function (i, item) {
                var selected = '';
  5.             if (i === 0) {
                    selected = ' selected="selected"';
                    $('.filterSelectWrap').append('<span class="selectInner filterSelected">' + item.Name + '</span>');
                    firstFilter = item.Value;
                }
  6.             $('#filterComboBox').append('<option value="' + item.Value + '"' + selected + '>' + item.Name + '</option>');
            });
        })
        .always(function () {
            filterPage(firstFilter);
        });
    }


  1. var firstTailoring;
  2. function populateTailoring(path) {
        console.log("7. populate tailoring");
        $.getJSON(path)
        .done(function (data) {
            if (!data) {
                return
            }
  3.         $('#tailoringComboBox').empty();
  4.         $(data).each(function (i, item) {
                var selected = '';
                if (i === 0) {
                    selected = ' selected="selected"';
                    $('.tailoringSelectWrap').append('<span class="selectInner tailoringSelected">' + item.Name + '</span>');
                    firstTailoring = item.Value;
                }
  5.             $('#tailoringComboBox').append('<option value="' + item.Value + '"' + selected + '>' + item.Name + '</option>');
            });
        })
        .always(function () {
            tailorPage(firstTailoring);
        });
    }


  1. function filterPage(filter) {
        $('div.openLevelThree').each(function (i, el) {
            var $this = $(el);
            var filters = $this.attr('data-filters');
  2.         if (filters.indexOf(filter) > -1) {
                $this.show();
            } else {
                $this.hide();
            }
        });
    }


  1. function tailorPage(tailoring) {
        $('div.openLevelThree').each(function (i, el) {
            var $this = $(el);
            var tailors = $this.attr('data-tailoring');
  2.         if (tailors.indexOf(tailoring) > -1) {
                $this.find('a').css("color", "#000000");
                $this.find('.fa-play').css("color", "green");
                $this.find('.fa-check-circle').css("color", "red");
            } else {
                $this.find('a').css("color", "#bfbfbf");
                $this.find('.fa-play').css("color", "#bfbfbf");
                $this.find('.fa-check-circle').css("color", "#bfbfbf");
            }
        });
    }


  1. var timerPopup;
  2. function assignPopups(selector) {
        $(selector).hover(
            function (b) {
                if ($(this).attr('title')) {
                    $(this).data('title', $(this).attr('title'));
                    $(this).removeAttr('title');
                }
  3.             if ($(this).data('title')) {
  4.                 var bkgColor = $(this).closest("td").css("background-color");
  5.                 rgb2hex(bkgColor);
  6.                 if (bkgColor === null || bkgColor === undefined) {
                        bkgColor = "#4aacc5";
                    }
  7.                 var html = '<div id="titlePopup" class="tooltip info" style="display: block; top: '
                        + (b.pageY + 10)
                        + 'px; left: '
                        + (b.pageX + 20)
                        + 'px;">'
                        + '<span id="temp" style="background-color:"' + bkgColor + ';>' + $(this).data('title') + '</span>'
                        + '</div>';
  8.                 timerPopup = setTimeout(function () {
                        $('div#titlePopup').remove();
                        $('body').append(html);
                    }, 800);
                }
            },
            function () {
                clearTimeout(timerPopup);
                $('div#titlePopup').remove();
            });
    }