In the Full calendar external-dragging events i want to change the description by adding the id of the event inserted in the database with the description while copying the event.
droppable: true, // this allows things to be dropped onto the calendar !!!
drop: function(date, allDay){ // this function is called when something is dropped
// retrieve the dropped element's stored Event Object
var originalEventObject = $(this).data('eventObject');
// we need to copy it, so that multiple events don't have a reference to the same object
var copiedEventObject = $.extend({}, originalEventObject);
// assign it the date that was reported
copiedEventObject.start = date;
copiedEventObject.description = 'custom_event';
copiedEventObject.allDay = allDay;
copiedEventObject.className = $(this).attr("data-class");
var new_date = copiedEventObject.start.format();
var new_event = copiedEventObject.title;
$.post('calendar_action.php',{'action':'create_event','date':new_date,'event':new_event},function(data){
$(copiedEventObject).attr("description",data);
});
// render the event on the calendar the last `true` argument determines if the event "sticks" (http://arshaw.com/fullcalendar/docs/event_rendering/renderEvent/)
$('#calendar').fullCalendar('renderEvent', copiedEventObject, true);
$(this).remove();
},
The $.post method in ajax is not passing the global variable so i used the $.ajax method and its working fine
$.ajax({
type: 'POST',
async: false,
url: "calendar_action.php",
data: {'action':'create_event','date':new_date,'event':new_event},
success: function(data) {
desc = data;
}
});
copiedEventObject.description = desc+'_custom_event';
Related
I have the following markup:
I have a instance of fullcalendar.
When clicking on a day (triggering the dayClick-callback), a bootstrap modal is opened, where the user can enter a title, and the start/end date. Once clicking on ok, those values provided, will be added to the calendar. Here's the code for that:
function addTitle(){ //having a button onClick="addTitle()"
var title = $('#add_date_title').val();
var startdate = $('#add_date_startdate').val();
var enddate = $('#add_date_enddate').val();
var end_split = enddate.split('-');
end_split[2]= parseInt(end_split[2])+parseInt("1");
enddate = end_split[0] + "-" + end_split[1] + "-" + end_split[2];
$('#add_date_title').val('');
$('#add_date_startdate').val('');
$('#add_date_enddate').val('');
$('#add_date_modal').modal('hide');
var myCalendar = $('#calendar');
var myEvent = {
title:title,
allDay: true,
start: startdate,
end: enddate
};
myCalendar.fullCalendar( 'renderEvent', myEvent );
}
So the event is now in the calendar. But when e.g. switching the month, or reloading the page, all data is lost, of course, because it's saved nowhere.
Now the question is: How could I save the event directly into the database, and then load it, so where can I bring in php code, to save the event to a db... The problem, why I'm asking, is that the site in between adding events is never reloaded, so I'm not able, to check for GET or POST-Parameters or something similiar... Could I maybe do this with AJAX? If yes, how? Because I'm not really familiar with AJAX.
You can actually save the events in DB.
Use this ajax after your modal trigger.
Get the values like title,startdate, end date in modal and send them in the following ajax
$.ajax({
url: 'add_events.php',
data: 'title='+ title+'&start='+ start2 +'&end='+ end2,
type: "POST",
success: function(json) {
$( "#getReason" ).modal('hide');
$('#mydiv').hide();
$('body').removeClass('blockMask');//calendar.fullCalendar( 'refetchEvents');
$('#calendar').fullCalendar('refetchEvents');
}
});
in add_events.php save the details in db
In your main page use this method for dynamically creating event source
function eventSourceCall(){
eventSourceCall = [
{
url: 'events.php?status=absent',
backgroundColor: 'red',
borderColor: 'white',
textColor: 'white',
rendering: 'background',
cache: false
}
in events.php perform a select operation and retrieve the event parameters as json encoded objects and return them.
In calendar function eventSources: eventSourceCall, add this line for selecting the event source.
I am trying to update my db with the updated start date of an event I drag to a new day. I have a save button that runs the 'clientEvents' method to return all events to insert/update to the db. My problem is returning the correct event start date when an event that has been dragged to a new day.
I am doing this so far to update the event data:
$('#calendar').fullCalendar({
eventDrop: function(event, delta, element) {
event.title = "NEW TITLE!";
event.start = event.start.format();
event.color = "blue";
console.log(event.start.format());
console.log(event.start);
console.log(event.start._i);
console.log(event.title);
console.log(event.color);
$('#calendar').fullCalendar('updateEvent', event); //update the event data
}
})
and my function to return all the events:
function saveEvents() {
//get events array
var events = $('#calendar').fullCalendar('clientEvents');
console.log(events);
}
However, using this code, the title and color update fine but the start date will not update. Using console.log, the new title and color return correctly, but the start date is the original date, not the new date the event was dragged to. The same for the event data returned in my saveEvents function: the new title and color are correct, but not the start date.
The strange thing is, in the 3 ways I log the event.start, only the event.start.format() shows the correct new date. How do I get the new date saved so when a call 'clientEvents', the correct new data is returned?
Could you explain what you mean by "original date" compared to what should be the "new date" ? Because you don't seem to update your start date as you only modify its format.
Create a moment copy of start, format it and attach to new event. Put your ajax call in the eventDrop callback in initialization of fullCalendar. Example solution using php and mysql:
$('#calendar').fullCalendar({
eventDrop: function(event, delta, element) {
var event_format = event;
event_format.start = moment(event.start).format();
$.ajax({
url : "script.php",
data : event=JSON.stringify(event_format),
type : "POST"
});
}
})
php:
<?php
$event = json_decode($_POST['event']);
$query = "UPDATE x SET start = '$event->start'";
mysql_query($query) or die ($query);
?>
Doing the same for the enddate would be a good idea :)
I'm a bit lost where is the proper place to make this with the Full Calendar documentation and need some fiddle to point me into the right way. When my calendar loads the events, before them show up on the calendar, I need to make a ajax call into a wordpress db which should return a date of a post. Each post is an event on the calendar. Depending on the response of the database, if the post date is in future time than the current time, then the calendar should show this event in an specific color, if it is past or current time it should be another different specific color.
So basically, before each event renders on the calendar I need to trigger an ajax call for each of them and evaluate the data returned to apply them the right color for past/current events and future events.
Someone experienced with Full Calendar could point me a fiddle with an example how is this done within the Full Calendar documentation?
This is the code I went so far. I am looking to stay in the loop with the calendar refetchEvents and be able to fetch with ajax in the background data from the posts of a WordPress website to use it on the next refetchEvents trigger and so on.
$(function () {
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
var webData = null; //array() data
$('#calendar-holder').fullCalendar({
eventRender: function(event, element, webData) {
var dataHoje = new Date();
/*
Use webData data taken with ajax on eventAfterAllRender callback option
inside this conditional statements to draw on the event box
colors and text values depending on the status and date of the post returned.
*/
if (event.start < dataHoje && event.end > dataHoje) {
element.css('background-color', '#FFB347');
element.find('.fc-event-inner').append('<span class="fc-event-status">ON AIR</span>');
} else if (event.start < dataHoje && event.end < dataHoje) {
element.css('background-color', '#77DD77');
element.find('.fc-event-inner').append('<span class="fc-event-status">Published</span>');
} else if (event.start > dataHoje && event.end > dataHoje) {
element.css('background-color', '#AEC6CF');
element.find('.fc-event-inner').append('<span class="fc-event-status">Schedued</span>');
}
},
eventAfterAllRender: function () {
webData = '(AJAX CALL TO WEBSITE POSTS I THINK SHOULD GO HERE)';
console.log(webData);
},
eventColor: '#378006',
complete: function() {
},
defaultView: 'basicDay',
googleCalendarApiKey: 'AIzaSyCtEQZsFtsY41kJ1Av5FftgX9kdfkHKH',
events: {
googleCalendarId: 'mywebsite.com_l84tadr5fulc7j0628g3g6oj3k#group.calendar.google.com'
},
header: {
left: 'prev, next',
center: 'title',
right: 'basicDay, basicWeek, month, '
},
lazyFetching: true,
timeFormat: {
agenda: 'h:mmt', // 5:00 - 6:30
'': 'h:mmt' // 7p
},
weekNumbers: false,
lang: 'en',
eventSources: [
{
url: Routing.generate('fullcalendar_loader'),
type: 'POST',
data: {
},
error: function() {
}
}
]
});
});
var refreshRate;
function reloadTime() {
refreshRate = setTimeout(reloadPage, 5000);
}
function reloadPage() {
$("#calendar-holder").fullCalendar("refetchEvents");
reloadTime();
}
$( document ).ready(function() {
reloadTime();
});
Changing the color:
The way you did it works, but the easiest way is to do it in eventDataTransform. Like so:
eventDataTransform: function(eventData){
if(eventData.end.isBefore(moment())){
eventData.color = "black";
}else{
eventData.color = "green";
}
return eventData;
},
Color Demo
Check if event exists
You didn't mention exactly what to do if the database returns false, but I'll assume you don't want nonexistent events rendered.
Since the source for your events is google calendar, this is actually kind of tricky. Normally, you would use the custom events function and do two ajax calls in it (one for the events and one for checking if they are valid). But you can't do this with google cal events.
So instead we will use eventDataTransform and only display the events after we know they exist.
eventDataTransform: function(eventData){
eventData.display = false; //Don't display until we check the server
eventData._uid = idCounter++; //unique ID. Don't need this if they already have unique IDs
ajaxCall(eventData); //check the server (will retroactively update the event to be displayed)
if(eventData.start.isBefore(moment())){ /*...*/ } //colors
return eventData;
},
The top of your eventRender callback should look like:
eventRender: function(event,element){
if(!event.display){ //Render only if the event exists
return false; //return false to stop the event from rendering.
}
/*...your other render code if you have any*/
}
Define your ajaxCall function outside of fullcalendar:
var ajaxCall = function(eventData){
$.get( "ajax/test.html", function( data ) {
setEvent(eventData._uid,data); //data should be a boolean
});
};
var setEvent = function(id,exists){
var fcEvent = $('#calendar').fullCalendar("clientEvents",function(event){ //get the associated event object
if(event._uid === id){
return true;
}
})[0];
if(typeof fcEvent !== "object")$.error("Event id "+id+" doesn't exist!"); //Throw error if it doesn't exist
fcEvent.display = exists; // Store the server response in the event
$('#calendar-holder').fullCalendar("updateEvent",fcEvent); // Updates and re-renders the event
}
JSFiddle Demo (using fake ajax calls)
Some Explanation
Couple of things that might be useful to know:
The word render in fullcalendar refers to actually displaying the events. It's done whenever the view changes (more often than events are fetched from the DB)
Event sources only fetch events when they are needed. They are stored client-side as data that can be rendered as needed.
eventDataTransform is called once after an event source retrieves an event.
So if you put your ajax call in eventAfterAllRender, the ajax call would be done everytime FC decided to render the calendar resulting in more ajax calls that necessary. It also means you would get a delay every time you change the view. It's much better to do it earlier than render-time.
I have the following js:
!function ($) {
$(function(){
// fullcalendar
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
var addDragEvent = function($this){
// create an Event Object (http://arshaw.com/fullcalendar/docs/event_data/Event_Object/)
// it doesn't need to have a start or end
var eventObject = {
title: $.trim($this.text()), // use the element's text as the event title
className: $this.attr('class').replace('label','')
};
// store the Event Object in the DOM element so we can get to it later
$this.data('eventObject', eventObject);
// make the event draggable using jQuery UI
$this.draggable({
zIndex: 999,
revert: true, // will cause the event to go back to its
revertDuration: 0 // original position after the drag
});
};
$('.calendar').each(function() {
$(this).fullCalendar({
header: {
left: 'prev,next',
center: 'title',
right: 'today,month,agendaWeek,agendaDay'
},
editable: true,
droppable: true, // this allows things to be dropped onto the calendar !!!
drop: function(date, allDay) { // this function is called when something is dropped
// retrieve the dropped element's stored Event Object
var originalEventObject = $(this).data('eventObject');
// we need to copy it, so that multiple events don't have a reference to the same object
var copiedEventObject = $.extend({}, originalEventObject);
// assign it the date that was reported
copiedEventObject.start = date;
copiedEventObject.allDay = allDay;
// render the event on the calendar
// the last `true` argument determines if the event "sticks" (http://arshaw.com/fullcalendar/docs/event_rendering/renderEvent/)
$('#calendar').fullCalendar('renderEvent', copiedEventObject, true);
// is the "remove after drop" checkbox checked?
if ($('#drop-remove').is(':checked')) {
// if so, remove the element from the "Draggable Events" list
$(this).remove();
}
}
,
events: [
],
eventClick: function(event) {
alert('win');
}
});
});
getEvents();
});
}(window.jQuery);
function getEvents()
{
$.ajax({
type: 'POST',
url: '/Calendar/findEvents',
dataType: 'json',
data: {
request: 'ajax'
},
success: function (data)
{
if(data.length > 0)
{
for (index = 0; index < data.length; ++index)
{
var d = new Date(data[index]['end']);
if(data[index]['is_online'] === 1)
{
var myevent = {title: 'Forløb: '+data[index]['academy_name'].toUpperCase()+' \n Modul: '+data[index]['module_name']+ '\n Type: E-learning',start: new Date(d.getFullYear(), d.getMonth(), d.getDate())};
}
else
{
var myevent = {title: 'Forløb: '+data[index]['academy_name'].toUpperCase()+' \n Modul: '+data[index]['module_name']+ '\n Type: Kursus'+ '\n Lokation: '+data[index]['location']+'\n Underviser: '+data[index]['mentor'],start: new Date(d.getFullYear(), d.getMonth(), d.getDate())};
}
$('.calendar').fullCalendar( 'renderEvent', myevent, true);
}
}
}
});
}
As you can see when the calendar is loaded i am starting to load events (through ajax) into the calendar.
Now what i want to do is simply add an eventListner on each of the elements.
In the documentation it sates the following:
eventClick: function(event) {
if (event.url) {
window.open(event.url);
return false;
}
}
Which i attempted with just a simple alert (as you can see in the code:
eventClick: function(event) {
alert('win');
}
However when i click my items nothing happens.
Can anyone tell me what i am missing?
I know you are loading events through AJAX, but have you tried returning an array of objects (the events) to the events array in your instantiation of the calender? Right now you are passing an empty array, so the plugin is not assigning any elements as 'events', and thus isn't assigning any click handlers.
events: [ getEvents()
],
eventClick: function(event) {
alert('win');
}
});
And then inside your getEvents() function call, rather than render the events, you should just return the event objects.
The suggested way to load events with an ajax call + some manipulation on the data you receive is to use your function as an event source (link to the doc) :
$(this).fullCalendar({ ...
events: function(start, end, tz, callback) {
$.ajax({
type: 'POST',
url: '/Calendar/findEvents',
dataType: 'json',
data: {
request: 'ajax'
},
success: function (data) {
// build an array of event objects with the data
var events = ...
// use the "callback" argument to load them in the grid :
callback(events);
}
});
},
...
});
note : the signature of the function depends on the version of fullcalendar you are using. Versions prior to version 2.0 do not have the tz argument (again, check the doc).
FullCalendar is processing your listeners with no events. Your ajax is loaded after the initialization of your calendar. You could keep your current code and add the listener on eventRender.
$('#calendar').fullCalendar({
eventRender: function(event, element, view){
element.click(function(){
alert('test');
})
}
});
I would probably suggest loading the events as suggested in the other answers though, but this should work.
$('#calendar').fullCalendar({
eventRender: function(event, element, view){
element.click(function(){
alert('test');
});
$("#calendar .fc-helper-container").find("a").remove();
}
});
I can't believe nobody asked this. This is driving me insane. Im using FullCalendar to let the user drop external events to the calendar. I´m folliwing the well known approach:
$('#external-events div.external-event').each(function () {
var eventObject = {
type: 2,
id: $(this).attr("data-id"),
title: $(this).attr("data-name"),
duration: $(this).attr("data-duration"),
guid: $(this).attr("data-guid"),
color: $(this).attr("data-color")
};
// store the Event Object in the DOM element so we can get to it later
$(this).data('eventObject', eventObject);
// make the event draggable using jQuery UI
$(this).draggable({ zIndex: 999, revert: true, revertDuration: 0 });
});
My calendar is configured like this (drop event):
drop: function(date) {
// retrieve the dropped element's stored Event Object
var originalEventObject = $(this).data('eventObject');
// we need to copy it, so that multiple events don't have a reference to the same object
var copiedEventObject = $.extend({}, originalEventObject);
// assign it the date that was reported
copiedEventObject.start = date.format();
// render the event on the calendar
//$('#calendar').fullCalendar('renderEvent', copiedEventObject, true);
$.ajax({
async: false,
url: '#Url.Action("AddWorkoutToPlan", "Planning")',
data: { 'planId': planId, 'workoutId': copiedEventObject.id, 'date': date.format() },
success: function(data) {
$('#calendar').fullCalendar('refetchEvents');
}
});
},
As you can see, I don't render the event, I just make an ajax call and on success I refetch the events so I can get the DB id, in case the user wants to remove it.
This is how I get my events:
events: {
url: '#Url.Action("GetPlannedActivities", "Planning")',
data: function() { return { planId: '#Model.Id' } },
beforeSend: function(xhr, opts) {
if (!$("#selectedPlan").val()) {
xhr.abort();
unblockContainer($("#calendar"));
}
},
success: function(data) {}
},
This is working nice, but if the user moves from the current month, then the external events wont drag nor the drop callback is triggered... I don't know what is going wrong...
Any ideas?
Finally I rolled back the FullCalendar version from 2.1.0_BETA1 / BETA2 to v2.0.2 and now is working as expected.
So I guess this is a bug in the new version that uses DIVS instead of TABLES.