【问题标题】:Moment / Jquery - Silly issue with a simple timelineMoment / Jquery - 简单时间线的愚蠢问题
【发布时间】:2016-05-18 13:02:09
【问题描述】:

我从这个社区获得了很多帮助,让我的时间线报告能够正常工作。设置的方式是通过检查 ajax 返回来获取日期范围。然后它将按星期几对我的所有条目进行分组。如果该日期范围内的特定 i 没有条目,那么它将简单地返回“今天没有条目”。

目前一切正常,您可以查看以下示例: https://jsfiddle.net/j3yg2j7j/7/

但是我注意到,如果日期范围的最后一天为空,它会忽略它。我需要它来返回“今天没有条目”。即使最后一天是空的。

这是一个问题的例子。 https://jsfiddle.net/j3yg2j7j/6/

更新: 发现另一个奇怪的问题。当我给它2016-05-02到2016-05-05的范围时。我开始收到重复的项目。

https://jsfiddle.net/j3yg2j7j/5/

这是 Ajax 请求:

responseText: {
    d: {
        results: [{
            ID: "1",
            Description: "Test1",
            Date: "2016-05-02 09:45"
        }, {
            ID: "2",
            Description: "Test2",
            Date: "2016-05-02 10:45"
        }, {
            ID: "3",
            Description: "Test3",
            Date: "2016-05-03 11:45"
        }, {
            ID: "4",
            Description: "Test4",
            Date: "2016-05-03 11:45",
        }]
    }
}

这是javascript:

      var items_by_date  = {}; // declare an object that will have date indexes
      $.ajax({url:"/SomeUrlBeginninWithSlash",
          dataType: 'json',
          cache: false,
          success: function (data) {
                    console.log("SUCCESS",data);    
                    drawTable(data.d.results);
          }
      });

 var drawTable = function(data) {
  // First sort the entries by date:
  data = data.sort(function(a, b) {
    return (moment(a.Date) - moment(b.Date));
  });

  // Find the date range to work with by looking at each end of the array:
  var firstDate = moment("2016-05-02");
  var lastDate = moment("2016-05-04");

  // loop through each day in that range, keeping track of a starting point i
  // so we don't have to keep checking already-passed events.
  var i = 0, // pointer to the first entry to check on the next date
    ret = ""; 
  for (var thisDate = firstDate; thisDate <= lastDate; thisDate.add(1, 'days')) {
    ret += '<tr><th>' + thisDate.format("dddd, MMMM D") + "</th></tr>";

    // check to see if the next entry is already beyond thisDate:
    if (moment(data[i].Date) > thisDate.endOf('day')) {
      ret += "<tr><td>No entries today.</td></tr>";
    } else {
      // starting at entry i, display all entries before the end of thisDate:
      for (var j = i; j < data.length; j++) {
        if (moment(data[j].Date) < thisDate.endOf('day')) {
          // the next one belongs on thisDate, so display it:
          ret += '<tr><td>' + moment(data[j].Date).format("HH:mm") + " - " + data[j].Description + "</td></tr>";
        } else {
          // next one is not for thisDate, so we can go on to the next day.
          i = j; // It'll start here, so we don't waste time looping over past events
          break; // (out of the inner loop)
        }
      }
    }
  }
  $('#x').html(ret);
}

我知道我忽略了一些简单的东西,但不能完全理解它。

【问题讨论】:

  • 我不确定我是否理解您在 ajax 数据之外设置范围的结尾。您的 lastDate 取决于数据数组的长度,因此在您损坏的示例中,它无法知道您想要包含 5 月 4 日。
  • 啊,那可能是问题所在。我在这里得到了其他用户的帮助来构建该功能。它的一部分仍然超出我的范围,但我试图找出我需要调整的地方。

标签: javascript jquery ajax momentjs


【解决方案1】:

对于缺少的最后一天,您将 lastDate 设置为 5 月 4 日的开始 - 它需要改为当天结束:

var lastDate = moment("2016-05-04").endOf('day');

重复事件是因为我为您的最后一个问题编写的代码假定条目列表中的最后一个日期是您要显示的最后一个日期,因此不需要处理您的情况在用完条目后继续循环遍历日期。这可以通过处理这种情况来解决:

if (i === data.length) {
   // we've run out of entries; don't try to check past the end of the data array:
   ret += "<tr><td>No entries today.</td></tr>";   
} else if (moment(data[i].Date) > thisDate.endOf('day')) {
  // The next entry is later than this day.
  ret += "<tr><td>No entries today.</td></tr>";
} else {
  // starting at entry i, display all entries before the end of thisDate:
  for (var j = i; j < data.length; j++) {
    if (moment(data[j].Date) < thisDate.endOf('day')) {
      // the next one belongs on thisDate, so display it:
      ret += '<tr><td>' + moment(data[j].Date).format("HH:mm") + " - " + data[j].Description + "</td></tr>";
    } else {
      // next one is not for thisDate, so we can go on to the next day.
      i = j; // It'll start here, so we don't waste time looping over past events
      break; // (out of the inner loop)
    }
  }
  // Did we run out of entries?  If so, need to update i here to prevent repeated display
  if (j === data.length) {
    i = j;
  }
}

https://jsfiddle.net/tt35rnoo/

但是……

考虑到您曾多次就这个问题提出变体,最好在这里保持简单。试试这个效率较低但复杂得多的版本,它不会尝试跳过每个循环中已经显示的事件:

  // loop through each day in that range
  var ret = ""; 
  for (var thisDate = firstDate; thisDate <= lastDate; thisDate.add(1, 'days')) {
    ret += '<tr><th>' + thisDate.format("dddd, MMMM D") + "</th></tr>";
    var showedAnEventToday=false;

    for (var j = 0; j < data.length; j++) {
        if (
            moment(data[j].Date) > thisDate.startOf('day') && 
            moment(data[j].Date) < thisDate.endOf('day')
        ) {

          showedAnEventToday = true;
          ret += '<tr><td>' + moment(data[j].Date).format("HH:mm") + " - " + data[j].Description + "</td></tr>";
        } 
    }
    if (!showedAnEventToday) {
        ret += '<tr><td>No events today.</td></tr>';
    }
  }
  $('#x').html(ret);

https://jsfiddle.net/ejaca00t/

【讨论】:

  • 再次感谢丹尼尔,非常感谢。您的初始代码超出了我对 javascript 的理解。第二个版本对我来说更容易理解。再次感谢丹尼尔!
猜你喜欢
  • 2021-10-29
  • 1970-01-01
  • 2011-08-24
  • 1970-01-01
  • 1970-01-01
  • 2015-07-11
  • 1970-01-01
  • 2021-09-05
  • 2011-06-09
相关资源
最近更新 更多