selecting a day from UICalendar - javascript

I am fairly new to angular I am trying to implement a calendar using ui-calendar. So far I have been able to display a very basic calendar and some events on it.
Now I need to be able to click on a day and display the detailed events on a side tab. I seem to be lost on how to achieve this clicking day thing. This may seems very naive, I thought i'd find the html for each day cell on the calendar, and then it would be as easy as attaching a ng-click to it. But I cant seem to find any template where the html for calendar is. All I can see is the directive, which doesnt help much. I dont understand jquery at all, so I am really struggling to find any answers too.
To sum things up, I just want to know how to make a day on calendar clickable.
Thanks in advance.
code:
$scope.uiConfig = {
calendar: {
height: 450,
editable: true,
header: {
left: 'title',
center: '',
right: 'today prev,next'
},
eventClick: $scope.alertOnEventClick,
eventDrop: $scope.alertOnDrop,
eventResize: $scope.alertOnResize,
eventRender: $scope.eventRender,
dayClick: function(date, jsEvent, view) {
console.log("inside dayClick");
alert('Clicked on: ' + date.format());
var events = myCalendar.fullCalendar('clientEvents', function(event) {
return event.start.isSame(date) || event.end.isSame(date) || date.isBetween(event.start, event.end); // Will return all events starting/ending on this date or overlapping this date
});
}
}
};

In your configuration variable you can add a dayClick callback , in this callback you can do something like this:
dayClick: function( date, jsEvent, view ) {
var events = myCalendar.fullCalendar('clientEvents', function(event) {
return event.start.isSame(date) || event.end.isSame(date) || date.isBetween(event.start, event.end); // Will return all events starting/ending on this date or overlapping this date
});
}
This will return all the events that either are on this day or overlap it.
FullCalendar docs can be found here.

Related

Fullcalendar external drag & drop does not work correctly

