/*
* Bic Calendar - v3.2.2
* A simple twitter bootstrap calendar / agenda to mark events and select range of dates.
* http://bichotll.github.io/bic_calendar
*
* Made by bichotll
* Under Apache License
*/
$.fn.bic_calendar = function(options) {
var opts = $.extend({}, $.fn.bic_calendar.defaults, options);
this.each(function() {
/*** vars ***/
//element called
var elem = $(this);
var calendar;
var daysMonthLayer;
var textMonthCurrentLayer = $('
');
var textYearCurrentLayer = $('');
var calendarId = "bic_calendar";
var events = opts.events;
var callback = opts.callback;
//Date obj to calc the day
var objFecha;
if (opts.date) {
if (typeof opts.date == 'string') {
var arrayDate = opts.date.split('/');
objFecha = new Date(parseInt(arrayDate[2]), parseInt(arrayDate[1]) - 1, parseInt(arrayDate[0]));
} else {
objFecha = opts.date;
}
} else {
objFecha = new Date();
}
var dayNames;
if (typeof opts.dayNames != "undefined")
dayNames = opts.dayNames;
else
dayNames = ["l", "m", "x", "j", "v", "s", "d"];
var monthNames;
if (typeof opts.monthNames != "undefined")
monthNames = opts.monthNames;
else
monthNames = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"];
var showDays;
if (typeof opts.showDays != "undefined")
showDays = opts.showDays;
else
showDays = true;
var popoverOptions;
if (typeof opts.popoverOptions != "undefined")
popoverOptions = opts.popoverOptions;
else
popoverOptions = {placement: 'bottom', html: true, trigger: 'hover'};
var tooltipOptions;
if (typeof opts.tooltipOptions != "undefined")
tooltipOptions = opts.tooltipOptions;
else
tooltipOptions = {placement: 'bottom', trigger: 'hover'};
var reqAjax;
if (typeof opts.reqAjax != "undefined")
reqAjax = opts.reqAjax;
else
reqAjax = false;
var enableSelect = false;
if (typeof opts.enableSelect != 'undefined')
enableSelect = opts.enableSelect;
var multiSelect = false;
if (typeof opts.multiSelect != 'undefined')
multiSelect = opts.multiSelect;
var displayMonthController = true;
if (typeof opts.displayMonthController != 'undefined')
displayMonthController = opts.displayMonthController;
var displayYearController = true;
if (typeof opts.displayYearController != 'undefined')
displayYearController = opts.displayYearController;
var startWeekDay = 0;
if (typeof opts.startWeekDay != 'undefined')
startWeekDay = opts.startWeekDay;
var firstDaySelected = '';
var lastDaySelected = '';
var daySelected = '';
/*** --vars-- ***/
/*** functions ***/
/**
* init n print calendar
*/
function showCalendar() {
//layer with the days of the month (literals)
daysMonthLayer = $('');
listListeralsWeek();
//current year n current month
var month = objFecha.getMonth();
var year = objFecha.getFullYear();
//show the days of the month n year configured
showMonthDays(month, year);
//next-previous month controllers
var nextMonthButton = $(' | ');
//event
nextMonthButton.click(function(e) {
e.preventDefault();
month = (month + 1) % 12;
if (month == 0)
year++;
changeDate(month, year);
})
var previousMonthButton = $(' | ');
//event
previousMonthButton.click(function(e) {
e.preventDefault();
month = (month - 1);
if (month == -1) {
year--;
month = 11;
}
changeDate(month, year);
})
//next-previous year controllers
var nextYearButton = $(' | ');
//event
nextYearButton.click(function(e) {
e.preventDefault();
year++;
changeDate(month, year);
})
var previousYearButton = $(' | ');
//event
previousYearButton.click(function(e) {
e.preventDefault();
year--;
changeDate(month, year);
})
//show the current year n current month text layer
var headerLayer = $('');
if (displayYearController === true) {
var yearTextLayer = $('
');
var yearControlTextLayer = $(' | ');
yearTextLayer.append(previousYearButton);
yearTextLayer.append(yearControlTextLayer);
yearTextLayer.append(nextYearButton);
yearControlTextLayer.append(textYearCurrentLayer);
headerLayer.append(yearTextLayer);
}
if (displayMonthController === true) {
var monthTextLayer = $('
');
var monthControlTextLayer = $(' | ');
monthTextLayer.append(previousMonthButton);
monthTextLayer.append(monthControlTextLayer);
monthTextLayer.append(nextMonthButton);
monthControlTextLayer.append(textMonthCurrentLayer);
headerLayer.append(monthTextLayer);
}
//calendar n border
calendar = $('');
calendar.prepend(headerLayer);
//calendar.append(capaDiasSemana);
//daysMonthLayer.prepend(capaDiasSemana);
calendar.append(daysMonthLayer);
//insert calendar in the document
elem.append(calendar);
//check and add events
checkEvents(month, year);
//if enable select
checkIfEnableMark();
}
/**
* indeed, change month or year
*/
function changeDate(month, year) {
daysMonthLayer.empty();
listListeralsWeek();
showMonthDays(month, year);
checkEvents(month, year);
markSelectedDays();
}
/**
* show literals of the week
*/
function listListeralsWeek() {
if (showDays != false) {
var capaDiasSemana = $('');
var codigoInsertar = '';
$(dayNames).each(function(indice, valor) {
codigoInsertar += '" + valor + ' | ';
});
codigoInsertar += '
';
capaDiasSemana.append(codigoInsertar);
daysMonthLayer.append(capaDiasSemana);
}
}
/**
* show the days of the month
*/
function showMonthDays(month, year) {
//print year n month in layers
textMonthCurrentLayer.text(monthNames[month]);
textYearCurrentLayer.text(year);
//show days of the month
var daysCounter = 1;
//calc the date of the first day of this month
var firstDay = calcNumberDayWeek(1, month, year);
//calc the last day of this month
var lastDayMonth = lastDay(month, year);
var nMonth = month + 1;
var daysMonthLayerString = "";
//print the first row of the week
for (var i = 0; i < 7; i++) {
if (i < firstDay) {
var dayCode = "";
if (i == 0)
dayCode += "";
//add weekDay
dayCode += ' | ';
} else {
var dayCode = "";
if (i == 0)
dayCode += '
';
dayCode += '';
if (i == 6)
dayCode += ' |
';
daysCounter++;
}
daysMonthLayerString += dayCode
}
//check all the other days until end of the month
var currentWeekDay = 1;
while (daysCounter <= lastDayMonth) {
var dayCode = "";
if (currentWeekDay % 7 == 1)
dayCode += "";
dayCode += ' | ';
if (currentWeekDay % 7 == 0)
dayCode += "
";
daysCounter++;
currentWeekDay++;
daysMonthLayerString += dayCode
}
//check if the empty cells it have yet to write of the last week of the month
currentWeekDay--;
if (currentWeekDay % 7 != 0) {
dayCode = "";
for (var i = (currentWeekDay % 7) + 1; i <= 7; i++) {
var dayCode = "";
dayCode += ' | ';
if (i == 7)
dayCode += ''
daysMonthLayerString += dayCode
}
}
daysMonthLayer.append(daysMonthLayerString);
}
/**
* calc the number of the week day
*/
function calcNumberDayWeek(day, month, year) {
var objFecha = new Date(year, month, day);
var numDia = objFecha.getDay();
numDia += startWeekDay;
if (numDia == 0)
numDia = 6;
else
numDia--;
return numDia;
}
/**
* check if a date is correct
*
* @thanks http://kevin.vanzonneveld.net
* @thanks http://www.desarrolloweb.com/manuales/manual-librerias-phpjs.html
*/
function checkDate(m, d, y) {
return m > 0 && m < 13 && y > 0 && y < 32768 && d > 0 && d <= (new Date(y, m, 0)).getDate();
}
/**
* return last day of a date (month n year)
*/
function lastDay(month, year) {
var lastDayValue = 28;
while (checkDate(month + 1, lastDayValue + 1, year)) {
lastDayValue++;
}
return lastDayValue;
}
function validateWritedDate(fecha) {
var arrayFecha = fecha.split("/");
if (arrayFecha.length != 3)
return false;
return checkDate(arrayFecha[1], arrayFecha[0], arrayFecha[2]);
}
/**
* check if there are ajax events
*/
function checkEvents(month, year) {
if (reqAjax != false) {
$('#calendari_lateral_container .calendar_loading').show();
//peticio ajax
$.ajax({
type: reqAjax.type,
url: reqAjax.url,
data: {mes: month + 1, ano: year},
dataType: 'json'
}).done(function(data) {
if (typeof events == 'undefined')
events = [];
$.each(data, function(k, v) {
events.push(data[k]);
});
markEvents(month, year);
if (typeof callback == 'function') { // make sure the callback is a function
callback.call(this); // brings the scope to the callback
}
});
} else {
this.markEvents(month, year);
}
}
/**
* mark all the events n create logic for them
*/
function markEvents(month, year) {
var temporalMonth = month + 1;
for (var i = 0; i < events.length; i++) {
if (events[i].date.split('/')[1] == temporalMonth && events[i].date.split('/')[2] == year) {
var loopDayTd = $('#' + calendarId + '_' + events[i].date.replace(/\//g, "_"));
var loopDayA = $('#' + calendarId + '_' + events[i].date.replace(/\//g, "_") + ' a');
loopDayTd.addClass('event');
loopDayA.attr('data-original-title', events[i].title);
//bg color
if (events[i].color)
loopDayTd.css('background', events[i].color);
//link
if (typeof events[i].link != 'undefined' && events[i].link != '') {
loopDayA.attr('href', events[i].link);
}
if (typeof events[i].linkTarget != 'undefined' && events[i].linkTarget != '') {
loopDayA.attr('target', events[i].linkTarget);
}
//class
if (events[i].class)
loopDayTd.addClass(events[i].class);
//tooltip vs popover
if (events[i].content) {
loopDayTd.addClass('event_popover');
loopDayA.attr('rel', 'popover');
loopDayA.attr('data-content', events[i].content);
} else {
loopDayTd.addClass('event_tooltip');
loopDayA.attr('rel', 'tooltip');
}
}
}
$('#' + calendarId + ' ' + '.event_tooltip a').tooltip(tooltipOptions);
$('#' + calendarId + ' ' + '.event_popover a').popover(popoverOptions);
$('.manual_popover').click(function() {
$(this).popover('toggle');
});
}
/**
* check if the user can mark days
*/
function checkIfEnableMark() {
if (enableSelect == true) {
var eventBicCalendarSelect;
elem.on('click', '#' + calendarId + ' td.day', function() {
//if multiSelect
if (multiSelect == true) {
if (daySelected == '') {
daySelected = $(this).data('date');
this.markSelectedDays();
} else {
if (lastDaySelected == '') {
//set firstDaySelected
firstDaySelected = daySelected;
lastDaySelected = $(this).data('date');
this.markSelectedDays();
//create n fire event
//to change
var eventBicCalendarSelect = new CustomEvent("bicCalendarSelect", {
detail: {
dateFirst: firstDaySelected,
dateLast: lastDaySelected
}
});
document.dispatchEvent(eventBicCalendarSelect);
} else {
firstDaySelected = '';
lastDaySelected = '';
daySelected = '';
elem.find('.selection').removeClass('middle-selection selection first-selection last-selection');
}
}
} else {
//remove the class selection of the others a
elem.find('td div').removeClass('selection');
//add class selection
$(this).find('div').addClass('selection');
//create n fire event
var eventBicCalendarSelect = new CustomEvent("bicCalendarSelect", {
detail: {
date: $(this).data('date')
}
});
document.dispatchEvent(eventBicCalendarSelect);
}
})
}
}
/**
* to mark selected dates
*/
function markSelectedDays() {
if (daySelected != '' && firstDaySelected == '') {
var arrayDate = daySelected.split('/');
$('#' + calendarId + '_' + arrayDate[1] + '_' + arrayDate[0] + '_' + arrayDate[2] + ' div').addClass('selection');
} else if (firstDaySelected != '') {
//create array from dates
var arrayFirstDay = firstDaySelected.split('/');
var arrayLastDay = lastDaySelected.split('/');
//remove all selected classes
elem.find('td.selection').removeClass('selection');
//create date object from dates
var oldSelectedDate = new Date(firstDaySelected);
var newSelectedDate = new Date(lastDaySelected);
//create a loop adding day per loop to set days
//turn dates if >
if (oldSelectedDate > newSelectedDate) {
//turn vars date
var tempSelectedDate = oldSelectedDate;
oldSelectedDate = newSelectedDate;
newSelectedDate = tempSelectedDate;
}
//set first selection
$('#' + calendarId + '_' + oldSelectedDate.getDate() + '_' + (parseInt(oldSelectedDate.getMonth()) + 1) + '_' + oldSelectedDate.getFullYear() + ' div').addClass('selection first-selection');
while (oldSelectedDate < newSelectedDate) {
oldSelectedDate.setDate(oldSelectedDate.getDate() + 1);
//set middle-selection
$('#' + calendarId + '_' + oldSelectedDate.getDate() + '_' + (parseInt(oldSelectedDate.getMonth()) + 1) + '_' + oldSelectedDate.getFullYear() + ' div').addClass('selection middle-selection');
}
//set last selection
$('#' + calendarId + '_' + oldSelectedDate.getDate() + '_' + (parseInt(oldSelectedDate.getMonth()) + 1) + '_' + oldSelectedDate.getFullYear() + ' div').removeClass('middle-selection').addClass('selection last-selection');
}
}
/*** --functions-- ***/
//fire calendar!
showCalendar();
});
return this;
};