FullCalendar 中的重复事件

Recurring Events in FullCalendar

提问人:Junnel Gallemaso 提问时间:3/1/2013 最后编辑:ADysonJunnel Gallemaso 更新时间:8/13/2021 访问量:97912

问:

我正在使用jQuery FullCalendar作为我的日历,用于我的网站,用于可用性议程。

fullcalendar 中是否有任何函数/方法/选项可以按天处理我的重复事件?例如,周一到上午 7:00 到上午 9:00,周二 - 下午 4:00 到晚上 9:00,类似的东西?

javascript jquery 日历 fullcalendar-3

评论

0赞 suhailvs 3/16/2014
github.com/collective/jquery.recurrenceinput.js
0赞 Keerthivasan 10/13/2015
@Junnel,你是如何完成这项任务的?我有同样的要求。
1赞 user1332981 3/3/2013
FullCalendar 不支持开箱即用的定期事件。在 Google Code 上查看此问题
0赞 xottabych007 4/4/2017
在此处查看我的解决方案,使用 dayRender 回调 stackoverflow.com/a/43211196/4153620

答:

14赞 Juan Gonzales 3/5/2013 #1

看看这个网站...http://fajitanachos.com/Fullcalendar-and-recurring-events/

它为经常性事件提供了很多很好的现场信息。FullCalendar 支持与 id 相关的重复事件。您可以在服务器端或客户端处理事件,但首选是服务器端。我会给你一些想法,但并不包罗万象。据我所知,重复发生的事件维护起来很痛苦。

如果你想在客户端处理它们,你必须遍历重复事件的频率和哪一天的逻辑。您可能需要使用 eventRender 回调,然后使用 options 回调呈现每个循环事件。这样做的问题是,您仍然必须在数据库中保存频率选项的重复频率和逻辑运算符......

(column1:frequency=(int)8, column2:type=enum(a'b'c), a=每日, b=每周, c=每月等)。

...然后,每当您编辑该事件时,它都会编辑所有事件。如果你只需要删除一个事件,你的逻辑中就会遇到一系列问题,它很容易变成一个巨大的混乱。

第二种选择是执行所有这些服务器端操作。创建两个表,一个包含父事件,另一个包含其所有重复事件。在父表中,您将存储一般信息,例如唯一 ID、颜色、背景颜色、标题、allDay、isRecurring、频率、类型等。在子表中,您将使用父表中的唯一 ID 来关联每个重复周期(请记住,如果要删除/编辑单个事件,子表行也需要有自己的唯一 ID 以及标记它所在的表的列)。添加重复事件时,需要添加一个枚举字段,用于标记它是否是重复事件 AKA...

列:recurring=enum('0','1')---true/false

...然后,您需要将每个重复周期添加到子表中,其中包含其特定信息,例如开始和结束等。查询事件时,可以从父级查询,然后如果事件重复出现,则在第二个查询中获取这些关联的事件,也可以在单个查询中对 table1.id=table2.parentID 使用 INNER JOIN。

正如你所看到的,重复发生的事件可以非常快速地变得非常详细,找出你需要什么逻辑,我希望这对你或某人至少有所帮助。干杯。

评论

3赞 Ron E 5/30/2013
有关在服务器端实现重复事件的更多信息,请查看此链接,看起来第一个链接的作者使用此信息来创建他的表: martinfowler.com/apsupp/recurring.pdf
0赞 Enrique 7/17/2014
您是否知道可以帮助我将重复事件保存在子表中的库或 php 代码?例如。从 7 月 17 日星期四开始,每周四 10:00 至 11:00 至 11 月 20 日星期四。这将是大约 19 条记录......谢谢
0赞 Juan Gonzales 7/20/2014
老实说,我不知道任何库,而且我用于重复事件的代码非常复杂,可能对你没有任何好处。查看我留下的链接并从那里开始。如果您知道将出现多少次,只需使用输入字段,然后将该事件输入到子表中。
0赞 Paula Livingstone 4/4/2019
您在帖子开头发布的链接已失效。您是否碰巧有关于此包中与重复事件相关的资源的任何更新信息?
7赞 Akshay Jindal 5/21/2013 #2

无需建立父子关系,这里是为 jquery 中重复发生的事件提供简单解决方案的代码 完整日历 在 php 文件中使用以下函数,您可以进一步使用这些函数来调用所有事件。

function render_fccalendar_events() {
        $_POST['start'] = strtotime('2013-05-01');
        $_POST['end'] = strtotime('2013-05-31');
        $start = date('Y-m-d',$_POST['start']);
        $end = date('Y-m-d', $_POST['end']);
        $readonly = (isset($_POST['readonly'])) ? true : false;    
        $events = fcdb_query_events($start, $end);       
        render_json(process_events($events, $start, $end, $readonly));
}

