1
votes

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();
});
1

1 Answers

4
votes

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.