首页 > 解决方案 > 使用 fullcalendar.js 如何在日历的每个空单元格上显示时段开始时间?

问题描述

使用 fullcalendar 库,我想在我的日历上显示每个空单元格的开始时间(空单元格是在下面的屏幕截图中标有红十字或红点的单元格,我修改了一些日历的方面): 完整的日历截图 所以我的预期输出是一个日历,时间段变成按钮,当您单击时,您开始预订 30 分钟约会的过程,该约会将从书面时间开始(绿色槽是以下屏幕截图中的悬停效果): 预期产出 我找不到阅读完整日历文档后的任何简单方法: https ://fullcalendar.io/docs

附属问题,我找不到改变CSS中空单元格样式的方法。无法通过我的 Chrome 控制台选择元素。

document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');

var calendar = new FullCalendar.Calendar(calendarEl, {
    columnHeaderHtml: function(date) {
        if (date.getUTCDay() === 0) {
        var date_day = "Lundi";
        }
        if (date.getUTCDay() === 1) {
        var date_day = "Mardi";
        }
        if (date.getUTCDay() === 2) {
        var date_day = "Mercredi";
        }
        if (date.getUTCDay() === 3) {
        var date_day = "Jeudi";
        }
        if (date.getUTCDay() === 4) {
        var date_day = "Vendredi";
        }
        if (date.getUTCDay() === 5) {
        var date_day = "Samedi";
        }
        if (date.getUTCDay() === 6) {
        var date_day = "Dimanche";
        }
        if(date.getMonth() === 0)
        {
        var date_month = "Jan";
        } 
        if(date.getMonth() === 1)
        {
        var date_month = "Fev";
        } 
        if(date.getMonth() === 2)
        {
        var date_month = "Mar";
        } 
        if(date.getMonth() === 3)
        {
        var date_month = "Avr";
        } 
        if(date.getMonth() === 4)
        {
        var date_month = "Mai";
        } 
        if(date.getMonth() === 5)
        {
        var date_month = "Juin";
        } 
        if(date.getMonth() === 6)
        {
        var date_month = "Juil";
        } 
        if(date.getMonth() === 7)
        {
        var date_month = "Août";
        } 
        if(date.getMonth() === 8)
        {
        var date_month = "Sept";
        } 
        if(date.getMonth() === 9)
        {
        var date_month = "Oct";
        } 
        if(date.getMonth() === 10)
        {
        var date_month = "Nov";
        } 
        if(date.getMonth() === 11)
        {
        var date_month = "Dec";
        } 

        var day_num = date.getDate();
        return '<b>'+date_day+'</b><br><small>'+day_num+" "+date_month+"</small>";

    },

    plugins: [ 'interaction', 'dayGrid', 'list', 'googleCalendar','timeGrid' ],
    selectable: true,

    defaultView: 'timeGridFourDay',
    views: {
        timeGridFourDay: {
            type: 'timeGrid',
            duration: { days: 4 },
            buttonText: '4 day'
        }
    },
    slotLabelFormat:{
        hour: 'numeric',
        minute: '2-digit',
        omitZeroMinute: true,
        meridiem: 'short'
    },

    locale:'fr',
    header: {
        left: 'prev today',
        right: 'next'
    },
    validRange: {
        start: '2019-08-05',
        end: '2019-09-05'
    },
    allDaySlot:false,
    firstDay:1,
    minTime:"08:00:00",
    maxTime:"20:00:00",

    displayEventTime: true, // don't show the time column in list view

    // THIS KEY WON'T WORK IN PRODUCTION!!!
    // To make your own Google API key, follow the directions here:
    // http://fullcalendar.io/docs/google_calendar/
    googleCalendarApiKey: 'AIzaSyAL9K2UqkCVfV0n81mDW0iEpOJSwcklfsY',

    // US Holidays
    events: 'fr.fr#holiday@group.v.calendar.google.com',

    eventClick: function(arg) {
        arg.jsEvent.preventDefault() // don't navigate in main tab

        console.log(arg);
    },

    select: function(info) {

        console.log(info)

    },

    loading: function(bool) {

    },
    eventSources: [
    {
    googleCalendarId: 'contact@vetorino.com',
    className: "gcalEvent"

    }],

    displayEventEnd:false,
    events:[
    { // this object will be "parsed" into an Event Object

    start: '2019-08-05 12:30:00', // a property!
    end: '2019-08-05 14:00:00', // a property! ** see important note below about 'e6d' **
    overlap: true,
    backgroundColor:"#F7F7F7",
    textColor:"#979797",
    classNames:"closed",
    }],
      contentHeight: "auto",






    });

    calendar.render();

 });

到目前为止,如我之前的屏幕截图所示,我只是设法拥有空单元格,您可以找到一些信息的唯一单元格是包含事件的单元格。

标签: javascriptfullcalendarfullcalendar-4

解决方案


正如上面评论中所讨论的,fullCalendar HTML 中没有单个元素表示 timeGrid 视图中的特定“单元格”或“槽”。您可以在屏幕上看到的网格实际上是通过将多个表格叠加在一起而产生的错觉。

因此,为了满足您对用户能够在空闲时段中选择 20 分钟约会的要求,我可以看到两个主要选项。第一个是我通常推荐的,使用标准的 fullCalendar 功能。第二个更像你所要求的,但我认为它过于复杂了。

