无法将动态事件添加到 jquery 简单日历插件

Unable to add dynamic events to jquery Simple Calendar Plugin

我在向 jquery 简单日历插件动态添加事件时遇到问题。这是代码:

$(document).ready(function() {
  var calInfo = new Array();
  var startDate = '';
  var finDate = '';
  jQuery.ajax({  
      async: true,  // Async by default is set to “true” load the script asynchronously
      url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/GetByTitle('Global Holidays')/items",   // URL to fetch data from sharepoint list
      method: "GET",  //Specifies the operation to fetch the list item
      headers: {  
        "accept": "application/json;odata=verbose",   //defines the Data format
        "content-type": "application/json;odata=verbose"   //defines the content type as JSON
      },  
      success: function(data) {
        $.each(data.d.results, function(key, value) {
            startDate = value.EventDate;
            startDate = startDate.slice(0, -1);
            finDate = value.EndDate;
            finDate = finDate.slice(0, -1);
            var obj = {
                'startDate': startDate, 
                'endDate': finDate, 
                'summary': value.Title
            };
            calInfo.push(obj);
        });
        console.log(calInfo);
    },  
    error: function(data) {
        console.log(JSON.stringify(data));  
    }  
});

  jQuery("#container").simpleCalendar({
    fixedStartDay: 0, // begin weeks by sunday
    disableEmptyDetails: true,
    events: calInfo
  });
});

日历上没有显示任何内容。但是,如果我手动将对象添加到事件数组,则它们会显示:

jQuery("#container").simpleCalendar({
    fixedStartDay: 0, // begin weeks by sunday
    disableEmptyDetails: true,
    events: [
        { startDate: "2020-01-01T00:00:00", endDate: "2020-01-01T23:59:00", summary: "New Year's Day" },
        { startDate: "2020-02-17T00:00:00", endDate: "2020-02-17T23:59:00", summary: "Family Day" },
        { startDate: "2020-04-10T00:00:00", endDate: "2020-04-10T23:59:00", summary: "Good Friday" },
        { startDate: "2020-05-18T00:00:00", endDate: "2020-05-18T23:59:00", summary: "Victoria Day" },
        { startDate: "2020-06-04T00:00:00", endDate: "2020-06-04T23:59:00", summary: "St. Jean Baptiste" },
        { startDate: "2020-07-01T00:00:00", endDate: "2020-07-01T23:59:00", summary: "Canada Day" },
        { startDate: "2020-08-03T00:00:00", endDate: "2020-08-03T23:59:00", summary: "Civic Holiday" },
        { startDate: "2020-09-07T00:00:00", endDate: "2020-09-07T23:59:00", summary: "Labor Day" },
        { startDate: "2020-10-12T00:00:00", endDate: "2020-10-12T23:59:00", summary: "Thanksgiving" },
        { startDate: "2020-11-11T00:00:00", endDate: "2020-11-11T23:59:00", summary: "Remembrance Day" },
        { startDate: "2020-12-25T00:00:00", endDate: "2020-12-25T23:59:00", summary: "Christmas Day" },
        { startDate: "2020-12-28T00:00:00", endDate: "2020-12-28T23:59:00", summary: "Boxing Day" },
        { startDate: "2020-05-25T00:00:00", endDate: "2020-05-25T23:59:00", summary: "Memorial Day" },
        { startDate: "2020-07-04T00:00:00", endDate: "2020-07-04T23:59:00", summary: "Independence Day" },
        { startDate: "2020-01-20T00:00:00", endDate: "2020-01-20T23:59:00", summary: "Martin Luther King's Birthday" },
        { startDate: "2020-02-17T00:00:00", endDate: "2020-02-17T23:59:00", summary: "President's Day" },
        { startDate: "2020-11-26T00:00:00", endDate: "2020-11-26T23:59:00", summary: "Thanksgiving Day" },
        { startDate: "2020-11-27T00:00:00", endDate: "2020-11-27T23:59:00", summary: "Day After Thanksgiving" },
        { startDate: "2020-09-07T00:00:00", endDate: "2020-09-07T23:59:00", summary: "Independence Day" },
        { startDate: "2020-10-05T00:00:00", endDate: "2020-10-05T23:59:00", summary: "Labour Day" },
        { startDate: "2020-04-13T00:00:00", endDate: "2020-04-13T23:59:00", summary: "Easter Monday" },
        { startDate: "2020-05-08T00:00:00", endDate: "2020-05-08T23:59:00", summary: "Early May Bank Holiday (VE Day)" },
        { startDate: "2020-05-25T00:00:00", endDate: "2020-05-25T23:59:00", summary: "Spring Bank Holiday" },
        { startDate: "2020-08-31T00:00:00", endDate: "2020-08-31T23:59:00", summary: "Summer Bank Holiday" },
        { startDate: "2020-08-03T00:00:00", endDate: "2020-08-03T23:59:00", summary: "Summer Bank Holiday" },
        { startDate: "2020-11-30T00:00:00", endDate: "2020-11-30T23:59:00", summary: "St. Andrew's Day" },
        { startDate: "2020-05-04T00:00:00", endDate: "2020-05-04T23:59:00", summary: "May Public Holiday" },
        { startDate: "2020-06-01T00:00:00", endDate: "2020-06-01T23:59:00", summary: "June Public Holiday" },
        { startDate: "2020-08-03T00:00:00", endDate: "2020-08-03T23:59:00", summary: "August Public Holiday" },
        { startDate: "2020-10-26T00:00:00", endDate: "2020-10-26T23:59:00", summary: "October Public Holiday" },
        { startDate: "2020-12-26T00:00:00", endDate: "2020-12-26T23:59:00", summary: "St. Stephen's Day" },
        { startDate: "2020-01-27T00:00:00", endDate: "2020-01-27T23:59:00", summary: "Australia Day" },
        { startDate: "2020-03-09T00:00:00", endDate: "2020-03-09T23:59:00", summary: "Canberra Day" },
        { startDate: "2020-04-11T00:00:00", endDate: "2020-04-11T23:59:00", summary: "Easter Saturday" },
        { startDate: "2020-04-12T00:00:00", endDate: "2020-04-12T23:59:00", summary: "Easter Sunday" },
        { startDate: "2020-04-14T00:00:00", endDate: "2020-04-14T23:59:00", summary: "Easter Tuesday" },
        { startDate: "2020-04-25T00:00:00", endDate: "2020-04-25T23:59:00", summary: "Anac Day" },
        { startDate: "2020-05-04T00:00:00", endDate: "2020-05-04T23:59:00", summary: "May Day" },

    ],
        
});

