I want to know how to repeat events from variable dates (start and end dates), weekly and monthly.
I found this answer, but it didn't work for me: Repeat fullcalendar events daily, monthly and yearly
This is my code:
function modal_activity_fun(info){
let modal_activity = $("#modal_activity");
function event_modal(){
// for modal_activity
modal_activity.on('show.bs.modal', function (e) { create_multiselect($('#activity_from')); });
modal_activity.on('shown.bs.modal', function (e) { $('#activity_title').focus(); });
modal_activity.on('hidden.bs.modal', function (e) {
document.getElementById("activity_form").reset();
$('#activity_from').multiselect('deselectAll', false);
$('#activity_from').multiselect('updateButtonText');
})
}
function datepicker_modal(){
// start datepicker
modal_activity.find('#activity_start_date').datepicker({
format: "DD, dd - MM - yyyy",
language: "pt-BR"
});
modal_activity.find('#activity_end_date').datepicker({
format: "DD, dd - MM - yyyy",
language: "pt-BR"
});
$('#activity_start_date').datepicker('setDate', moment(info.startStr, 'YYYY-MM-DD').format('DD - MM - YYYY'));
$('#activity_end_date').datepicker('setDate', moment(info.endStr, 'YYYY-MM-DD').subtract(1, "days").format('DD - MM - YYYY'));
}
function add_activity(){
// When 'add_activity' button is pressed, an event is created and the modal is closed
$('#add_activity').off("click");
$('#add_activity').on("click", info, function(e){
let title = modal_activity.find("#activity_title").val();
let btn = $(this);
let total_empty = 0;
let last_empty = '';
$('input,textarea,select').filter('[required]:visible').each(function(){
if($(this).val()==''){total_empty += 1; last_empty=$(this);}
});
let form = $(this).parents('.modal-content');
if (form.find("#activity_from").val().length == 0 ){
if (last_empty == ""){
last_empty = $('.dropdown-toggle, .multiselect');
}
total_empty += 1;
$('.dropdown-toggle, .multiselect').addClass("generic_focus");
}
if( total_empty == 0){
let startStr = moment($('#activity_start_date').datepicker('getDate')).format('YYYY-MM-DD');
let endStr = moment($('#activity_end_date').datepicker('getDate')).add(1, "days").format('YYYY-MM-DD');
let start_day_number = moment(startStr).subtract(1, "days").day();
let end_day_number = moment(endStr).subtract(1, "days").day();
let extendedProps = {
description: form.find('#activity_description').val(),
from: form.find('#activity_from').val(),
repetition: form.find('#activity_repetition option:selected' ).text(),
status: "Scheduled",
}
let event_object = {title: title, start: startStr, end:endStr, allDay: true, extendedProps: extendedProps}
let repetition = form.find('#activity_repetition').val();
if(repetition == 3){
event_object['repeat'] = 1;
}
if(repetition == 2){
event_object['repeat'] = 0;
}
debugger;
info.calendar.addEvent(event_object);
modal_activity.modal('hide');
}else{
last_empty.focus();
btn.popover("show");
setTimeout(function(event) {btn.popover("hide")},3000);
}
});
}
function go(options='show'){
modal_activity.modal(options);
}
function assemble(){
event_modal();
datepicker_modal();
add_activity();
go();
}
return {assemble}
}
function modal_activity_view_fun(info){
let modal_activity_view = $('#modal_activity_view');
let startStr = moment(info.event.startStr, 'YYYY-MM-DD').locale('pt-br');
let endStr = moment(info.event.endStr, 'YYYY-MM-DD').locale('pt-br').subtract(1, "days");
modal_activity_view.on('hidden.bs.modal', function (e) { $('#activity_repetition_view').html(); });
function set_values(){
modal_activity_view.find('.modal-title').text(info.event.title);
modal_activity_view.find('#activity_description_view').html(info.event.extendedProps.description.replace(/\n/g, "</br>\n"));
if(startStr.isSame(endStr)){
modal_activity_view.find('#activity_schedule_view').html(startStr.format('dddd, DD [de] MMMM'));
}else if(startStr.month() == endStr.month() && startStr.year() == endStr.year()){
modal_activity_view.find('#activity_schedule_view').html(
startStr.format('DD')+' – '+endStr.format('DD [de] MMMM')
);
}else{
modal_activity_view.find('#activity_schedule_view').html(
startStr.format('DD [de] MMMM [de] YYYY')+' – '+endStr.format('DD [de] MMMM [de] YYYY')
);
}
debugger;
if (info.event.extendedProps.repetition != "não se repete"){
modal_activity_view.find('#activity_repetition_view').html('• '+info.event.extendedProps.repetition);
}
modal_activity_view.find("#activity_status_view").text(info.event.extendedProps.status)
}
function go(options='show'){
modal_activity_view.modal(options);
}
function assemble(){
set_values();
go();
}
return {assemble}
}
function list_interval(start, end){
let array = [];
for(let i=start; i <= end; i++){
array.push(i);
}
return array;
}
function fullcalendar_activities(){
document.addEventListener('DOMContentLoaded', function() {
var calendar_atv_el = document.getElementById('calendar_atv');
var calendar_atv = new FullCalendar.Calendar(calendar_atv_el, {
initialView: 'dayGridMonth',
selectable: true,
locale: 'pt-br',
select: function(info){
info["calendar"] = calendar_atv;
let activity = modal_activity_fun(info);
activity.assemble();
},
eventClick: function(info) {
let activity_view = modal_activity_view_fun(info);
activity_view.assemble();
}
});
calendar_atv.render();
});
}
function create_multiselect(element){
element.multiselect({
enableFiltering: true,
includeSelectAllOption: true,
enableCaseInsensitiveFiltering: true,
buttonWidth: '100%',
maxHeight: 450,
});
}
(function() {
// start fullcalendar
fullcalendar_activities();
})();
.modalPdf{visibility: visible;}
.m-0 {margin: 0!important;}
.m-1 {margin: .25rem!important;}
.m-2 {margin: .5rem!important;}
.m-3 {margin: 1rem!important;}
.m-4 {margin: 1.5rem!important;}
.m-5 {margin: 3rem!important;}
.mr-0{margin-right: 0rem!important;text-align: justify;}
.mr-3{margin-right: 1rem!important;text-align: justify;}
.ml-0{margin-left: 0rem!important;text-align: justify;}
.ml-3{margin-left: 1rem!important;text-align: justify;}
.mt-0{margin-top: 0rem!important;text-align: justify;}
.mt-3{margin-top: 1rem!important;text-align: justify;}
.mr-2, .mx-2 {margin-right: .5rem!important;}
.mt-4, .my-4 {margin-top: 1.5rem!important;}
.mt-5{margin-top: 3rem!important;text-align: justify;}
.ml-auto, .mx-auto {margin-left: auto!important;}
.mr-auto, .mx-auto {margin-right: auto!important;}
.mx-3 {margin-right: 1rem!important;margin-left: 1rem!important;}
.mb-2, .my-2 {margin-bottom: .5rem!important;}
.mt-2, .my-2 {margin-top: .5rem!important;}
.mb-auto, .my-auto {margin-bottom: auto!important;}
.mt-auto, .my-auto {margin-top: auto!important;}
.ml-0, .mx-0 {margin-left: 0!important;}
.mr-0, .mx-0 {margin-right: 0!important;}
.ml-1, .mx-1 {margin-left: .25rem!important;}
.mr-1, .mx-1 {margin-right: .25rem!important;}
.ml-4, .mx-4 {margin-left: 1.5rem!important;}
.mb-5, .my-5 {margin-bottom: 3rem!important;}
.p-2 {padding: .5rem!important;}
.p-3 {padding: 1rem!important;}
.pl-0, .px-0 {padding-left: 0!important;}
.pr-0, .px-0 {padding-right: 0!important;}
.pb-2, .py-2 {padding-bottom: .5rem!important;}
.pt-2, .py-2 {padding-top: .5rem!important;}
.pl-2, .px-2 {padding-left: .5rem!important;}
.pr-2, .px-2 {padding-right: .5rem!important;}
.pl-3, .px-3 {padding-left: 1rem!important;}
.pr-3, .px-3 {padding-right: 1rem!important;}
.pl-5, .px-5 {padding-left: 3rem!important;}
.pr-5, .px-5 {padding-right: 3rem!important;}
.align-middle {vertical-align: middle!important;}
.align-items-center {
-webkit-box-align: center!important;
-ms-flex-align: center!important;
align-items: center!important;
}
.d-flex {
display: -webkit-box!important;
display: -ms-flexbox!important;
display: flex!important;
}
.h-100 {height: 100%!important;}
.btn {white-space:normal !important; word-wrap: break-word; word-break: normal;}
.form-row {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
margin-right: -5px;
margin-left: -5px;
}
.form-row>.col, .form-row>[class*=col-] {
padding-right: 5px;
padding-left: 5px;
}
.dropzone, .rounded {border-radius: .25rem!important;}
.dropzone{border-style:dashed;}
.dz-progress{top: 70%!important;}
.dz-error-message{top:105%!important;}
.table-responsive {
display: block;
width: 100%;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
-ms-overflow-style: -ms-autohiding-scrollbar;
}
.ftacoes{white-space: nowrap;}
.a-remove{
white-space: nowrap;
font-size: 13px;
text-align: center;
display: block;
cursor: pointer;
border: none;
}
.disabledbutton {
pointer-events: none;
opacity: 0.4;
}
.header{
position:sticky;
top: 0;
}
.valid-tooltip {
position: absolute;
top: 100%;
left: 0;
z-index: 5;
display: none;
max-width: 100%;
padding: .25rem .5rem;
margin-top: .1rem;
font-size: 1.4rem;
line-height: 1.5;
color: #fff;
background-color: rgba(40,167,69,.9);
border-radius: .25rem;
}
.invalid-tooltip {
position: absolute;
top: 100%;
left: 0;
z-index: 5;
display: none;
max-width: 100%;
padding: .25rem .5rem;
margin-top: .1rem;
font-size: 1.4rem;
line-height: 1.5;
color: #fff;
background-color: rgba(220,53,69,.9);
border-radius: .25rem;
}
.bg-light {background-color: #f8f9fa!important;}
.d-table{ display: table!important; }
.position-relative {position: relative!important;}
.float-right {float: right!important;}
.btn-x-sm {
padding: .25rem .5rem;
font-size: .875rem;
line-height: 1.5;
border-radius: .2rem;
}
.align-middle {
vertical-align: middle!important;
}
.cursor-pointer{
cursor: pointer;
}
.btn-default2 {
color: #333;
background-color: #fff;
}
.btn-default2:focus {
color: #333;
background-color: #e6e6e6;
}
.btn-default2:hover {
color: #333;
background-color: #e6e6e6;
}
.btn-default2:active {
color: #333;
background-color: #e6e6e6;
}
@keyframes spinner-border {
to { transform: rotate(360deg)}
}
.spinner-border {
display: inline-block;
width: 2rem;
height: 2rem;
vertical-align: text-bottom;
border: .25em solid currentColor;
border-right-color: transparent;
border-radius: 50%;
-webkit-animation: .75s linear infinite spinner-border;
animation: .75s linear infinite spinner-border;
}
.spinner-border-sm {
width: 1rem;
height: 1rem;
border-width: .2em;
}
.spinner-border-md {
width: 1.5rem;
height: 1.5rem;
border-width: .25em;
}
.spanIcone{ width: 1.8rem;}
.fc-event{
cursor: pointer;
}
.generic_focus:focus{
border-color: #66afe9;
outline: 0;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102,175,233,.6);
box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102,175,233,.6);
}
.text-truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Language" content="pt-br">
<title>Atividades dos Colaboradores</title>
<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<!-- Bootstrap -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<!-- Ícones -->
<script src="https://kit.fontawesome.com/a076d05399.js"></script>
<!-- fullcalendar -->
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@5.4.0/main.min.js" integrity="sha256-oenhI3DRqaPoTMAVBBzQUjOKPEdbdFFtTCNIosGwro0=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fullcalendar@5.4.0/main.min.css" integrity="sha256-uq9PNlMzB+1h01Ij9cx7zeE2OR2pLAfRw3uUUOOPKdA=" crossorigin="anonymous">
<script src='https://cdn.jsdelivr.net/npm/rrule@2.6.4/dist/es5/rrule.min.js'></script>
<!-- multiselect -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-multiselect/0.9.15/css/bootstrap-multiselect.css" integrity="sha512-EvvoSMXERW4Pe9LjDN9XDzHd66p8Z49gcrB7LCUplh0GcEHiV816gXGwIhir6PJiwl0ew8GFM2QaIg2TW02B9A==" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-multiselect/0.9.15/js/bootstrap-multiselect.min.js" integrity="sha512-aFvi2oPv3NjnjQv1Y/hmKD7RNMendo4CZ2DwQqMWzoURKxcqAoktj0nNG4LU8m23+Ws9X5uVDD4OXLqpUVXD5Q==" crossorigin="anonymous"></script>
<!--datapicker-->
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/css/bootstrap-datepicker.css" rel='stylesheet' type='text/css'>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/js/bootstrap-datepicker.js"></script>
<!--tradução datepicker para pt-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/locales/bootstrap-datepicker.pt-BR.min.js"></script>
<!-- moment js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/locale/pt-br.min.js" integrity="sha512-1IpxmBdyZx3okPiZ14mzw6+pOGa690uDmcdjqvT310Kwv3NRcjvL/aOtoSprEyvkDdAb7ZtM2um6KrLqLOY97w==" crossorigin="anonymous"></script>
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<div class="row">
<div class="col-xs-12">
<!--Painel que contém todo o conteúdo-->
<div class="panel mt-3 panel-default">
<div class="panel-body">
<div id="calendar_atv"></div>
</div>
</div><!-- /.painel -->
</div><!-- /.col -->
</div><!-- /.row -->
</div><!-- /.container -->
<div id="modal_activity" class="modal fade bs-example-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">New</h4>
</div>
<div class="modal-body">
<form id="activity_form">
<div class="form-group">
<label for="activity_title" class="control-label">Title:</label>
<input type="text" class="form-control" id="activity_title", placeholder="Adicione um título" maxlength="40" required>
</div>
<div class="form-group">
<label for="activity_description" class="control-label">Description:</label>
<textarea class="form-control" rows="4" id="activity_description" placeholder="Descreva a atividade" required></textarea>
</div>
<div class="form-group">
<label for="activity_from" class="control-label">for:</label>
<select id="activity_from" name="multiselect[]" multiple="multiple" class="form-control">
<option valeu="1">email1@emal.com</option>
<option valeu="2">email2@emal.com</option>
<option valeu="3">email3@emal.com</option>
</select>
</div>
<label for="activity_start_date" class="control-label">scheduling:</label>
<div class="row">
<div class="col-xs-6 pr-0">
<div class="form-group mx-0">
<label for="activity_start_date" class="col-xs-1 px-0 control-label"><i class="far fa-clock" style="vertical-align: -6px;"></i></label>
<div class="col-xs-11 pl-1 pr-0">
<input type="text" class="form-control" id="activity_start_date" placeholder="data inicial" required>
</div>
</div>
</div>
<div class="col-xs-6">
<div class="form-group ">
<input type="text" class="form-control" id="activity_end_date" placeholder="data final" required>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-6">
<div class="form-group mx-0">
<div class="col-xs-1 px-0"></div>
<div class="col-xs-8 pl-1 pr-0">
<select id="activity_repetition" name="activity_from"class="form-control" required>
<option value="1">does not repeat</option>
<option value="2">weekly</option>
<option value="3">monthly</option>
</select>
</div>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button id="add_activity" type="button" class="btn btn-primary" data-toggle="popover" data-trigger="manual" data-placement="top" data-content="Some fields are empty.">Save</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<div id="modal_activity_view" class="modal fade bs-example-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title text-truncate">Evento</h4>
</div>
<div class="modal-body">
<form id="activity_form_view">
<div class="text-center" >Status: <span id="activity_status_view" style="vertical-align: 2px;" class="label label-default ">...</span></div>
<h5>Description</h5>
<div class="row">
<div class="col-xs-12">
<div class="form-group mx-0">
<div class="col-xs-1 px-0">
<i class="fas fa-align-justify" aria-hidden="true"></i>
</div>
<div class="col-xs-11 pl-0 pr-0">
<p id="activity_description_view"></p>
</div>
</div>
</div>
</div>
<h5 >Scheduling</h5>
<div class="row">
<div class="col-xs-12">
<div class="form-group mx-0">
<div class="col-xs-1 px-0">
<i class="far fa-calendar-alt" aria-hidden="true"></i>
</div>
<div class="col-xs-11 pl-0 pr-0">
<p id="activity_schedule_view"></p>
<p id="activity_repetition_view"></p>
</div>
</div>
</div>
</div>
<div class="text-center">
<button type="button" class="mt-5 form-check btn btn-default">
<i class="fa fa-check mr-2" aria-hidden="true"></i>Mark as done
</button>
</div>
</form>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</body>
<link rel="stylesheet" href="activities.css">
<script src="activities.js"></script>
</html>
basically when the period is selected in the calendar, a modal is opened in which the user must enter information such as: title, description and the repetition options for the event.
I tried to use "dow:" when creating the event, but when it is a long event (with more than one day), it divides that event into days. I also tried to use "repeat: 1", but nothing just happened