function process_events($events, $start, $end, $readonly) {
    if ($events) {
        $output = array();
        foreach ($events as $event) {
            $event->view_start = $start;
            $event->view_end = $end;
            $event = process_event($event, $readonly, true);
            if (is_array($event)) {
                foreach ($event as $repeat) {
                    array_push($output, $repeat);
                }
            } else {
                array_push($output, $event);
            }
        }
        return $output;
    }
}

function process_event($input, $readonly = false, $queue = false) {
    $output = array();
    if ($repeats = generate_repeating_event($input)) {
        foreach ($repeats as $repeat) {
            array_push($output, generate_event($repeat));
        }
    } else {
        array_push($output, generate_event($input));
    }

    if ($queue) {
        return $output;
    }
    render_json($output);
}


function generate_event($input) {
    $output = array(
        'id' => $input->id,
        'title' => $input->name,
        'start' => $input->start_date,
        'end' => $input->end_date,
        'allDay' => ($input->allDay) ? true : false,
        //'className' => "cat{$repeats}",
        'editable' => true,
        'repeat_i' => $input->repeat_int,
        'repeat_f' => $input->repeat_freq,
        'repeat_e' => $input->repeat_end
    );
    return $output;
}



function generate_repeating_event($event) {

    $repeat_desk = json_decode($event->repeat_desk);
    if ($event->repeat == "daily") {
        $event->repeat_int =0;
        $event->repeat_freq = $repeat_desk->every_day;
    }
    if ($event->repeat == "monthly") {
        $event->repeat_int =2;        
        $event->repeat_freq = $repeat_desk->every_month;
    }
    if ($event->repeat == "weekly") {
        $event->repeat_int =1;                
       $event->repeat_freq = $repeat_desk->every_weak;
    }
    if ($event->repeat == "year") {
        $event->repeat_int =3;                        
        $event->repeat_freq = $repeat_desk->every_year;
    }

    if ($event->occurrence == "after-no-of-occurrences") {
        if($event->repeat_int == 0){
            $ext = "days";
        }
        if($event->repeat_int == 1){
            $ext = "weeks";
        }
        if($event->repeat_int == 2){
            $ext = "months";
        }
        if($event->repeat_int == 3){
            $ext = "years";
        }
       $event->repeat_end =  date('Y-m-d',strtotime("+" . $event->repeat_int . " ".$ext));
    } else if ($event->occurrence == "no-end-date") {
        $event->repeat_end = "2023-04-13";
    } else if ($event->occurrence == "end-by-end-date") {
        $event->repeat_end = $event->end_date;
    }



    if ($event->repeat_freq) {

        $event_start = strtotime($event->start_date);
        $event_end = strtotime($event->end_date);
        $repeat_end = strtotime($event->repeat_end) + 86400;
        $view_start = strtotime($event->view_start);
        $view_end = strtotime($event->view_end);
        $repeats = array();

        while ($event_start < $repeat_end) {
            if ($event_start >= $view_start && $event_start <= $view_end) {
                $event = clone $event; // clone event details and override dates
                $event->start_date = date(AEC_DB_DATETIME_FORMAT, $event_start);
                $event->end_date = date(AEC_DB_DATETIME_FORMAT, $event_end);
                array_push($repeats, $event);
            }
            $event_start = get_next_date($event_start, $event->repeat_freq, $event->repeat_int);
            $event_end = get_next_date($event_end, $event->repeat_freq, $event->repeat_int);
        }
        return $repeats;
    }
    return false;
 }

function get_next_date($date, $freq, $int) {
    if ($int == 0)
        return strtotime("+" . $freq . " days", $date);
    if ($int == 1)
        return strtotime("+" . $freq . " weeks", $date);
    if ($int == 2)
        return get_next_month($date, $freq);
    if ($int == 3)
        return get_next_year($date, $freq);
}

function get_next_month($date, $n = 1) {
    $newDate = strtotime("+{$n} months", $date);
    // adjustment for events that repeat on the 29th, 30th and 31st of a month
    if (date('j', $date) !== (date('j', $newDate))) {
        $newDate = strtotime("+" . $n + 1 . " months", $date);
    }
    return $newDate;
}

function get_next_year($date, $n = 1) {
    $newDate = strtotime("+{$n} years", $date);
    // adjustment for events that repeat on february 29th
    if (date('j', $date) !== (date('j', $newDate))) {
        $newDate = strtotime("+" . $n + 3 . " years", $date);
    }
    return $newDate;
}