控制台日志输出显示数组如下: 数组 [] (calInfo) Array(38) [ {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, ... ](事件)

我怀疑是数组构建的方式导致了这个问题,但我不知道如何纠正它。

知道我应该做什么吗?

谢谢。

您的代码的问题是您的 plug-in 的初始化发生在 之前 您的 Ajax 请求完成(由于它的 异步行为)。所以我修改了你的代码,先获取事件信息,然后再初始化。

这是一个例子:

;(function ($, window, document, undefined) {

  "use strict";

  // Create the defaults once
  var pluginName = "simpleCalendar",
    defaults = {
      months: ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'], //string of months starting from january
      days: ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'], //string of days starting from sunday
      displayYear: true, // display year in header
      fixedStartDay: true, // Week begin always by monday or by day set by number 0 = sunday, 7 = saturday, false = month always begin by first day of the month
      displayEvent: true, // display existing event
      disableEventDetails: false, // disable showing event details
      disableEmptyDetails: false, // disable showing empty date details
      events: [], // List of event
      onInit: function (calendar) {}, // Callback after first initialization
      onMonthChange: function (month, year) {}, // Callback on month change
      onDateSelect: function (date, events) {}, // Callback on date selection
      onEventSelect: function () {},              // Callback fired when an event is selected     - see $(this).data('event')
      onEventCreate: function( $el ) {},          // Callback fired when an HTML event is created - see $(this).data('event')
      onDayCreate:   function( $el, d, m, y ) {}  // Callback fired when an HTML day is created   - see $(this).data('today'), .data('todayEvents')
    };

  // The actual plugin constructor
  function Plugin(element, options) {
    this.element = element;
    this.settings = $.extend({}, defaults, options);
    this._defaults = defaults;
    this._name = pluginName;
    this.currentDate = new Date();
    this.init();
  }

  // Avoid Plugin.prototype conflicts
  $.extend(Plugin.prototype, {
    init: function () {
      var container = $(this.element);
      var todayDate = this.currentDate;

      var calendar = $('<div class="calendar"></div>');
      var header = $('<header>' +
        '<h2 class="month"></h2>' +
        '<a class="simple-calendar-btn btn-prev" href="#"></a>' +
        '<a class="simple-calendar-btn btn-next" href="#"></a>' +
        '</header>');

      this.updateHeader(todayDate, header);
      calendar.append(header);

      this.buildCalendar(todayDate, calendar);
      container.append(calendar);

      this.bindEvents();
      this.settings.onInit(this);
    },

    //Update the current month header
    updateHeader: function (date, header) {
      var monthText = this.settings.months[date.getMonth()];
      monthText += this.settings.displayYear ? ' <div class="year">' + date.getFullYear() : '</div>';
      header.find('.month').html(monthText);
    },

    //Build calendar of a month from date
    buildCalendar: function (fromDate, calendar) {
      var plugin = this;

      calendar.find('table').remove();

      var body = $('<table></table>');
      var thead = $('<thead></thead>');
      var tbody = $('<tbody></tbody>');

      //setting current year and month
      var y = fromDate.getFullYear(), m = fromDate.getMonth();

      //first day of the month
      var firstDay = new Date(y, m, 1);
      //last day of the month
      var lastDay = new Date(y, m + 1, 0);
      // Start day of weeks
      var startDayOfWeek = firstDay.getDay();

      if (this.settings.fixedStartDay !== false) {
        // Backward compatibility
        startDayOfWeek =  this.settings.fixedStartDay ? 1 : this.settings.fixedStartDay;

        // If first day of month is different of startDayOfWeek
        while (firstDay.getDay() !== startDayOfWeek) {
          firstDay.setDate(firstDay.getDate() - 1);
        }
        // If last day of month is different of startDayOfWeek + 7
        while (lastDay.getDay() !== ((startDayOfWeek + 7) % 7)) {
          lastDay.setDate(lastDay.getDate() + 1);
        }
      }

      //Header day in a week ( (x to x + 7) % 7 to start the week by monday if x = 1)
      for (var i = startDayOfWeek; i < startDayOfWeek + 7; i++) {
        thead.append($('<td>' + this.settings.days[i % 7].substring(0, 3) + '</td>'));
      }

      //For firstDay to lastDay
      for (var day = firstDay; day <= lastDay; day.setDate(day.getDate())) {
        var tr = $('<tr></tr>');
        //For each row
        for (var i = 0; i < 7; i++) {
          var td = $('<td><div class="day" data-date="' + day.toISOString() + '">' + day.getDate() + '</div></td>');

          var $day = td.find('.day');

          //if today is this day
          if (day.toDateString() === (new Date).toDateString()) {
            $day.addClass("today");
          }

          //if day is not in this month
          if (day.getMonth() != fromDate.getMonth()) {
            $day.addClass("wrong-month");
          }

          // filter today's events
          var todayEvents = plugin.getDateEvents(day);

          if (todayEvents.length && plugin.settings.displayEvent) {
            $day.addClass(plugin.settings.disableEventDetails ? "has-event disabled" : "has-event");
          } else {
            $day.addClass(plugin.settings.disableEmptyDetails ? "disabled" : "");
          }

          // associate some data available from the onDayCreate callback
          $day.data( 'todayEvents', todayEvents );

          // simplify further customization
          this.settings.onDayCreate( $day, day.getDate(), m, y );

          tr.append(td);
          day.setDate(day.getDate() + 1);
        }
        tbody.append(tr);
      }

      body.append(thead);
      body.append(tbody);

      var eventContainer = $('<div class="event-container"><div class="close"></div><div class="event-wrapper"></div></div>');

      calendar.append(body);
      calendar.append(eventContainer);
    },
    changeMonth: function (value) {
      this.currentDate.setMonth(this.currentDate.getMonth() + value, 1);
      this.buildCalendar(this.currentDate, $(this.element).find('.calendar'));
      this.updateHeader(this.currentDate, $(this.element).find('.calendar header'));
      this.settings.onMonthChange(this.currentDate.getMonth(), this.currentDate.getFullYear())
    },
    //Init global events listeners
    bindEvents: function () {
      var plugin = this;

      //Click previous month
      $(plugin.element).on('click', '.btn-prev', function ( e ) {
        plugin.changeMonth(-1)
        e.preventDefault();
      });

      //Click next month
      $(plugin.element).on('click', '.btn-next', function ( e ) {
        plugin.changeMonth(1);
        e.preventDefault();
      });

      //Binding day event
      $(plugin.element).on('click', '.day', function (e) {
        var date = new Date($(this).data('date'));
        var events = plugin.getDateEvents(date);
        if (!$(this).hasClass('disabled')) {
          plugin.fillUp(e.pageX, e.pageY);
          plugin.displayEvents(events);
        }
        plugin.settings.onDateSelect(date, events);
      });

      //Binding event container close
      $(plugin.element).on('click', '.event-container .close', function (e) {
        plugin.empty(e.pageX, e.pageY);
      });
    },
    displayEvents: function (events) {
      var plugin = this;
      var container = $(this.element).find('.event-wrapper');

      events.forEach(function (event) {
        var startDate = new Date(event.startDate);
        var endDate = new Date(event.endDate);
        var $event = $('' +
          '<div class="event">' +
          ' <div class="event-hour">' + startDate.getHours() + ':' + (startDate.getMinutes() < 10 ? '0' : '') + startDate.getMinutes() + '</div>' +
          ' <div class="event-date">' + plugin.formatDateEvent(startDate, endDate) + '</div>' +
          ' <div class="event-summary">' + event.summary + '</div>' +
          '</div>');

        $event.data( 'event', event );
        $event.click( plugin.settings.onEventSelect );

        // simplify further customization
        plugin.settings.onEventCreate( $event );

        container.append($event);
      })
    },
    //Small effect to fillup a container
    fillUp: function (x, y) {
      var plugin = this;
      var elem = $(plugin.element);
      var elemOffset = elem.offset();

      var filler = $('<div class="filler" style=""></div>');
      filler.css("left", x - elemOffset.left);
      filler.css("top", y - elemOffset.top);

      elem.find('.calendar').append(filler);

      filler.animate({
        width: "300%",
        height: "300%"
      }, 500, function () {
        elem.find('.event-container').show();
        filler.hide();
      });
    },
    //Small effect to empty a container
    empty: function (x, y) {
      var plugin = this;
      var elem = $(plugin.element);
      var elemOffset = elem.offset();

      var filler = elem.find('.filler');
      filler.css("width", "300%");
      filler.css("height", "300%");

      filler.show();

      elem.find('.event-container').hide().find('.event').remove();

      filler.animate({
        width: "0%",
        height: "0%"
      }, 500, function () {
        filler.remove();
      });
    },
    getDateEvents: function (d) {
      var plugin = this;
      return plugin.settings.events.filter(function (event) {
        return plugin.isDayBetween(d, new Date(event.startDate), new Date(event.endDate));
      });
    },
    isDayBetween: function (d, dStart, dEnd) {
      dStart.setHours(0,0,0);
      dEnd.setHours(23,59,59,999);
      d.setHours(12,0,0);

      return dStart <= d && d <= dEnd;
    },
    formatDateEvent: function (dateStart, dateEnd) {
      var formatted = '';
      formatted += this.settings.days[dateStart.getDay()] + ' - ' + dateStart.getDate() + ' ' + this.settings.months[dateStart.getMonth()].substring(0, 3);

      if (dateEnd.getDate() !== dateStart.getDate()) {
        formatted += ' to ' + dateEnd.getDate() + ' ' + this.settings.months[dateEnd.getMonth()].substring(0, 3)
      }
      return formatted;
    }
  });

  // A really lightweight plugin wrapper around the constructor,
  // preventing against multiple instantiations
  $.fn[pluginName] = function (options) {
    return this.each(function () {
      if (!$.data(this, "plugin_" + pluginName)) {
        $.data(this, "plugin_" + pluginName, new Plugin(this, options));
      }
    });
  };

})(jQuery, window, document);

$(document).ready(function() {
     setupEvents();
})

function getEvents() {
  
  return $.ajax({  
      url: "https://my-json-server.typicode.com/SagnalracSO/repo/events", // URL to fetch data from sharepoint list
      method: "GET",  //Specifies the operation to fetch the list item
      content_type: "application/json;odata=verbose"   //defines the content type as JSON
    });
}

function setupEvents() {

    getEvents().done(function(data) {
          
          var calInfo = [];
          
          $.each(data, function(key, value) { //.d.results
             var obj = {
                'startDate': value.startDate, //lStartDate, 
                'endDate': value.endDate, //finDate, 
                'summary': value.summary
             };
             calInfo.push(obj);
          });
          //console.log(calInfo);
          initializeSimpleCalendar(calInfo);
     })
     .fail(function(txtStatus) {
         concole.log("Error!");
     });
}

function initializeSimpleCalendar(jEvents) {

    $("#container").simpleCalendar({
        fixedStartDay: 0, // begin weeks by sunday
        disableEmptyDetails: true,
        events: jEvents
    });
}
.calendar {
  position: relative;
  overflow: hidden;
  text-transform: capitalize;
  text-align: center;
  font: 15px/1em inherit;
  color: #545A5C; }
  .calendar a {
    text-decoration: none;
    color: inherit; }
  .calendar header .simple-calendar-btn {
    display: inline-block;
    position: absolute;
    width: 30px;
    height: 30px;
    text-align: center;
    line-height: 30px;
    color: #CBD1D2;
    border-radius: 50%;
    border: 2px solid #CBD1D2; }
  .calendar header .simple-calendar-btn:hover {
    background: #CBD1D2;
    color: white; }
  .calendar header .simple-calendar-btn:before {
    content: '';
    position: absolute;
    top: 9px;
    left: 8px;
    width: 8px;
    height: 8px;
    border-style: solid;
    border-width: 3px 3px 0 0;
    transform: rotate(45deg);
    transform-origin: center center; }
  .calendar header .btn-prev {
    top: 0;
    left: 0;
    transform: rotate(-180deg); }
  .calendar header .btn-next {
    top: 0;
    right: 0; }
    .calendar header .btn-next:before {
      transform: rotate(45deg); }
  .calendar header .month {
    padding: 0;
    margin: 0; }
    .calendar header .month .year {
      font-size: 0.6em;
      font-weight: 100; }
  .calendar table {
    width: 100%;
    margin: 20px 0;
    border-spacing: 0px; }
  .calendar thead {
    font-size: 1.2em;
    font-weight: 600; }
  .calendar td {
    padding: .8em .1em; }
  .calendar .day {
    position: relative;
    display: inline-block;
    width: 2.5em;
    height: 2.5em;
    line-height: 2.5em;
    border-radius: 50%;
    border: 2px solid transparent;
    cursor: pointer; }
    .calendar .day:hover {
      border: 2px solid #6691CC; }
    .calendar .day.today {
      background: #6691CC;
      color: white; }
      .calendar .day.today.has-event:after {
        background: white; }
    .calendar .day.wrong-month {
      color: #CBD1D2; }
    .calendar .day.wrong-month:hover {
      border: 2px solid transparent; }
    .calendar .day.has-event:after {
      content: '';
      position: absolute;
      top: calc(50% + .6em);
      left: calc(50% - 2px);
      width: 4px;
      height: 4px;
      border-radius: 50%;
      background: #6691CC; }
    .calendar .day.disabled {
      cursor: default; }
      .calendar .day.disabled:hover {
        border: 2px solid transparent; }
  .calendar .event-container {
    display: none;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    padding: 70px;
    background: #545A5C;
    box-sizing: border-box; }
    .calendar .event-container .event-wrapper {
      overflow-y: auto;
      max-height: 100%; }
    .calendar .event-container .close {
      position: absolute;
      width: 30px;
      height: 30px;
      top: 20px;
      right: 20px;
      cursor: pointer; }
      .calendar .event-container .close:before, .calendar .event-container .close:after {
        content: '';
        position: absolute;
        top: 0;
        left: 50%;
        width: 2px;
        height: 100%;
        background-color: #CBD1D2; }
      .calendar .event-container .close:before {
        transform: rotate(45deg); }
      .calendar .event-container .close:after {
        transform: rotate(-45deg); }
    .calendar .event-container .event {
      position: relative;
      width: 100%;
      padding: 1em;
      margin-bottom: 1em;
      background: #6691CC;
      border-radius: 4px;
      box-sizing: border-box;
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.12);
      text-align: left;
      color: white; }
      .calendar .event-container .event-date {
        margin-bottom: 1em; }
      .calendar .event-container .event-hour {
        float: right; }
      .calendar .event-container .event-summary {
        font-weight: 600; }
  .calendar .filler {
    position: absolute;
    width: 0;
    height: 0;
    border-radius: 50%;
    background: #545A5C;
    transform: translate(-50%, -50%); 
}
<link href='https://fonts.googleapis.com/css?family=Lato' rel='stylesheet' type='text/css'>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://raw.githubusercontent.com/brospars/simple-calendar/master/dist/jquery.simple-calendar.min.js"></script>

<div id="container"></div>

注意: 很抱歉,因为我找不到脚本和 css 文件的 CDN,所以我不得不将两者都包含在代码片段中.