Hey everyone,
I’ve been mucking around with FullCalendar recently and decided to share one of the prototypes I’ve ended up with. It basically lets the user change the events without having to do a postback. A user simply has to click the event, type in the changes and hit update.
I’ve posted the code below, however there’s also a zip which is a little easier to manage. Note that you’ll probably want to clean it up a little if you plan to use it in production. The following libraries and plugins are also used:
– jQuery
– jQuery UI
– jQuery FullCalendar
– jQuery miniColors
What it Looks Like:
Full Calendar Example with Client Side Edits
How to Use It:
It’s all pretty straight forward, but just in case any one runs into issues there are two parts to this example. First, you generate an event template. You can then drag and drop this template onto the calendar as many times as you want.
The second part allows you to edit existing events without posting back to the server. To do this, simply click an event and then make the necessary adjustments using the top panel on the right. Once you’re done, just press update event.
The example uses the standard title property, but also includes a few others: descriptions, price, available. You can change/remove these to suit your needs, just remember to pull them out of the JavaScript as well.
Zip:
Full Calendar Zip
Basic Example Page:
Background:
Border:
Text:
Description
http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js
http://js/jquery-ui-1.9.2.custom.min.js
http://js/fullcalendar.js
http://js/view_calendar.js
http://js/jquery.miniColors.js
Basic JavaScript:
/* Wait for DOM to load etc */
$(document).ready(function(){
//Initialisations
initialise_calendar();
initialise_color_pickers();
initialise_buttons();
initialise_event_generation();
initialise_update_event();
});
/* Initialise buttons */
function initialise_buttons(){
$('.btn').button();
}
/* Binds and initialises event generation functionality */
function initialise_event_generation(){
//Bind event
$('#btn_gen_event').bind('click', function(){
//Retrieve template event
var template_event = $('#external_event_template').clone();
var background_color = $('#txt_background_color').val();
var border_color = $('#txt_border_color').val();
var text_color = $('#txt_text_color').val();
var title = $('#txt_title').val();
var description = $('#txt_description').val();
var price = $('#txt_price').val();
var available = $('#txt_available').val();
//Edit id
$(template_event).attr('id', get_uni_id());
//Add template data attributes
$(template_event).attr('data-background', background_color);
$(template_event).attr('data-border', border_color);
$(template_event).attr('data-text', text_color);
$(template_event).attr('data-title', title);
$(template_event).attr('data-description', description);
$(template_event).attr('data-price', price);
$(template_event).attr('data-available', available);
//Style external event
$(template_event).css('background-color', background_color);
$(template_event).css('border-color', border_color);
$(template_event).css('color', text_color);
//Set text of external event
$(template_event).text(title);
//Append to external events container
$('#external_events').append(template_event);
//Initialise external event
initialise_external_event('#' + $(template_event).attr('id'));
//Show
$(template_event).fadeIn(2000);
});
}
/* Initialise external events */
function initialise_external_event(selector){
//Initialise booking types
$(selector).each(function(){
//Make draggable
$(this).draggable({
revert: true,
revertDuration: 0,
zIndex: 999,
cursorAt: {
left: 10,
top: 1
}
});
//Create event object
var event_object = {
title: $.trim($(this).text())
};
//Store event in dom to be accessed later
$(this).data('eventObject', event_object);
});
}
/* Initialise color pickers */
function initialise_color_pickers(){
//Initialise color pickers
$('.color_picker').miniColors({
'trigger': 'show',
'opacity': 'none'
});
}
/* Initialises calendar */
function initialise_calendar(){
//Initialise calendar
$('#calendar').fullCalendar({
theme: true,
firstDay: 1,
header: {
left: 'today prev,next',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
defaultView: 'agendaWeek',
minTime: '6:00am',
maxTime: '6:00pm',
allDaySlot: false,
columnFormat: {
month: 'ddd',
week: 'ddd dd/MM',
day: 'dddd M/d'
},
eventSources: [
{
url: 'calendar_events.json',
editable: false
}
],
droppable: true,
drop: function(date, all_day){
external_event_dropped(date, all_day, this);
},
eventClick: function(cal_event, js_event, view){
calendar_event_clicked(cal_event, js_event, view);
},
editable: true
});
//Initialise external events
initialise_external_event('.external-event');
}
/* Handle an external event that has been dropped on the calendar */
function external_event_dropped(date, all_day, external_event){
//Create vars
var event_object;
var copied_event_object;
var duration = 60;
var cost;
//Retrive dropped elemetns stored event object
event_object = $(external_event).data('eventObject');
//Copy so that multiple events don't reference same object
copied_event_object = $.extend({}, event_object);
//Assign reported start and end dates
copied_event_object.start = date;
copied_event_object.end = new Date(date.getTime() + duration * 60000);
copied_event_object.allDay = all_day;
//Assign colors etc
copied_event_object.backgroundColor = $(external_event).data('background');
copied_event_object.textColor = $(external_event).data('text');
copied_event_object.borderColor = $(external_event).data('border');
//Assign text, price, etc
copied_event_object.id = get_uni_id();
copied_event_object.title = $(external_event).data('title');
copied_event_object.description = $(external_event).data('description');
copied_event_object.price = $(external_event).data('price');
copied_event_object.available = $(external_event).data('available');
//Render event on calendar
$('#calendar').fullCalendar('renderEvent', copied_event_object, true);
}
/* Initialise event clicks */
function calendar_event_clicked(cal_event, js_event, view){
//Set generation values
set_event_generation_values(cal_event.id, cal_event.backgroundColor, cal_event.borderColor, cal_event.textColor, cal_event.title, cal_event.description, cal_event.price, cal_event.available);
}
/* Set event generation values */
function set_event_generation_values(event_id, bg_color, border_color, text_color, title, description, price, available){
//Set values
$('#txt_background_color').miniColors('value', bg_color);
$('#txt_border_color').miniColors('value', border_color);
$('#txt_text_color').miniColors('value', text_color);
$('#txt_title').val(title);
$('#txt_description').val(description);
$('#txt_price').val(price);
$('#txt_available').val(available);
$('#txt_current_event').val(event_id);
}
/* Generate unique id */
function get_uni_id(){
//Generate unique id
return new Date().getTime() + Math.floor(Math.random()) * 500;
}
/* Initialise update event button */
function initialise_update_event(){
var test = $('#calendar').fullCalendar( 'clientEvents');
//Bind event
$('#btn_update_event').bind('click', function(){
//Create vars
var current_event_id = $('#txt_current_event').val();
//Check if value found
if(current_event_id){
//Retrieve current event
var current_event = $('#calendar').fullCalendar('clientEvents', current_event_id);
//Check if found
if(current_event && current_event.length == 1){
//Retrieve current event from array
current_event = current_event[0];
//Set values
current_event.backgroundColor = $('#txt_background_color').val();
current_event.textColor = $('#txt_text_color').val();
current_event.borderColor = $('#txt_border_color').val();
current_event.title = $('#txt_title').val();
current_event.description = $('#txt_description').val();
current_event.price = $('#txt_price').val();
current_event.available = $('#txt_available').val();
//Update event
$('#calendar').fullCalendar('updateEvent', current_event);
}
}
});
}
Stylesheet
body{
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 12px;
}
#content_wrapper{
width: 820px;
margin-left: auto;
margin-right: auto;
}
#calendar{
width: 650px;
float: left;
}
.btn{
font-size: 85%
margin-top: 10px;
}
#event_generation_wrapper{
float: left;
width: 120px;
background-color: #DDD;
margin-left: 20px;
margin-top: 40px;
border: 1px solid #4297D7;
background-color: #FCFDFD;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
padding: 10px 5px 10px 5px;
}
#event_generation_wrapper .left{
float: left;
width: 70px;
}
#event_generation_wrapper .right{
float: left;
max-width: 25px;
margin-left: 10px;
}
#event_generation_wrapper input{
width: 112px;
}
#event_generation_wrapper textarea{
width: 110px;
height: 50px;
}
#event_generation_wrapper .miniColors-triggerWrap{
margin-bottom: 5px;
}
#event_generation_wrapper .text{
padding-top: 1px;
margin-bottom: 5px;
line-height: 10px;
}
#external_events{
float: left;
width: 130px;
background-color: #DDD;
margin-left: 20px;
margin-top: 40px;
border: 1px solid #4297D7;
background-color: #FCFDFD;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
}
#external_events .external-event{
width: 100px;
margin: 5px;
font-family: Verdana, Arial, sans-serif;
border: 1px solid #36C;
padding: 3px;
text-align: center;
background-color: #36C;
color: white;
cursor: pointer;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
}
#calendar .ui-widget-header{
font-weight: normal;
padding: 3px 3px 3px 3px;
}
#calendar .fc-header-title{
font-weight: normal;
}
#external_event_template{
display: none;
}
Basic List of Events (JSON):
[
"0",
{
"allDay": "",
"title": "Test event",
"id": "821",
"start": "2012-11-23 14:00:00",
"end": "2012-11-23 15:00:00"
},
"1",
{
"allDay": "",
"title": "Test event 2",
"id": "822",
"start": "2012-11-23 9:00:00",
"end": "2012-11-23 10:00:00"
},
"2",
{
"allDay": "",
"title": "Test event 3",
"id": "823",
"start": "2012-11-24 8:00:00",
"end": "2012-11-24 6:00:00"
},
"3",
{
"allDay": "",
"title": "Test event 4",
"id": "824",
"start": "2012-11-27 6:00:00",
"end": "2012-11-27 7:00:00"
}
]
Let me know if you have any issues or something to add!
Cheers,
Chris