function render_json($output) {
    header("Content-Type: application/json");
    echo json_encode(cleanse_output($output));
    exit;
}


function cleanse_output($output) {
    if (is_array($output)) {
        array_walk_recursive($output, create_function('&$val', '$val = trim(stripslashes($val));'));
    } else {
        $output = stripslashes($output);
    }
    return $output;
}

function fcdb_query_events($start, $end) {
    global $wpdb;
    $limit = ($limit) ? " LIMIT {$limit}" : "";
    $result = $wpdb->get_results("SELECT id, name,start_date,end_date,repeat_desk,`repeat`,occurrence,occurrence_desk

                                        FROM " . 

$wpdb->prefix . "lgc_events
                                        WHERE (
                                        (start_date >= '{$start}' AND start_date < '{$end}')
                                        OR (end_date >= '{$start}' AND end_date < '{$end}')
                                        OR (start_date <= '{$start}' AND end_date >= '{$end}')
                                        OR (start_date < '{$end}' AND (`repeat`!= ''))


                            )
                                        ORDER BY start_date{$limit};");

    return return_result($result);
}


function return_result($result) {
    if ($result === false) {
        global $wpdb;
        $this->log($wpdb->print_error());
        return false;
    }
    return $result;
}

在上面的代码中,我使用了repeat_desk其中存储了重复频率的 JSON 代码enter image description here

和 jquery 来调用你的文件

 events:  {
                url: '<?php echo $lgc_plugindir; ?>includes/imagerotator.php',
                data: {
                    action: 'get_events'
                },
                type: 'POST'
            }

我将其用于 WordPress,您可以根据您的要求使用此代码

2赞 Sergey Kharchishin 3/7/2015 #3

目前我正在做一个项目,我有 FullCalendar,我必须做定期事件。所以这就是我为什么可以做到这一点。希望这段代码对某人有所帮助:)

我在数据库中有下一个表:

CREATE TABLE IF NOT EXISTS `app_ext_calendar_events` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `users_id` int(11) NOT NULL,
  `name` varchar(255) NOT NULL,
  `description` text,
  `start_date` int(11) NOT NULL,
  `end_date` int(11) NOT NULL,
  `event_type` varchar(16) NOT NULL,
  `is_public` tinyint(1) DEFAULT NULL,
  `bg_color` varchar(16) DEFAULT NULL,
  `repeat_type` varchar(16) DEFAULT NULL,
  `repeat_interval` int(11) DEFAULT NULL,
  `repeat_days` varchar(16) DEFAULT NULL,
  `repeat_end` int(11) DEFAULT NULL,
  `repeat_limit` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_users_id` (`users_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=18 ;

我开发了下一个 php 类来获取具有重复事件的事件:

<?php

class calendar
{
  static public function get_events($date_from, $date_to,$calendar_type)
  {
    global $app_user;

    $list = array();

    $events_query = db_query("select * from app_ext_calendar_events where FROM_UNIXTIME(start_date,'%Y-%m-%d')>='" . $date_from . "' and  FROM_UNIXTIME(end_date,'%Y-%m-%d')<='" . $date_to . "' and event_type='" . $calendar_type . "' and users_id='" . db_input($app_user['id']) . "'");
    while($events = db_fetch_array($events_query))
    {
      $list[] = $events; 
    }

    if(count($repeat_events_list = calendar::get_repeat_events($date_to,$calendar_type)))
    {
      $list = array_merge($list,$repeat_events_list);
    }

    return $list;
  }

  public static function weeks_dif($start, $end)
  {
    $year_start = date('Y',$start);
    $year_end = date('Y',$end);

    $week_start = date('W',$start); 
    $week_end = date('W',$end);

    $dif_years = $year_end - $year_start;
    $dif_weeks = $week_end - $week_start;

    if($dif_years==0 and $dif_weeks==0)
    {
      return 0;
    }
    elseif($dif_years==0 and $dif_weeks>0)
    {
      return $dif_weeks;
    }
    elseif($dif_years==1)
    {
      return (42-$week_start)+$week_end;
    }
    elseif($dif_years>1)
    {
      return (42-$week_start)+$week_end+(($dif_years-2)*42);
    }


  }

