How to display end time on oneslot events with Fullcalendar? - javascript

How to display end time on oneslot events? I want one slot events to show start and end like the longer events(12.00-12.30).
Already tried using timeFormat but that didn't help. Using select to make new events.
Oneslot events have end on database but it's not showing on the calendar for some reason.
Problem is that when user clicks the calendar it creates event that has start and end but for some reason only start shows on the calendar (lower event on picture) but when user selects larger area like 1h it shows start and end on the calendar (first event).
Those events that don't show end on the calendar seem to break the for--if in select. After creating 30 min long event user can make overlapping events.
Picture with the problem:
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right:''
},
allDaySlot: false,
allDayDefault:false,
lang: currentLangCode,
slotEventOverlap:false,
minTime:"09:00:00",
maxTime:"15:00:00",
hiddenDays:[6,0],
lazyFetching:true,
selectable: true,
selectHelper: true,
aspectRatio:3.15,
select: function(start, end) {
check_time=false;
var events = $("#calendar").fullCalendar('clientEvents');
if(moment(start._d).format('YYYY/MM/DD')== moment(end._d).format('YYYY/MM/DD')){
overnight=true;
}
else{
overnight=false;
}
if(events.length>0){
for(var i in events)
{
//prevent overlapping events
if(
((moment(events[i].start._d).format('YYYY/MM/DD/HH/mm')) == (moment(start._d).format('YYYY/MM/DD/HH/mm'))) ||
(((moment(events[i].start._d).format('YYYY/MM/DD/HH/mm')) < (moment(end._d).format('YYYY/MM/DD/HH/mm')))&&
((moment(events[i].end._d).format('YYYY/MM/DD/HH/mm')) > (moment(start._d).format('YYYY/MM/DD/HH/mm')))) ||
(((moment(events[i].start._d).format('YYYY/MM/DD/HH/mm')) > (moment(start._d).format('YYYY/MM/DD/HH/mm'))) &&
((moment(events[i].start._d).format('YYYY/MM/DD/HH/mm')) < (moment(end._d).format('YYYY/MM/DD/HH/mm')))) ||
(((moment(events[i].start._d).format('YYYY/MM/DD/HH/mm')) > (moment(start._d).format('YYYY/MM/DD/HH/mm'))) &&
((moment(events[i].end._d).format('YYYY/MM/DD/HH/mm')) < (moment(end._d).format('YYYY/MM/DD/HH/mm'))))
){
check_time=false;
}
else{
check_time=true;
}
i++;
}
}
else{
check_time=true;
}
$("#dialog").dialog("open");
startstamp=moment(start).unix();
endstamp=moment(end).unix();
starttime=moment(start).toISOString();
endtime=moment(end).toISOString();
$('#calendar').fullCalendar('unselect');
},
defaultView: 'agendaWeek',
editable: false,
events:/events.php
});

Related

Fullcalendar | Jquery hover function doesn't work anymore after view changing

