title: Jquery DOM not updating after .each() iteration
body: <p>I am trying to keep track of updates as the each iterates and when the each is finished I would like to show a summary to the user in a graceful way. I have tried almost everything to a method call to update an element on the page but unless I fire off an alert at any point in the event call it will not update.</p>
  
  <p>If anyone knows what I may be missing I would like to see how it is done. Big THANKS in advance!</p>
  
  
  
  <pre class="lang-js prettyprint-override"><code>$('#button-restore-projects').live("click", function() {
                      var countSuccess = 0
                      , countError = 0
                      , element = $("#selectedProjects option")
                      , eachCount = element.length;
                      $("#countReady").html(eachCount);
  
                      $.each(element, function(i, o) {
                          var id = $(this).val();
                          //alert(i);
                          $.ajax({
                              type: "POST",
                              url: RestoreProject,
                              data: "plan=&lt;%= Model.RtpSummary.RtpYear %&gt;"
                                  + "&amp;id=" + id,
                              dataType: "json",
                              success: function(response, textStatus, XMLHttpRequest) {
                                  if (response.error == "false") {
                                      //$('').html(response.message);
                                      //$('').addClass('success');
                                      //autoHide(2500);
                                      oProjectListGrid.fnAddData([
                                          "&lt;a href=\"/RtpProject/" + response.data.RtpYear + "/Info/" + response.data.ProjectVersionId + "\"&gt;" + response.data.Title + "&lt;/a&gt;",
                                          response.data.PlanType,
                                          response.data.COGID,
                                          response.data.TIPId,
                                          response.data.ImprovementType,
                                          response.data.SponsorAgency,
                                          response.data.AmendmentStatus,
                                          response.data.ProjectVersionId]);
                                      countSuccess++;
                                      removeProject(id, false, null);
                                  } else {
                                      countError++;
                                      //$('.dialog-result').html(response.message + " Details: " + response.exceptionMessage);
                                      //$('.dialog-result').addClass('error');
                                      //autoHide(10000);
                                  }
                                  window.onbeforeunload = null;
                              },
                              error: function(response, textStatus, AjaxException) {
                                  //alert("error");
                                  countError++;
                                  //$('').html(response.statusText);
                                  //$('').addClass('error');
                                  //autoHide(10000);
                              }
                          });
                          //alert(eachCount);
                          //eachCount--;
                          $("#countReady").text(eachCount + ", " + countError + ", " + countSuccess);
                          //alert(eachCount + ", " + countError + ", " + countSuccess);
  
                          if (eachCount-1 == i) { showRestoreResponse(countError, countSuccess); }
                      });
                      //alert("test");
  
  
                      return false;
                  });
  </code></pre>
  
  <p><strong>SOLUTION!!!</strong></p>
  
  <p>First many thanks to all and specifically @SLaks! Second, <a href="http://james.padolsey.com/javascript/monitoring-dom-properties/" rel="nofollow noreferrer">http://james.padolsey.com/javascript/monitoring-dom-properties/</a> is credited for a small plugin to monitor an object.</p>
  
  <p>What I did was convert my original variables to an object that was essentially watched. Using the jquery plugin from above I watched the object for a condition:  newVal == 0, where newVal is the new value of the eachCount. That watch hit every millisecond waiting for all the server responses to come back to me with error or success. When finished I display a nice little summary report of the actions that happened.</p>
  
  <p>I'm not too sure if this was the best way but it looks good on the screen and my eyes dont hurt too bad looking at it. Below is my solution. Later I will add in the suggestions for keeping an active record update of what is left in the queue. All that code was primarily the debugging that I was adding.</p>
  
  <pre class="lang-js prettyprint-override"><code>$('#button-restore-projects').live("click", function() {
  
                  var element = $("#selectedProjects option");
  
                  var obj = { eachCount: element.length, countSuccess: 0, countError: 0 };
                  //$("#countReady").html(eachCount);
  
                  $.each(element, function(i, o) {
                      var id = $(this).val();
                      //alert(i);
                      $.ajax({
                          type: "POST",
                          url: RestoreProject,
                          data: "plan=&lt;%= Model.RtpSummary.RtpYear %&gt;"
                              + "&amp;id=" + id,
                          dataType: "json",
                          success: function(response, textStatus, XMLHttpRequest) {
                              if (response.error == "false") {
                                  //$('').html(response.message);
                                  //$('').addClass('success');
                                  //autoHide(2500);
                                  oProjectListGrid.fnAddData([
                                      "&lt;a href=\"/RtpProject/" + response.data.RtpYear + "/Info/" + response.data.ProjectVersionId + "\"&gt;" + response.data.Title + "&lt;/a&gt;",
                                      response.data.PlanType,
                                      response.data.COGID,
                                      response.data.TIPId,
                                      response.data.ImprovementType,
                                      response.data.SponsorAgency,
                                      response.data.AmendmentStatus,
                                      response.data.ProjectVersionId]);
                                  obj.eachCount--;
                                  obj.countSuccess++;
                                  removeProject(id, false, null);
                              } else {
                                  obj.countError++;
                                  //$('.dialog-result').html(response.message + " Details: " + response.exceptionMessage);
                                  //$('.dialog-result').addClass('error');
                                  //autoHide(10000);
                              }
                              window.onbeforeunload = null;
                          },
                          error: function(response, textStatus, AjaxException) {
                              //alert("error");
                              obj.countError++;
                              //$('').html(response.statusText);
                              //$('').addClass('error');
                              //autoHide(10000);
                          }
                      });
                      //$("#countReady").text(eachCount + ", " + countError + ", " + countSuccess);
                  });
  
                  $(obj).watch('eachCount', function(propName, oldVal, newVal) {
                      //alert(newVal);
                      if (newVal == 0) {
                          showRestoreResponse(obj.countError, obj.countSuccess);
                      }
                  });
  
                  return false;
              });
  </code></pre>