  public static function months_dif($start, $end)
  {
    // Assume YYYY-mm-dd - as is common MYSQL format
    $splitStart = explode('-', date('Y-n',$start));
    $splitEnd = explode('-', date('Y-n',$end));

    if (is_array($splitStart) && is_array($splitEnd)) 
    {
        $startYear = $splitStart[0];
        $startMonth = $splitStart[1];
        $endYear = $splitEnd[0];
        $endMonth = $splitEnd[1];

        $difYears = $endYear - $startYear;
        $difMonth = $endMonth - $startMonth;

        if (0 == $difYears && 0 == $difMonth) 
        { // month and year are same
            return 0;
        }
        else if (0 == $difYears && $difMonth > 0) 
        { // same year, dif months
            return $difMonth;
        }
        else if (1 == $difYears) 
        {
            $startToEnd = 13 - $startMonth; // months remaining in start year(13 to include final month
            return ($startToEnd + $endMonth); // above + end month date
        }
        else if ($difYears > 1) 
        {
            $startToEnd = 13 - $startMonth; // months remaining in start year 
            $yearsRemaing = $difYears - 2;  // minus the years of the start and the end year
            $remainingMonths = 12 * $yearsRemaing; // tally up remaining months
            $totalMonths = $startToEnd + $remainingMonths + $endMonth; // Monthsleft + full years in between + months of last year
            return $totalMonths;
        }
    }
    else 
    {
      return false;
    }
  }

  public static function get_repeat_events($date_to,$calendar_type)
  {
    global $app_user;

    //convert date to timestamp
    $date_to_timestamp = get_date_timestamp($date_to);

    $list = array();

    //get all events that already started (start_date<=date_to)      
    $events_query = db_query("select * from app_ext_calendar_events where length(repeat_type)>0 and FROM_UNIXTIME(start_date,'%Y-%m-%d')<='" . $date_to . "' and  event_type='" . $calendar_type . "' and users_id='" . db_input($app_user['id']) . "'");
    while($events = db_fetch_array($events_query))
    {
      $start_date = $events['start_date'];

      //set repeat end      
      $repeat_end = false;
      if($events['repeat_end']>0)
      {
        $repeat_end = $events['repeat_end'];
      } 

      //get repeat events by type                       
      switch($events['repeat_type'])
      {
        case 'daily': 
            //check repeat events day bay day       
            for($date = $start_date; $date<=$date_to_timestamp; $date+=86400)            
            {
              if($date>$start_date)
              {
                $dif = round(abs($date-$start_date)/86400);

                if($dif>0)
                {  
                  $event_obj = $events;                                                
                  $event_obj['start_date'] = strtotime('+' . $dif . ' day',$event_obj['start_date']);                                                          
                  $event_obj['end_date'] = strtotime('+' . $dif . ' day',$event_obj['end_date']);

                  if(calendar::check_repeat_event_dif($dif,$event_obj,$repeat_end))
                  {                
                    $list[] = $event_obj;                
                  }
                }
              }
            }                                                          
          break;
        case 'weekly':  
            //check repeat events day bay day    
            for($date = $start_date; $date<=$date_to_timestamp; $date+=86400)            
            {
              if($date>$start_date)
              {
                //find days dif
                $dif = round(abs($date-$start_date)/86400);
                //find week dif
                $week_dif = calendar::weeks_dif($start_date, $date);

                if($dif>0 and (in_array(date('N',$date),explode(',',$events['repeat_days']))))
                {  
                  $event_obj = $events;                                                
                  $event_obj['start_date'] = strtotime('+' . $dif . ' day',$event_obj['start_date']);                                                          
                  $event_obj['end_date'] = strtotime('+' . $dif . ' day',$event_obj['end_date']);

                  if(calendar::check_repeat_event_dif($week_dif,$event_obj,$repeat_end))
                  {                
                    $list[] = $event_obj;                
                  }
                }
              }
            }                       

          break;            
        case 'monthly':                        
            /**
             *in calendar we display 3 month in one view
             *so we have to check difference for each month
             */

             //check 1                                      
            $date_to_timestamp2 = strtotime('-2 month',$date_to_timestamp);

            $dif =  calendar::months_dif($start_date, $date_to_timestamp2);

            if($dif>0)
            {  
              $event_obj = $events;                                                
              $event_obj['start_date'] = strtotime('+' . $dif . ' month',$event_obj['start_date']);                                                          
              $event_obj['end_date'] = strtotime('+' . $dif . ' month',$event_obj['end_date']);

              if(calendar::check_repeat_event_dif($dif,$event_obj,$repeat_end))
              {                
                $list[] = $event_obj;                
              }
            }

            //check 2
            $date_to_timestamp1 = strtotime('-1 month',$date_to_timestamp);

            $dif =  calendar::months_dif($start_date, $date_to_timestamp1);

            if($dif>0)
            {  
              $event_obj = $events;                                                
              $event_obj['start_date'] = strtotime('+' . $dif . ' month',$event_obj['start_date']);                                                          
              $event_obj['end_date'] = strtotime('+' . $dif . ' month',$event_obj['end_date']);

              if(calendar::check_repeat_event_dif($dif,$event_obj,$repeat_end))
              {                
                $list[] = $event_obj;                
              }
            }

            //check 3
            $dif =  calendar::months_dif($start_date, $date_to_timestamp);

            if($dif>0)
            {     
              $event_obj = $events;                                             
              $event_obj['start_date'] = strtotime('+' . $dif . ' month',$event_obj['start_date']);                                                          
              $event_obj['end_date'] = strtotime('+' . $dif . ' month',$event_obj['end_date']);

              if(calendar::check_repeat_event_dif($dif,$event_obj,$repeat_end))
              {                                
                $list[] = $event_obj;
              }
            }

          break;
        case 'yearly':                        
            $dif =  date('Y',$date_to_timestamp)-date('Y',$start_date);

            if($dif>0)
            {             
              $events['start_date'] = strtotime('+' . $dif . ' year',$events['start_date']);                                                          
              $events['end_date'] = strtotime('+' . $dif . ' year',$events['end_date']);

              if(calendar::check_repeat_event_dif($dif,$events,$repeat_end))
              {
                $list[] = $events;
              }
            }                                                                                               
          break;
      }            

    }

    return $list;

  }