The Context
Hi everybody,
I'm using Fullcalendar to display availabilities and bookings of properties (houses) in a CRM application developed under Symfony 3.
The calendar is functional. We have .fc-event-container element to display the bookings and .fc-bgevent for the availabilities as below.
fullcalendar.png
What I've added after, is the possibility to know, by hovering a cell (.fc-bgevent), who has set the availabilities and when. These informations are retrieved from the database, stored into a custom attribute « data-informations » during the render of each cell (.fc-bgevent) and finally displayed above the calendar view container as below.
fullcalendar-hover.png
To show you how I have achieved that, I put the code of the using files below.
Controller
//src/LD/PlatformBundle/Controller/Properties/indexController.php
public
function viewAction(Request $request, $id) {
$events = $manager - > getRepository('LDPlatformBundle:Availabilities') - > findBy(array('idProperties' => $id));
$Availa = array();
foreach($events as $event) {
...
$Ava['user'] = $event - > getIdUsers();
$Ava['updateDate'] = $event - > getDateModifAvailabilities();
if ($Ava['updateDate'] != null) {
$Ava['updateDate'] = $Ava['updateDate'] - > format('D d-M-y');
} else {
$Ava['updateDate'] = "unknonw date";
}
if ($Ava['user'] == null) {
$Ava['user'] = 'unknown user';
}
$Ava['informations'] = "Created by ".$Ava['user'].
" on ".$Ava['updateDate'];
$Availa[] = $Ava;
}
return $this - > render('LDPlatformBundle:Properties:view.html.twig', array(
'Availa' => $Availa,
));
}
View
//src/LD/PlatformBundle/Resources/views/Properties/view.html.twig
<script >
$(document).ready(function() {
$('#calendar').fullCalendar({
schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source',
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay,listMonth'
},
navLinks: true, // can click day/week names to navigate views
businessHours: true, // display business hours
editable: false,
eventOverlap: false,
events: [{ % include('FrontBootstrap/ajaxPlanning.html.twig') %
}],
eventRender: function(event, element) {
$(element).attr('data-informations', event.informations);
},
nextDayThreshold: "01:00:00"
});
$('.fc-view-container').prepend('<div id="informations-date"><span></span></div>');
$('#informations-date').css('visibility', 'hidden');
$('.fc-bgevent').hover(function() {
var informations = $(this).attr('data-informations');
$('#informations-date span').text(informations);
$('#informations-date').css('visibility', 'visible');
}, function() {
$('#informations-date').css('visibility', 'hidden');
});
});
</script>
<style >
#informations - date {
height: 20 px;
}
/* Disable hover */
.fc - content - skeleton,
.fc - bgevent - skeleton {
pointer - events: none
}
/* Enable hover on .fc-bgevent, .fc-bgevent-skeleton child and .fc-event-container */
.fc - bgevent,
.fc - event - container {
pointer - events: auto;
}
</style>
Events
//app/Resources/views/FrontBootstrap/ajaxPlanning.html.twig
{ %
for ava in Availa %
} {
start: ('{{ ava.start|date("Y") }}-{{ ava.start|date("m") }}-{{ ava.start|date("d") }}'),
color: '{{ ava.color }}',
rendering: 'background',
informations: '{{ava.informations}}',
} { %
if loop.last %
} { %
else %
}, { % endif %
} { % endfor %
}
The Problem
Now, the thing is, when I change the view by selecting other month (june, july...) or other range (week, month...), the functionality doesn't work anymore. I know the problem comes from Jquery because I still have the attribute « data-informations » on the cells of others views. I first thought that the hover function doesn't work cause its targets elements that are on the DOM when the function is called. That's why I also try to declare the function and call it into viewRender parameter but it didn't solved the problem.
//src/LD/PlatformBundle/Resources/views/Properties/view.html.twig
$(document).ready(function() {
// console.log(items);
console.log(Availa);
$('#calendar').fullCalendar({
schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source',
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay,listMonth'
},
navLinks: true, // can click day/week names to navigate views
businessHours: true, // display business hours
editable: false,
eventOverlap: false,
events: [{ % include('FrontBootstrap/ajaxPlanning.html.twig') %
}],
eventRender: function(event, element) {
$(element).attr('data-informations', event.informations);
},
viewRender: function(view, element) {
console.log('ok');
$('.fc-bgevent').hover(function() {
console.log('ok');
});
getDateInformations();
},
nextDayThreshold: "01:00:00"
});
$('.fc-view-container').prepend('<div id="informations-date"><span></span></div>');
getDateInformations();
});
function getDateInformations() {
$('#informations-date').css('visibility', 'hidden');
$('.fc-bgevent').hover(function() {
console.log('ok');
var informations = $(this).attr('data-informations');
console.log(informations);
$('#informations-date span').text(informations);
$('#informations-date').css('visibility', 'visible');
}, function() {
$('#informations-date').css('visibility', 'hidden');
});
}
I think there is surely a special feature of the hover function that I don't know.
You'd have to add the event handler in fullCalendar's eventAfterAllRender instead of viewRender because, as the documentation (https://fullcalendar.io/docs/viewRender) says, viewRender runs after the plain view has been drawn, but the events are not necessarily loaded into it at that time - that is done asynchronously, so there's a good chance your events are still not in the DOM at that time.
eventAfterAllRender: function(view)
{
$('.fc-bgevent').hover(function() {
console.log('ok');
});
}
See also https://fullcalendar.io/docs/v3/eventAfterAllRender

Get fullcalendar business-hours on resize events

I have implemented full calendar to maintain some events. Now the fullcalendar is implemented with some default business hours. Lets say I have set business hours from 10:00 to 17:00 hours.
Now I am creating the event from 15:30 to 16:30 hours. Now I when I resize the event and stretch it and end it to 17:30, which is out of the business hours, I want it to revert the changes.
Following is how I have initialised the fullcalendar:
$('#calendar').fullCalendar({
header: {
left: '',
center: '',
right: '',
},
firstDay: 0,
editable: true,
selectable: true,
defaultView: 'agendaWeek',
columnFormat: 'dddd',
events: events_data,
eventResize: function(event, delta, revertFunc) {
console.log($(this).businessHours);
}
});
In your eventResize function, you can check the event parameter and check the input.
function isBusinessHour(event) {
// Check if your event.start and event.end is in business hours
// Using moment functions such as isBetween()
}
eventResize: function(event, delta, revertFunc) {
if (!isBusinessHour(event))
revertFunc();
}
To achieve this you can set the "eventConstraint" option to "businessHours":
eventConstraint: "businessHours"
The documentation for this setting says:
If "businessHours" is given, events being dragged or resized must be
fully contained within the week’s business hours (Monday-Friday
9am-5pm by default). A custom businessHours value will be respected.
See https://fullcalendar.io/docs/eventConstraint for more details.
It does not work, even with the version 4.
You need to compare values for event and those of business Hours:`
eventDrop: function(info) {
var format = 'HH:mm';
// get moment as time:min only
var ies = moment(info.event.start);
var tes = ies.hours()+':'+ies.minutes();
var event_start = moment(tes,format);
var iee = moment(info.event.end);
var tee = iee.hours()+':'+iee.minutes();
var event_end = moment(tee,format);
// get business hours
var bh_start = moment(calendar.getOption('businessHours')['startTime'],format);
var bh_end = moment(calendar.getOption('businessHours')['endTime'],format);
if ( event_start.isBefore( bh_start ) || event_end.isAfter( bh_end )) {
console.log(' out of busqiness hours');
info.revert();
return false;
}
}

FullCalendar : Ignore events during select

I've created a monthly calendar using fullCalendar month view.
On my calendar, I've displayed only one event per day. This event is used to display user's status (available, not available, busy...)
Because I'll always have 1 event per day, I've set eventLimit to true to avoid multiple events and because this event is about the entire day, I've also set editable to false to prevent events' drag & drop .
Here is my code:
$('#calendar').fullCalendar({
editable: false, // Prevent event drag & drop
events: '/json/calendar', // Get all events using a json feed
selectable: true,
eventLimit: true, // Only 1 event per day
header: {
left: 'prev,next',
center: 'title',
right: 'today'
},
select: function(start, end) {
window.location.hash = '#oModal-calendar'; // Display some popup with a form
end.subtract(1, 'days');
$('#checkboxButton').data('start', start);
$('#checkboxButton').data('end', end);
$('#calendar').fullCalendar('unselect');
}
});
I want my user to be able to select days directly from the calendar so I've set selectable: true in the calendar's option. However, I've got many feedback that "it didn't worked".
After some investigation, I found that users often click on the event block instead of the day.
Because events are draggable by default, a click on an event doesn't trigger the select and because I've set editable to false it doesn't do anything anymore.
This combination leads my users to think that there is a bug.
I would like the fullCalendar select to work like there was no event on the calendar. How can I achieve this behavior ?
Edit: here is a jsfiddle based on full calendar example and my code
I finally found the solution.
FullCalendar event's click is bind to the css class fc-day-grid-event.
It's possible to simply ignore it with one css line pointer-events: none;.
.fc-day-grid-event {
pointer-events: none;
}
Here is the Jsfiddle updated.
One way to do this would be to allow the user to click on event's through the eventClick callback, but when they click on them trigger the "select" function through FullCalendar's API $('#calendar').fullCalendar('select', start, end).
I updated your jsfiddle example with the relevant code.
HTML
<div id="calendar"></div>
Javascript
$('#calendar').fullCalendar({
editable: false, // Prevent event drag & drop
defaultDate: '2015-02-12',
events: [{
title: 'All Day Event',
start: '2015-02-01'
}, {
title: 'Lunch',
start: '2015-02-12T12:00:00'
}],
selectable: true,
eventLimit: true, // Only 1 event per day
header: {
left: 'prev,next',
center: 'title',
right: 'today'
},
select: function (start, end) {
var title = prompt('Event Title:');
var eventData;
if (title) {
eventData = {
title: title,
start: start,
end: end
};
$('#calendar').fullCalendar('renderEvent', eventData, true); // stick? = true
}
$('#calendar').fullCalendar('unselect');
},
eventClick: function(calEvent, jsEvent, view) {
var start = calEvent.start;
var end = calEvent.end;
$('#calendar').fullCalendar('select', start, end);
}
});

FullCalendar overlay doesn't show correct values

Hi I'm using the fullCalendar plugin to display a calendar. In that I have an overlay 'window' that is activated whenever one hover over an object. It display extra information such as location and description of that element.
And it works fine with the original calendar settings and data and with the regular day, week and month views. But I also wan't to create a functionality that removes the weekends and only shows a work week(monday-friday).
I have decided to do this by destroying the calendar and re-initialized it with new default settings(weekends:false) and render the events again. This is a function activated on a button click. And this is where the overlay starts failing. Depending on what I did before I clicked the button it either shows just an empty overlay or the information from whatever object I hovered over before I clicked the button. And therefore displays the same information no matter what object I hover over. Anyone has any inputs to what goes wrong and whether I could change something?
The overlay function:
$scope.overlay = $('.fc-overlay');
$scope.alertOnMouseOver = function( event, jsEvent, view ){
$scope.event = event;
$scope.overlay.removeClass('left right top').find('.arrow').removeClass('left right top pull-up');
var wrap = $(jsEvent.target).closest('.fc-event');
var cal = wrap.closest('.calendar');
var left = wrap.offset().left - cal.offset().left;
var right = cal.width() - (wrap.offset().left - cal.offset().left + wrap.width());
var top = cal.height() - (wrap.offset().top - cal.offset().top + wrap.height());
if( right > $scope.overlay.width() ) {
$scope.overlay.addClass('left').find('.arrow').addClass('left pull-up')
}else if ( left > $scope.overlay.width() ) {
$scope.overlay.addClass('right').find('.arrow').addClass('right pull-up');
}else{
$scope.overlay.find('.arrow').addClass('top');
}
if( top < $scope.overlay.height() ) {
$scope.overlay.addClass('top').find('.arrow').removeClass('pull-up').addClass('pull-down')
}
(wrap.find('.fc-overlay').length == 0) && wrap.append( $scope.overlay );
The buttonclick function:
/*remove weekends from calendar*/
$scope.removeWeekends = function (noWeekend) {
$(".calendar").fullCalendar('destroy');
$(".calendar").fullCalendar({
defaultView: 'agendaWeek',
height: 400,
editable: true,
weekends: noWeekend,
weekNumbers: true,
header:{
left: 'prev',
center: 'title',
right: 'next'
},
dayClick: $scope.alertOnEventClick,
eventDrop: $scope.alertOnDrop,
eventResize: $scope.alertOnResize,
eventMouseover: $scope.alertOnMouseOver
});
$scope.renderAcademy($scope.academy);
$scope.renderCourse($scope.events);
}
The last two functioncalls are just simple forloops that render the elements as:
$scope.renderCourse= function (data) {
for (var j = 0; j < data.length; j++) {
$('.calendar').fullCalendar('renderEvent',{
id: data[j].id,
title: data[j].title,
start: data[j].start,
end: data[j].end,
className: data[j].className,
editable: false,
location: data[j].location,
info: data[j].info
}, true)
}
};
Which actually brings up a little sidequestion: Can anyone explain why it works fine when I call those two functions in this order, but if I call the renderCourse function first, the second seemingly is never called?
Fullcalendar already support the ability to hide weekends by setting the weekends to false.. There is no need for you to destroy/recreate the object
Change:
editable: true,
weekends: noWeekend,
To:
editable: true,
weekends: false
Ok I don't know if anyone would even read this now that it is a few days old but here goes.
I've changed the way that the calendar was initialized from:
$scope.uiConfig = {
calendar:{
height: 450,
editable: true,
weekNumbers: true,
header:{
left: 'prev',
center: 'title',
right: 'next'
},
dayClick: $scope.alertOnEventClick,
eventDrop: $scope.alertOnDrop,
eventResize: $scope.alertOnResize,
eventMouseover: $scope.alertOnMouseOver
}
};
HTML:
<div class="calendar" ng-model="eventSources" config="uiConfig.calendar" ui-calendar="uiConfig.calendar"></div>
To this:
$(document).ready(function() {
$('.calendar').fullCalendar({
height: 450,
editable: true,
weekNumbers: true,
header:{
left: 'prev',
center: 'title',
right: 'next'
},
dayClick: $scope.alertOnEventClick,
eventDrop: $scope.alertOnDrop,
eventResize: $scope.alertOnResize,
eventMouseover: $scope.alertOnMouseOver
})
});
HTML:
<div class="calendar" ng-model="eventSources" id="calendar"></div>
This, unlike the other way, lets me dynamically change values in the calendar options with something like this:
$scope.removeWeekends = function () {
$('.calendar').fullCalendar('getView').calendar.options.weekends=false;
};
But the mouseOver overlay doesn't work at all now. Or it doesn't show anyting. It get's the value from the object because if I for instance hover over a button with a tooltip before one of the calendar object, it works but only shows the same object values for all the events.
The HTML for the overlay:
<div class="panel bg-white b-a pos-rlt">
<span class="arrow"></span>
<div class="h4 font-thin m-b-sm">{{event.title}}</div>
<div class="line b-b b-light"></div>
<div><i class="icon-calendar text-muted m-r-xs"></i> {{event.start | date:'medium'}}</div>
<div class="ng-hide" ng-show='event.end'><i class="icon-clock text-muted m-r-xs"></i> {{event.end | date:'medium'}}</div>
<div class="ng-hide" ng-show='event.location'><i class="icon-pointer text-muted m-r-xs"></i> {{event.location}}</div>
<div class="m-t-sm">{{event.info}}</div>
</div>

Fullcalendar does not Re-render Events when calendar is not visible

I am trying to update my calendar (fullcalendar.js) dynamically, however it is not rerendering the events when the calendar is not visible. I'm also using javascript tabs in my web app so by 'not visible' I mean that it is on a different tab. I've set up a jsfiddle to demonstrate the behavior:
http://jsfiddle.net/35kU5/10/
If you click the Add button while you are on the tab that contains the calendar, the events will be added and immediately visible.
However, if you click the Add button while you are on the second (empty) tab, then switch back to the first tab with the calendar, the 'added' events are not there until you force the calendar to repaint them by some action such as switching the view from week to month, or switching days/weeks/months, then going back.
I've tried the
$("#calendar").fullcalendar('refetchEvents');
$("#calendar").fullcalendar('rerenderEvents');
methods, neither of these solve the issue....Can anyone tell me what I'm doing wrong here? Or is this simply not possible?
Please see the Adam Shaw's full calendar selectable demo. It shows that new events will be added by selecting the date.
The full calendar starts with this code which includes the select event. I use ColdFusion and this is how I retrieve data from my database server:
$myCalendar = $('#myCalendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: ''
},
theme: true,
selectable: true,
selectHelper: true,
height: 500,
events:'events.cfc?method=getevents',
select: function(start, end, allDay) {
alert('select function chosen');
// set the dialog date to the date selected on the calendar
// commented out the dates below when we changed to datetimepicker
// $('#eventStart').val(start);
// $('#eventEnd').val(end);
// added the info below to support the datetimepicker
$('#eventStart').datetimepicker("setDate", new Date(start));
$('#eventEnd').datetimepicker("setDate", new Date(end));
//clear out the contents of the event title and the event id
$('#eventTitle').val('');
$('#ID').val('');
//default the value of all day to halfday value 1,
all day is valued at 2
$('#eventallday').val(1);
$('#calEventDialog').dialog('open');
},...........
Here is the code I use for the select function. This is placed at the bottom of my js code. I reference additional fields you may not use.
var title = $('#eventTitle');
var start = $('#eventStart');
var end = $('#eventEnd');
$('#calEventDialog').dialog({
resizable: false,
autoOpen: false,
title: 'Add Event',
width: 400,
buttons: {
Save: function() {
if ($('input:radio[name=allday]:checked').val() == "1") {
eventClass = "gbcs-halfday-event";
color = "#9E6320";
end.val(start.val());
}
else {
eventClass = "gbcs-allday-event";
color = "#875DA8";
}
if (title.val() !== '') {
$myCalendar.fullCalendar('renderEvent', {
title: title.val(),
start: start.val(),
end: end.val(),
allDay: true,
className: eventClass,
color: color
}, true // make the event "stick"
);
$('calendar').fullCalendar('renderEvent', {
title: ($("#eventTitle").val()),
start: ($("#eventStart").val()),
end:($("#eventEnd").val()),
allDay: ($("#allday").val()),
color:($("background-Color").val())
}, true // make the event "stick"
);
$.ajax({
url: 'events.cfc?method=add_events',
data: 'title='+ ($("#eventTitle").val())+
'&start='+ ($("#eventStart").val()) +'
&end='+ ($("#eventEnd").val()) +
'&id='+ 0 ,
type: "POST",
success: function(json) {
alert('Updated Successfully');
}
})
}
$myCalendar.fullCalendar('unselect');
$(this).dialog('close');
},
Cancel: function() {
$(this).dialog('close');
}
}
});
});// JavaScript Document
I hope this points you in the right direction. Thanks for posting your question. You showed me how to use tabs!.

Categories