In a previous article we learn how to make use of FullCalendar JavaScript framework to display calendar events.
Now let’s step it a step further and the ability to filter and search for events. We will be filtering events base on their types, and search for events that contains the search terms in the event name and description. To achieve this goal, we will need to do the following:
- Create a function to retrieve the event types
- Create the calendar display page with filter selection and search box
- Add the JavaScript to retrieve and render filtered events
Function to retrieve event types
Create a ColdFusion component events.cfc and inside this component add the following code which will retrieve the event types (we will assume you already have a table that stores the event types)
<cfcomponent>
<cffunction name="getEvents" output="no" access="remote" returntype="any" returnformat="json">
<cfscript>
var q=new query();
var results = [];
var qResults = "";
var dDiff = [];
q.setDatasource(<your-event-ds>);
q.setSQL("
SELECT events_id AS eventID, eventTitle AS title,
eventDesc AS [desc], startDate AS [start], endDate AS [end],
isAllDay, t.[name] AS type, eventURL AS url
FROM events e
INNER JOIN evTypes t on e.evType_id = t.evType_id
");
q.addParam(name="isApproved",value="true", CFSQLTYPE="CF_SQL_BIT");
qResults=q.execute().getResult();
for (var i=1; i<= qResults.RecordCount; i++) {
event = {};
event["id"] = qResults.eventID[i];
event["title"] = qResults.title[i];
event["desc"] = qResults.desc[i];
event["type"] = qResults.type[i];
event["url"] = qResults.url[i];
event["start"] = '#LSDateFormat(qResults.start[i],"yyyy-mm-dd")#T#LSTimeFormat(qResults.start[i],"hh:mm:ss")#';
event["end"] = '#LSDateFormat(qResults.end[i],"yyyy-mm-dd")#T#LSTimeFormat(qResults.end[i],"HH:mm:ss")#';
if (qResults.isAllDay[i] neq ""){
event["allDay"] = iif(qResults.isAllDay[i] eq 1, DE("True"),DE("False"));
}
else {
event["allDay"] = "False";
}
ArrayAppend(results,event);
} //for
return serializeJSON(results);
</cfscript>
</cffunction>
<cffunction name="getEventTypes" output="no" access="public" returntype="query">
<cfscript>
var qGet = "";
var qService = new query();
var qResults = "";
qService.setDatasource(<your-event-ds>);
qService.setName("qGet");
qService.setSQL("SELECT [name] FROM eventTypes WHERE isActive = 1 ORDER BY [name]");
qResults = qService.execute().getResult();
return qResults;
</cfscript>
</cffunction>
</cfcomponent>
Create the calendar display with filters and search
Now let’s create the front-end calendar event display page. Create a new file called events.cfm and enter the following code:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Calendar Events</title>
<link rel="stylesheet" href="/path/to/fullcalendar/3.9.0/fullcalendar.min.css" type="text/css" />
<link rel="stylesheet" href="/path/to/bootstrap/bootstrap-3.1.1//css/bootstrap.min.css" type="text/css" />
<script src="/path/to/fullcalendar/3.9.0/lib/moment.min.js"></script>
<script src="/path/to/jquery/jquery.min.js"></script>
<script src="/path/to/bootstrap/bootstrap-3.1.1/js/bootstrap.min.js"></script>
<script src="/path/to/fullcalendar/3.9.0/fullcalendar.min.js"></script>
<script src="/path/to/events.js"></script>
</head>
<body>
<cfsilent>
<cfscript>
oEvents = createobject("component","#request.cfcPath#.events");
qTypes = oEvents.getEventTypes();
</cfscript>
</cfsilent>
<div class="container">
<div class="row">
<div class="col-md-12">
<div id="filters">
<form class="form-inline">
<div class="col-md-3">
<label class="sr-only" for="searchTerm">Search</label>
<input type="text" id="searchTerm" name="searchTerm" class="form-control control-label" placeholder="Type search terms">
</div>
<div class="col-md-3">
<select class="form-control filter" id="eventType" name="eventType">
<option value='all'>All Types</option>
<cfloop query="qTypes">
<option value="#qTypes.name#">#qTypes.name#</option>
</cfloop>
</select>
</div>
</form>
</div><!--- filters --->
</div><!--- col --->
</div><!--- row --->
<div class="row">
<div class="col-md-12">
<div id="calendar"></div>
</div>
</div><!--- row --->
</div><!--- container --->
</body>
</html>
Add JavaScript to retrieve and render filtered events
Let’s add the JavaScript that will retrieve and render the filtered events based on user inputs. Create a new JavaScript file called events.js and add the following code:
$( document ).ready(function(){
$('#calendar').fullCalendar({
firstDay: 1,
fixedWeekCount: false,
header: {
left: 'month,agendaWeek,agendaDay',
center: 'title',
right: 'prevYear,prev,next,nextYear'
},
events: {
url: '/events/calendar/show/events.cfc?method=getEvents&returnformat=json',
type: 'POST',
error: function() {
alert('there was an error while fetching events!');
},
success: function(res){
console.log('success!');
}
}, //events
eventRender: function eventRender( event, element, view ) {
var showTypes, showFacilities, showSearchTerms = true;
var types = $('#eventType').val();
var searchTerms = $('#searchTerm').val();
/* filters */
if (searchTerms.length > 0){
showSearchTerms = event.title.toLowerCase().indexOf(searchTerms) >= 0 || event.desc.toLowerCase().indexOf(searchTerms) >= 0;
}
if (types && types.length > 0) {
if (types.trim().toLowerCase() == "all") {
showTypes = true;
}
else {
showTypes = types.indexOf(event.type) >= 0;
}
}
return showTypes && showSearchTerms;
} //end: eventRender
}); //calendar
$('.filter').on('change',function(){
$('#calendar').fullCalendar('rerenderEvents');
});
$('#searchTerm').on('input', function(){
$('#calendar').fullCalendar('rerenderEvents');
});
}); //document.ready
The calendar events will be re-rendered when a selection is made on the event type drop down or text entered in the search box, and will only display events that satisfy the filter inputs.