  static public function check_repeat_event_dif($dif,$events,$repeat_end)
  {
    $check = true;

    if($dif>0)
    {
      //check interval
      if($dif/$events['repeat_interval']!=floor($dif/$events['repeat_interval'])) $check=false;            

      //check repeat limit
      if($events['repeat_limit']>0)            
      if(floor($dif/$events['repeat_interval'])>$events['repeat_limit']) $check=false;
    }
    else
    {
      $check=false; 
    } 

    //check repeat end date            
    if($repeat_end>0)
    {
      if($repeat_end<$events['start_date'])
      {
         $check=false;
      }
    }

    return $check;
  }  

}

获取所有事件 + 重复事件get_events函数 在我看来,有 4 种类型的重复事件:每日、每周、每月、每年 +有重复间隔,重复日期结束和重复限制。

函数get_repeat_events计算每种事件类型的差异,并包括重复事件(如果存在)。

注意:函数 db_query() 可以替换为 myslq_query 或其他内容

将事件准备到 FullCalendar 我正在使用下一个代码

$list = array();        

  foreach(calendar::get_events($_GET['start'],$_GET['end'],'personal') as $events)
  {
    $start = date('Y-m-d H:i',$events['start_date']);
    $end = date('Y-m-d H:i',$events['end_date']);


    $list[] = array('id' => $events['id'],
                  'title' => addslashes($events['name']),
                  'description' => str_replace(array("\n\r","\n","\r"),'<br>',$events['description']),
                  'start' => str_replace(' 00:00','',$start),
                  'end' => str_replace(' 00:00','',$end),
                  'color'=> $events['bg_color'],                      
                  'allDay'=>(strstr($start,'00:00') and strstr($end,'00:00')),
                  'url' => url_for('ext/calendar/personal_form','id=' . $events['id'])                      
                  );      
  }

  echo json_encode($list);
-2赞 user3401445 3/24/2015 #4

现在有一个插件可以做你想做的事:http://momentjs.com/docs/#/plugins/recur/

评论

0赞 ADyson 9/7/2017
目前尚不清楚这将如何与 fullCalendar 集成以解决所提出的问题。就其本身而言,它不会创建一种格式,用于为日历指定重复周期,也不会提供任何代码来操作事件源以创建重复周期。仅仅提供一个链接,没有进一步的信息是一个糟糕的答案。链接可能会过时。
101赞 DanielST 4/1/2015 #5

简单的重复事件

为了添加此处列出的简单替代方案,Fullcalendar 现在(在某种程度上)支持每周重复事件。因此,如果您只需要类似以下内容: ,则可以使用以下命令:[Every Monday and Thursday from 10:00am to 02:00pm]

events: [{
    title:"My repeating event",
    start: '10:00', // a start time (10am in this example)
    end: '14:00', // an end time (2pm in this example)
    dow: [ 1, 4 ] // Repeat monday and thursday
}],

JSFiddle

这记录在后台事件中,但它也适用于常规事件

将其保存到数据库中并不难。

添加一些限制

如果您不希望它们无限重复,则需要添加一些开始和结束日期。

因此,在数据库中:

  • 让上面显示的事件表示父记录
  • 有另一个包含开始/结束日期的表。
  • 联接表示例:

eventId  timeStart  timeEnd   dow    dateStart      dateEnd
     1      10:00    12:00  [1,4]  2015/03/01   2015/04/01  // Month of March
     1      10:00    12:00  [1,4]  2015/05/01   2015/06/01  // Month of May
     1      10:00    12:00  [1,4]  2016/01/01   2017/01/01  // Year of 2017

将其作为 JSON 传递给客户端:

{ id:1, start:"10:00", end:"12:00", dow:[1,4],
  ranges[{start:"2015/03/01", end:"2015/04/01"},
         {start:"2015/05/01", end:"2015/06/01"},
         {start:"2016/01/01", end:"2017/01/01"},]
}

客户端,使用 fullcalendar 的 eventRender 仅在其中一个时间范围内呈现事件。像这样的东西应该可以工作:

eventRender: function(event){
    return (event.ranges.filter(function(range){ // test event against all the ranges

        return (event.start.isBefore(range.end) &&
                event.end.isAfter(range.start));

    }).length)>0; //if it isn't in one of the ranges, don't render it (by returning false)
},

这是假设您的事件结构如下:

var repeatingEvents = [{
    title:"My repeating event",
    id: 1,
    start: '10:00', 
    end: '14:00', 
    dow: [ 1, 4 ], 
    ranges: [{ //repeating events are only displayed if they are within at least one of the following ranges.
        start: moment().startOf('week'), //next two weeks
        end: moment().endOf('week').add(7,'d'),
    },{
        start: moment('2015-02-01','YYYY-MM-DD'), //all of february
        end: moment('2015-02-01','YYYY-MM-DD').endOf('month'),
    },/*...other ranges*/],
},/*...other repeating events*/];

JSFiddle


一 夜 之间

如果您想要隔夜重复的事件(就像这里一样),只需在结束时间结束。例如:24:00

{
  start: '10:00', //starts at 10 on monday
  end:   '27:00', //24+3 is handled correctly.
  dow: [1]
}

JSFiddle

评论

0赞 Timber 4/15/2015
谢谢!这很有帮助,但可能会泄露有关范围和 eventRender 的更多详细信息?我可以让它在时间范围内渲染它们。
0赞 Timber 4/15/2015
非常感谢您添加这些内容!成功了。大大的拥抱。OP 应将此标记为答案:)。
1赞 Deepanshu Goyal 8/1/2015
答案很完美......谢谢。我正在尝试显示重复发生的事件,但需要删除特定日期的事件,假设我有一个整个星期日的重复事件,但我只需要删除特定星期日的事件
2赞 DanielST 8/1/2015
@Deepanshu 只需添加另一个名为 的表,这样您就可以为每个 .然后在 中,检查您正在呈现的事件是否不在该列表中。如果清楚,请告诉我。"excludedDates"rangeeventRender
1赞 DanielST 3/31/2017
@KevinCohen当然,只需向 eventRender 函数添加另一个条件即可。这个答案是一个模板,展示了如何有条件地渲染事件,你使用的实际条件是灵活的。
2赞 tohood87 12/18/2015 #6

这似乎在eventRender中工作得很好:function(event, element){}

            EXAMPLE JSON:
            var json = [{title: "All Day Event",
              start: "2015-12-22T00:00",
              end: "2015-12-22T23:55",
              dow: [2,4],
              recurstart: moment("2015-12-22").startOf("week"),
              recurend: moment("2015-12-22").endOf("week").add(1,'w')},{
              title: "Long Event",
              start: "2015-12-21T00:00",
              end: "2015-12-24T23:55",
              recurstart: moment("2015-12-21").startOf("month"),
              recurend: moment("2015-12-24").endOf("month"),
            }];

            eventRender: function(event, element){
            var theDate = moment(event.start).format("YYYY-MM-DD");
            var startDate = event.recurstart;
            var endDate = event.recurend;

            if (startDate < theDate && theDate < endDate) {
                console.log(theDate);
                }
            else {
                return event.length>0;
            }
            }, /* End eventRender */

1)在JSON中设置开始/结束日期和时间。

2) 在 JSON 中创建两个自定义 recur Start 和 recur End。

3) 使用 moment.js 创建重复持续时间:http://momentjs.com/docs/#/durations/

4) Recur Start 使用 (start:) 日期来确定一周的开始时间。

5) Recur End 使用 (end:) 日期来确定一周的结束 + 添加 1 周。

6) 增加 1、2、3 周可以创建重复限制。

7) 添加 JSON 的另一部分称为 (recurlimit:“”) 可以管理重复限制。