I am trying to implement a Fullcalendar functionality like so: an external event is dragged to the calendar, then the event is saved to the database via ajax, with its title, start and end dates.
I did achieve making the event title and start date/time to be saved to the DB, however I cannot fix the following couple of issues:
Currently, the end date/time saved to the DB is the same as the start date/time.
How do I make the end date to be 24h after the start date for all day events?
How do I get the exact start and end dates for a fixed duration event?
Once the event is dragged and saved to the DB, I cannot drag-drop any more events until I hit F5
My HML is the following:
<div id='external-events'>
<div class="fc-events-container">
<div>All Day Events</div>
<div class='fc-event' data-color='#28A745'>All Day Event</div>
<div>Fixed Duration Events</div>
<div class='fc-event' data-color='#50C1E9'>Event From 8am till 5 pm</div>
</div>
</div>
JQuery:
$('#external-drag').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
editable: true,
droppable: true,
defaultDate: new Date(),
selectable: true,
events: "../../ajax/get_events.php",
drop: function( date, allDay, jsEvent, ui ) {
var start = date.format();
var end = date.format();
var title = $.trim($(this).text());
$.ajax({
url: '../../ajax/add_event.php',
data: 'title='+ title+'&start='+ start +'&end='+ end,
type: "POST",
success: function(json) {
alert('Added Successfully');
},
error: function() {
alert('Error');
}
});
calendar.fullCalendar('renderEvent',
{
title: title,
start: start,
end: end,
allDay: allDay
},
true
);
}
});
Firstly, some background context to what you're experiencing: although you've labelled your second event as "from 8 to 5pm", that has no actual practical effect. If you drop either of your draggable items onto a time-aware calendar view (e.g. week view) then it will gain a start date and time. On a view such as month, which has no concept of specific times of day, then it will just gain a start date, without a time attached.
However in both cases, there is no end date. Once you add the event to the calendar via renderEvent, then fullCalendar will assign it a default duration (as per the
defaultAllDayEventDuration or defaultTimedEventDuration settings, as appropriate). You can use that to work out the notional end date (although the event object doesn't actually have its end property set unless you set forceEventDuration to true).
Now to a solution:
If you want to control it so that specific dragged items have pre-defined times, you would have to specify the time data in the data- properties of the relevant draggable items. Then you need to get those values in your drop callback, the same way as you do with the title, and use them when creating your event.
It took a bit of fiddling to get to this point, especially with the moment objects, but it now appears to do what you want - as far as I understand it.
drop: function(date, jsEvent, ui) {
var element = $(this);
var title = $.trim(element.text());
var color = element.data("color");
var start = moment(date.format()); //lose the extended fullCalendar moment with its "ambiguously-timed" feature, which gets in the way here
var end = start.clone();
var allDay = true;
console.log(start.format(), end.format());
if (typeof element.data("starttime") !== 'undefined') {
//timed events
var starttime = moment.duration(element.data("starttime"));
var endtime = moment.duration(element.data("endtime"));
start.set({ "hour": starttime.hours(), "minute": starttime.minutes()});
end.set({ "hour": endtime.hours(), "minute": endtime.minutes()});
allDay = false;
console.log(starttime.hours());
} else {
//allday events
end.add({ days: 1 });
}
console.log("title=" + title + "&start=" + start.format() + "&end=" + end.format());
$.ajax({
url: '../../ajax/add_event.php',
data: 'title='+ title+'&start='+ start.format() +'&end='+ end.format(),
type: "POST",
success: function(json) {
alert('Added Successfully');
},
error: function() {
alert('Error');
}
});
calendar.fullCalendar(
"renderEvent",
{
title: title,
start: start,
end: end,
color: color,
allDay: allDay
},
true
);
}
Demo: https://codepen.io/ADyson82/pen/GRRXwRL?editors=1010
N.B. Note that if a user drags an event onto a time-aware view like the week view, it will still create the events exactly as per the settings in the draggable, and will ignore whatever time of day they dropped it on. It's possible this could be confusing or irritating to some users - but I guess it depends what you're trying to achieve exactly.
P.S. I don't know where you got the idea that the drop callback has an allDay parameter. It's clearly not there in the documentation. You can't use that, so I've removed it in my version.

fullcalendar: display all events of a specific day when hovering his daycell

I'm developing a Calendar application via fullcalendar.
I'm currently working on a mini sized calendar. The mini calendar will not display the events.
I'm trying to use tooltip instead. so when the user will mouseover a specific daycell - all the events of the specific daycell will be displayed via tooltip. (this is my issue)
I been working on this issue for almost two days now.
unfortunately, full calendar only offers "eventMouseover". (no dayMouseover available).
Also, using $(".fc-day").hover is not really the best way to go because it is working only when hovering the bottom of the cell.
there is no documentation for this on the web so far.
Anybody knows which is the best way to Tackle an issue?
here is my code so far:
$("#miniCalendar").fullCalendar({
defaultDate: currentDate,
viewRender: function (view, element)
{
monthStart = view.intervalStart.format("YYYY-MM-DD");
monthEnd = view.intervalEnd.subtract(1, "days");
monthEnd = view.intervalEnd.format("YYYY-MM-DD");
mStart = view.intervalStart.format("M");
yStart = view.intervalStart.format("YYYY");
},
events: function (start, end, timezone, callback) { //custom events function to be called every time the view changes
$.ajax({
url: getMonthDataUrl,
type: "post",
data: {
startDate: monthStart,
endDate: monthEnd,
custom_config: Config
},
error: function () {
//alert("there was an error while fetching events!");
},
success: function (data) {
calendarData = data;
console.log(calendarData);
thingsToDoAfterWeLoadCalendarData(calendarData);
callback(eventsJsonArray); //pass the event data to fullCalendar via the supplied callback function
}
});
},
fixedWeekCount: false,
dayRender:
function (date, cell) {
//the events are loaded vie eventAfterAllRender function
//eventAfterAllRender takes time to load. so we need dayRender function in order to give the calendar default colors until the real colors are loaded
// the default colors spouse to look like the correct colors. this is needed for a better looking calendar while loading new events
if (!cell.hasClass("fc-other-month")) {
//that means this is a cell of this current month (becuase only cells that belong to other month have the "fc-other-month" class
var weekDay = date.format("dddd");
if (weekDay == "Saturday" || weekDay == "Friday") {
cell.css("background-color", "#edf5f9");
} else{
//regular days
cell.css("background-color", "#f7fafc");
}
} else{
//cells that belong to the other months
$(".fc-other-month").css("background-color", "#ffffff");
}
},
eventAfterAllRender:
(function(view, event, element) {
let viewDisplay = $("#miniCalendar").fullCalendar("getView");
if (viewDisplay.name == "month") { //checking if this the month view. this is needed for better display of the week\day view (if we ever want to use it)
$(".fc-day:not(.fc-other-month)").each(function(index, element) {
//loop through each current month day cell
$(this).empty(); //removing old icons in case they are displayed
let cellDate = moment($(this).data("date")).format("YYYY-M-D"); // "YYYY-M-D" date format is the key in the json_backgrundColorBigCalendar array
$(this).css("background-color", json_backgrundColorBigCalendar[cellDate]); //set the background colour of the cell from the json_backgrundColorBigCalendar array.
});
}
$(".fc-other-month").css("background-color", "#ffffff"); //days that belong to other month gets a color background that will show this days are irrelevant
}),
dayClick: function(date, jsEvent, view) {
window.location = fullCalendarUrl;
},
});
I dont really know if there is a "fullcalendar-way" doing this, but why can't you use your hover event listener and just also let it listen on fc-day-top hover?
$(".fc-day, .fc-day-top").hover(function(e) {
console.log($(e.currentTarget).data("date"));
});
This will also work if you hover the top of a day cell.
Update:
To get the events on hover use this:
var $calendar = $("#calendar");
$(".fc-day, .fc-day-top").hover(function(e) {
var date = moment.utc($(e.currentTarget).data("date"));
var events = $calendar.fullCalendar("clientEvents", function(event) { return event.start.startOf("day").isSame(date); });
console.log(events);
});
(Tested on the calendar on the fullcalendar main site).
Of course you have to change the jQuery selector of the calendar (#calendar) as it is in your code.
I've never seen full calendar before, but if I understand correctly you want to bind a hover function to custom days of the calendar. Is that correct?
If so you can simply select days of the calendar with their "data-date" attribute. So something like the code below would let you specify a hover function for a desired day:
$("[data-date='2017-10-10']").hover(function(e) {
console.log("You moused over 10/10/2017!");
});

Affecting Fullcalendar today button .fc-today-button

I'm having trouble getting custom controls to work when clicking the 'today' button that is part of Fullcalendar.
All the documentation I can find tells me that Fullcalendar's built-in controls can be affected using two methods:
So, this one works for me when it's applied to previous, next, month, agendaWeek and agendaDay, but not for 'today' (button.fc-today-button):
$('body').on('click', 'button.fc-next-button', function() {
console.log('I Clicked Next');
});
Some documentation also say that this works, although I can't make it do so on any button:
$('.fc-next-button span').click(function(){
console.log('I Clicked Next');
});
Does anyone know why this is and what I'm doing wrong?
Well, you want to affect the "today" button, yet you are adding code for the "next" button. You want to do something like:
$(".fc-today-button").click(function() {
alert('Clicked Today!');
});
This applies a click event to anything with the class "fc-today-button" (that is the class that the Today button will have).
Working example:
$('#fullCal').fullCalendar({
events: [{
title: 'Event 1',
start: moment().add(1, 'h'),
end: moment().add(2, 'h'),
allDay: false
}],
header: {
left: '',
center: 'prev title next today',
right: ''
},
timezone:'local',
defaultDate: '2014-11-15',
editable: false,
eventLimit: false,
firstDay: 6,
defaultView: 'agendaWeek',
});
$(".fc-today-button").click(function() {
alert('Clicked Today!');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.3/moment.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/2.1.1/fullcalendar.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/2.1.1/fullcalendar.min.js"></script>
<div id="fullCal"></div>
After investigation and the help of MikeSmithDev (thanks Mike - your help was invaluable), it appears as though the 'today' event only gets triggered if it physically positioned below/after the calendar, the rest of the header controls (button.fc-next-button etc) don't seem to mind where they are physically positioned.
Likely the first function executes before the calendar is finished loading... so it works, there is just no button to bind it to.
I was able to more or less achieve this with a native workaround of sorts. You may utilize the "customButtons" and "headerToolbar" in combination to effectively remove the original today button and replace it with your own which can trigger custom function code upon being clicked.
I'm actually using this with VueJS, but should be equally feasible with Vanilla JS.
// these are the options you can pass when initializing a fullcalendar
customButtons: {
focusButton: {
text: "focus",
click: this.scrollToCurrentDay // this is a vue component function, but you could just as well pass a vanilla JS function
}
},
headerToolbar: { // this effectively removes the original today button and adds our custom button to the header of the calendar
left: '',
center: 'title',
right: 'prev focusButton next'
}
I wanted to do this because I wanted to not only focus the month when today was clicked, but also to scroll the calendar to the day (useful when using small screens like phones).
My custom today button click handler:
scrollToCurrentDay: function(arg) {
let CalendarAPI = this.$refs.calendar.getApi();
CalendarAPI.today();
var todayElement = document.getElementsByClassName('fc-day-today')[0];
var calendarElement = document.getElementsByClassName('fc')[0];
if (todayElement) {
todayElement.scrollIntoView();
} else {
calendarElement.scrollIntoView();
}
},

Get events clicking a day in FullCalendar

I want to know if is possible to get a list or array or something with events of one day by clicking that day in fullcalendar.
Now I get the events from google calendar, if I need to make a query each time I want to get events of one day, it will be so hard for connections. I guess it has to be possible since you already have the events for rendering them.
One user ask me for code:
dayClick: function(date, allDay, jsEvent, view) {
console.log(date);
console.log(allDay);
console.log(jsEvent);
console.log(view);
if (allDay) {
// alert('Clicked on the entire day: ' + jsEvent);
}
},
eventClick: function(event) {
if (event.url) {
return false;
}
}
I can't understand why someone voted me negative. I made a question, someone ask for code, I put code but I EXPLAINED why I have no more code, and -1 vote? I can't understand it.
I think you could do something like
dayClick: function(date, allDay, jsEvent, view) {
var dayEvents = $('yourSelector').fullCalendar( 'clientEvents' function(event){
return event.start.setHours(0, 0, 0, 0) === date.setHours(0, 0, 0, 0);
//or some way to compare that is the same day
//I recommend momentjs lib ex moment(event.start).isSame(date,'day')
});
}
What I suggest is to query the client events and filter it checking if its the same day

How do I remove events from an array datasource in fullcalendar?

I'm using fullcalendar to allow people to select multiple days. If they make a mistake, they can click the event to remove it.
Here's where I am:
var eventArray = new Array();
var cal = $('#new-show-calendar');
cal.fullCalendar({
height: 250
,events: eventArray
,dayClick: function(date, allDay, jsEvent, view) {
var stringDate = date.toString();
e = { title: "Some Title", start: stringDate }
eventArray.push(e);
cal.fullCalendar( 'renderEvent', e );
}
,eventClick: function(event, jsEvent, view) {
eventArray.splice(eventArray.indexOf(event), 1);
cal.fullCalendar( 'removeEvents', event._id );
}
})
This line gives semi-unpredictable results
cal.fullCalendar( 'removeEvents', event._id );
I've tried rerenderEvents (which doesn't do anything) and a few other things. I'm trying to avoid cleaning out all the events then re-rendering each event individually for performance reasons.
I assume this is a bit of wonkiness around having a local, array-based datasource as opposed to a json source somewhere else.
EDIT: This code (above) works as long as the view doesn't change. If I remove some things, then switch months, new events no longer persist on the calendar across views.
How can I remove an event from the calendar?

Categories