1)这个选项只是简单地设置日历的时间段为 20 分钟,然后有代码阻止用户选择更长的时间段(他们不能选择更短的时间段,由于slotDuration设置。这意味着他们可以点击在任何空白空间上一次,它就会知道在该位置创建一个正确长度的事件。不允许用户选择已经存在事件的任何插槽。(PS我希望实际上你需要收集更多数据之前添加事件,但对于演示,它会立即添加一个事件。)

document.addEventListener("DOMContentLoaded", function() {
  var Calendar = FullCalendar.Calendar;
  var calendarEl = document.getElementById("calendar");

  var calendar = new Calendar(calendarEl, {
    plugins: ["timeGrid", "interaction"],
    header: {
      left: "prev,next today",
      center: "title",
      right: "timeGridFourDay"
    },
    defaultView: "timeGridFourDay",
    views: {
      timeGridFourDay: {
        type: "timeGrid",
        duration: { days: 4 },
        buttonText: "4 day"
      }
    },
    slotLabelFormat: {
      hour: "numeric",
      minute: "2-digit",
      omitZeroMinute: true,
      meridiem: "short"
    },
    allDaySlot: false,
    firstDay: 1,
    minTime: "08:00:00",
    maxTime: "20:00:00",
    contentHeight: "auto",
    slotDuration: "00:20:00",
    selectable: true,
    select: function(info) {
      //console.log(info);
      calendar.addEvent({ "title": "Test", start: info.start, end: info.end })
      calendar.unselect();
    },
    selectOverlap: false,
    selectAllow: function(selectInfo) {
      var stM = moment(selectInfo.start);
      var enM = moment(selectInfo.end);
      var diff = enM.diff(stM, "minutes");
      console.log(diff);
      if (diff > 20)
      {
        return false;
      }
      return true;
    },
    events: [
      { "title": "Existing event", "start": "2019-08-08 10:00", "end": "2019-08-08 10:20"},
      { "title": "Existing event", "start": "2019-08-08 13:20", "end": "2019-08-08 13:40"},
]
  });

  calendar.render();
});

演示:https ://codepen.io/ADyson82/pen/aeqJQg


2) 此选项更接近您想要的 UI(来自您的第二张屏幕截图),但实现起来有点复杂。我个人也认为这会让你的日历看起来很混乱,并且更难看到空闲和忙碌的时段在哪里,但最终取决于你想要如何实现它。这通过添加第二个事件源来工作,其中包含所有当前空闲插槽的列表。然后这些用于在其中心显示每个空闲插槽的开始时间。它们与现有事件的颜色不同(表示一个繁忙的插槽),因此更容易区分。

当然,这需要您使用服务器端代码来计算数据库中所有当前可用的插槽,并使用该信息来填充第二个事件源。(在演示中,空闲槽数据是静态的,但在实际应用程序中当然不起作用。)

document.addEventListener("DOMContentLoaded", function() {
  var Calendar = FullCalendar.Calendar;
  var calendarEl = document.getElementById("calendar");

  var calendar = new Calendar(calendarEl, {
    plugins: ["timeGrid", "interaction"],
    header: {
      left: "prev,next today",
      center: "title",
      right: "timeGridFourDay"
    },
    defaultView: "timeGridFourDay",
    views: {
      timeGridFourDay: {
        type: "timeGrid",
        duration: { days: 4 },
        buttonText: "4 day"
      }
    },
    slotLabelFormat: {
      hour: "numeric",
      minute: "2-digit",
      omitZeroMinute: true,
      meridiem: "short"
    },
    allDaySlot: false,
    firstDay: 1,
    minTime: "08:00:00",
    maxTime: "20:00:00",
    contentHeight: "auto",
    slotDuration: "00:20:00",
    displayEventTime: false,
    eventClick: function(info) {
        if (info.event.extendedProps.type == "free") {
          calendar.addEvent({
            title: "Test",
            start: info.event.start,
            end: info.event.end
          });
          info.event.remove(); //delete the "free slot" event
        }
    },
    eventSources: [
      {
        id: "busy",
        events: [
          {
            title: "Existing event",
            start: "2019-08-08 10:00",
            end: "2019-08-08 10:20"
          },
          {
            title: "Existing event",
            start: "2019-08-08 13:20",
            end: "2019-08-08 13:40"
          }
        ]
      },
      {
        id: "free",
        backgroundColor: "green",
        events: [
          {
            title: "08:00",
            start: "2019-08-08 08:00",
            end: "2019-08-08 08:20",
            type: "free"
          },
          {
            title: "08:20",
            start: "2019-08-08 08:20",
            end: "2019-08-08 08:40",
            type: "free"
          },
          {
            title: "08:40",
            start: "2019-08-08 08:40",
            end: "2019-08-08 09:00",
            type: "free"
          },
          {
            title: "09:00",
            start: "2019-08-08 09:00",
            end: "2019-08-08 09:20",
            type: "free"
          },
          {
            title: "09:20",
            start: "2019-08-08 09:20",
            end: "2019-08-08 09:40",
            type: "free"
          },
          {
            title: "09:40",
            start: "2019-08-08 09:40",
            end: "2019-08-08 10:00",
            type: "free"
          },
          {
            title: "10:20",
            start: "2019-08-08 10:20",
            end: "2019-08-08 10:40",
            type: "free"
          },
          {
            title: "10:40",
            start: "2019-08-08 10:40",
            end: "2019-08-08 11:00",
            type: "free"
          },
        ]
      }
    ]
  });

  calendar.render();
});

对于这个演示,我只创建了少数“免费”插槽(因为创建它们很乏味),但希望你能了解它在整个日历中的外观如何。当然,您也可以根据您的要求修改 CSS。

演示:https ://codepen.io/ADyson82/pen/JgpNEX

(您当然可以进一步修改它的 CSS 以使其看起来更像您想要的外观。)

附录:这是 OP 的最终版本,适用于任何对最终产品感兴趣的人 - 基于考虑上述建议:https ://codepen.io/hugo-trial/pen/rXdajv


推荐阅读