8) 在 eventRender 中使用变量 - 设置我的示例使用的日期 (theDate),即 moment(event.start)。正确格式化这一点很重要,以便 start/end/recurstart 等所有匹配格式,即 (YYYY-MM-DD) http://momentjs.com/docs/#/displaying/format/

9) 自定义 recurstart 的变量

10) 自定义重复的变量

11) 使用 IF 语句查看 (theDate) 介于 (recurstart) 和 (recurend) 之间的天气 - 日志结果

12) 使用 ELSE 语句返回 length>0 以隐藏不属于该参数的其他事件。

13) 非重复事件必须具有 moment(“match start date”).startOf(“month”) & moment(“match start date”).endOf(“month”),否则它们将不可见。

评论

1赞 Neil Masson 12/18/2015
如果答案包括解释和代码,则更好。
0赞 tohood87 12/18/2015
很抱歉,这是我的第一篇stackoverflow帖子。我添加了更多信息,希望能更清楚一些。
0赞 Rahul Pawar 6/9/2016
复发对我不起作用...请帮帮我和简单的陶氏:[ 1, 4 ] 也不起作用。
3赞 John 7/16/2019 #7

对于具有比 FullCalendar 可以处理的内置事件更复杂的重复事件的人(参见 slicedtoad 的答案),您可以使用 rSchedule

例如,周一至上午 7:00 至上午 9:00,周二 - 下午 4:00 至晚上 9:00

import { Schedule } from '@rschedule/rschedule';
import { StandardDateAdapter } from '@rschedule/standard-date-adapter';

const mondayDate = new Date(2019, 6, 15);
const tuesdayDate = new Date(2019, 6, 16);

const schedule = new Schedule({
  // add specific dates
  dates: [
    new StandardDateAdapter(mondayDate, {duration: 1000 * 60 * 60 * 2})
  ],
  // add recurrence rules
  rrules: [{
    start: tuesdayDate,
    duration: 1000 * 60 * 60 * 5, // duration is expressed in milliseconds
    frequency: 'WEEKLY'
  }],
});

const firstFiveEvents = schedule
  .occurrences({ take: 5 })
  .toArray()
  .map(adapter => 
    ({title: 'My event title', start: adapter.date, end: adapter.end})
  );

// You can then pass `firstFiveEvents` to fullcalendar for rendering

rSchedule 还支持 / 以及时区。有关更多信息,您可以查看 rSchedule 文档momentluxon

评论

0赞 ADyson 7/24/2019
那么,如何将其与fullCalendar集成以显示事件呢?从你的回答中并不清楚。
0赞 John 7/24/2019
@ADyson我只有使用 Angular FullCalendar 组件的经验,但您只需将事件映射到 fullcalendar 期望的事件格式,并将它们传递给 fullcalendar 进行渲染。一个简单的例子:schedule.occurrences({ take: 5 }).toArray().map(adapter => ({title: 'My event title', start: adapter.date, end: adapter.end}))
0赞 ADyson 7/24/2019
如果您将此部分作为答案文本本身的一部分,那么值得点赞 - 谢谢!
0赞 John 7/24/2019
我充实了这个例子 👍
1赞 leela 4/22/2020 #8

为了处理复杂的重复规则,我们应该使用 iCal 的 rrule 实现库。我们有JS库(rrule)。FullCalendar 现在还支持 rrule 插件

1赞 Nitesh S Chauhan 8/13/2021 #9

您可以使用以下代码显示一天、每天、每周、每两周和每月的事件,并在鼠标悬停事件上显示工具提示。

/*This is js*/

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

  var calendar = new FullCalendar.Calendar(calendarEl, {
    
    //NOTE MUST HAVE REFERENCE rrule javascript and plugin 'rrule', not rrPlugin like docs
    //if using scripts, not import/build method
    defaultDate: "2021-08-25",
    plugins: ['interaction', 'dayGrid', 'timeGrid', 'rrule'],
   timeZone: 'UTC',
   defaultView: 'dayGridMonth',
   header: {
     left: 'prev,next today',
     center: 'title',
     right: 'dayGridMonth,timeGridWeek,timeGridDay'
   },
   editable: true,
    eventClick: function(arg) {
      console.log(arg);
      if (confirm('Are you sure you want to delete this event?')) {
        arg.event.remove()
      }
    },
    eventMouseEnter: function(info) {
            var tis=info.el;
            var popup=info.event.extendedProps.popup;
            var tooltip = '<div class="tooltipevent" style="top:'+($(tis).offset().top-5)+'px;left:'+($(tis).offset().left+($(tis).width())/2)+'px"><div>' + popup.title + '</div><div>' + popup.description + '</div></div>';
            var $tooltip = $(tooltip).appendTo('body');
        },
        eventMouseLeave: function(info) {           
            $(info.el).css('z-index', 8);
            $('.tooltipevent').remove();
        },
    events: [    
   { 
     title: 'One Day',
      popup: {
          title: 'One Day',
          description: 'This is the description',
      }, 
     backgroundColor: '#c1391c',
     rrule: {        
        dtstart: '2021-08-01T10:30:00',
        until: '2021-08-01T19:30:00',        
        },          
    },    
    {     
     title: 'Daily',
     popup: {
          title: 'Daily',
          description: 'This is Daily the description',
      },       
     backgroundColor: '#bcc11c',
     rrule: {        
        freq: 'daily',
        dtstart: '2021-08-02T10:30:00',
        until: '2021-08-05T19:30:00',        
        },          
    }, 
    {     
     title: 'Weekly Event',
     popup: {
          title: 'Daily',
          description: 'This is Daily the description',
      },             
     backgroundColor: '#1cc1ab',
     rrule: {        
        freq: 'weekly',
        dtstart: '2021-08-06T10:30:00',
        until: '2021-08-20T19:30:00',        
        },          
    },    
    {     
     title: 'Two Weekly Event',
     popup: {
          title: 'Daily',
          description: 'This is Daily the description',
      },             
     backgroundColor: '#1c60c1',
     rrule: {        
        interval: 2,
        freq: 'weekly',
        dtstart: '2021-08-07T10:30:00',
        until: '2021-08-30T19:30:00',        
        },          
    },
    {     
     title: 'Four Weekl Event',
     popup: {
          title: 'Daily',
          description: 'This is Daily the description',
      },             
     backgroundColor: '#c11cbc',
     rrule: {        
        interval: 4,
        freq: 'weekly',
        dtstart: '2021-08-01T10:30:00',
        until: '2021-12-30T19:30:00',        
        },          
    },       
    ]
   
  });
  
  
  calendar.render();
});
html, body {
  margin: 0;
  padding: 0;
  font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
  font-size: 14px;
}

#calendar {
  max-width: 900px;
  margin: 40px auto;
}
.tooltipevent{
    width:200px;/*
    height:100px;*/
    background:#ccc;
    position:absolute;
    z-index:10001;
    transform:translate3d(-50%,-100%,0);
    font-size: 0.8rem;
    box-shadow: 1px 1px 3px 0px #888888;
    line-height: 1rem;
}
.tooltipevent div{
    padding:10px;
}
.tooltipevent div:first-child{
    font-weight:bold;
    color:White;
    background-color:#888888;
    border:solid 1px black;
}
.tooltipevent div:last-child{
    background-color:whitesmoke;
    position:relative;
}
.tooltipevent div:last-child::after, .tooltipevent div:last-child::before{
    width:0;
    height:0;
    border:solid 5px transparent;/*
    box-shadow: 1px 1px 2px 0px #888888;*/
    border-bottom:0;
    border-top-color:whitesmoke;
    position: absolute;
    display: block;
    content: "";
    bottom:-4px;
    left:50%;
    transform:translateX(-50%);
}
.tooltipevent div:last-child::before{
    border-top-color:#888888;
    bottom:-5px;
}
<!-- Required js and css with url -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/es5/rrule.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/@fullcalendar/[email protected]/main.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/@fullcalendar/[email protected]/main.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/@fullcalendar/[email protected]/main.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/@fullcalendar/[email protected]/main.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/@fullcalendar/[email protected]/main.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/tooltip.js/dist/umd/tooltip.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/popper.js/dist/umd/popper.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>

<link rel="stylesheet" type="text/css" href="https://unpkg.com/@fullcalendar/[email protected]/main.min.css">
<link rel="stylesheet" type="text/css" href="https://unpkg.com/@fullcalendar/[email protected]/main.min.css">
<link rel="stylesheet" type="text/css" href="https://unpkg.com/@fullcalendar/[email protected]/main.min.css">
<div id='calendar'></div>

评论

0赞 Jordan_Walters 8/16/2021
Nitesh,我在尝试使用您的代码段时不断收到以下错误:未捕获的 TypeError:无法读取未定义的属性“长度”有什么想法吗?你有没有一个偶然工作的编码笔?这绝对是我想要做的,您的任何建议都将是最有帮助的。
1赞 Nitesh S Chauhan 8/17/2021
您好@Jordan_Walters,您可以在事件点击函数中定义长度,如下代码: arg.length = '10';我希望它会有所帮助。