// // OBJECT USED TO SETUP GCALENDARVIEWER FUNCTIONALITY // function GCalendarViewer(gCalendarViewerEventsService) { // declare variables this.gCalendarViewerEventsService = (gCalendarViewerEventsService) ? gCalendarViewerEventsService : null; this.activeEvent = null; this.activeDate = null; this.today = null; this.mode = 'month'; this.startDate = null; this.endDate = null; this.blockID = -1; this.monthOffset = 0; this.monthNames = null; this.fullMonthNames = new Array('January','February','March','April','May','June','July','August','September','October','November','December'); this.dayNames = null; this.fullDayNames = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'); this.scrollbarController = null; // agenda specific variables this.retrievingAgendaEvents = false; } GCalendarViewer.prototype.init = function() { // initialize gCalendarViewerEventsService object if(this.gCalendarViewerEventsService) this.gCalendarViewerEventsService.init(); // initialize properties as necessary if(this.monthNames == null) this.monthNames = this.fullMonthNames; if(this.dayNames == null) this.dayNames = this.fullDayNames; // setup initial state switch(this.mode.toLowerCase()){ case 'week': this.setupWeekHeader(); this.setupWeekDayEvents(); this.generateNewMonthHTML(0); this.setupWeekMonthPopUp(); this.setupEventPopUps(); break; case 'day': this.setupDayHeader(); this.setupDayEvents(); this.generateNewMonthHTML(0); this.setupDayMonthPopUp(); this.setupEventPopUps(); break; case 'agenda': this.setupAgendaScrollbar(); this.setupEventPopUps(); this.determineAgendaLoaderVisibility(); break; case 'month': default: this.setupMonthNavigationButtons(); this.setupMonthCalendarPopUps(); this.setupEventPopUps(); } } GCalendarViewer.prototype.setupMonthNavigationButtons = function() { var context = this; // define click for reset month button $('#gcalendar-viewer-container-' + context.blockID + ' div.gc-month a').attr('title', 'Click to reset to current month'); $('#gcalendar-viewer-container-' + context.blockID + ' div.gc-month a').unbind('click').click(function(){ context.gCalendarViewerEventsService.getCurrent(); }); // define click for previous month button $('#gcalendar-viewer-container-' + context.blockID + ' div.gc-previous-button a').attr('title', 'Click to go to previous month'); $('#gcalendar-viewer-container-' + context.blockID + ' div.gc-previous-button a').unbind('click').click(function(){ context.gCalendarViewerEventsService.getPrevious(); }); // define click for next month button $('#gcalendar-viewer-container-' + context.blockID + ' div.gc-next-button a').attr('title', 'Click to go to next month'); $('#gcalendar-viewer-container-' + context.blockID + ' div.gc-next-button a').unbind('click').click(function(){ context.gCalendarViewerEventsService.getNext(); }); } GCalendarViewer.prototype.setupMonthCalendarPopUps = function() { var context = this; var popUpTriggers = $('#gcalendar-viewer-container-' + this.blockID + ' .gc-popup-trigger'); for(var i = 0; i < popUpTriggers.length; i++){ popUpTriggers[i].index = i; var eventPopUp = $('#gcalendar-viewer-container-' + this.blockID + ' #gc-event-popup-' + i); eventPopUp.index = i; eventPopUp.css('z-index', '1'); eventPopUp.hide(); $(popUpTriggers[i]).unbind('click').click(function() { var eventPopUp = $('#gcalendar-viewer-container-' + context.blockID + ' #gc-event-popup-' + this.index); if(context.activeEvent != null){ context.activeEvent.css('z-index', '1'); context.activeEvent.fadeOut(250); } eventPopUp.css('z-index', '2'); eventPopUp.fadeIn(250); context.activeEvent = eventPopUp; // eventPopUp.parent().addClass('open'); }); $(popUpTriggers[i]).mouseout(function() { var eventPopUp = $('#gcalendar-viewer-container-' + context.blockID + ' #gc-event-popup-' + this.index); eventPopUp.css('z-index', '1'); clearTimeout(eventPopUp.timer); eventPopUp.timer = setTimeout(function(){ eventPopUp.fadeOut(250, function(){ $(this).parent().removeClass('open'); }); }, 350); eventPopUp.mouseover(function(){ clearTimeout(eventPopUp.timer); }); eventPopUp.mouseout(function(){ clearTimeout(eventPopUp.timer); eventPopUp.timer = setTimeout(function(){ eventPopUp.fadeOut(250, function(){ $(this).parent().removeClass('open'); }); }, 350); }); }); } // stagger event line colours $('#gcalendar-viewer-container-' + this.blockID + ' ul.gc-body-month ul.gc-events li:even').css('background-color', '#fff'); } GCalendarViewer.prototype.setupWeekHeader = function() { var context = this; // set the header text to the active date var title = context.monthNames[this.activeDate.getMonth()] + ' ' + this.activeDate.getDate() + ', ' + this.activeDate.getFullYear(); $('#gcalendar-viewer-container-' + this.blockID + ' .gc-todays-date > span').html(title); } GCalendarViewer.prototype.setupWeekDayEvents = function() { var context = this; // grab an array of all day visual buttons var visualButtons = $('#gcalendar-viewer-container-' + this.blockID + ' div.gcalendar-viewer-container-body li.gc-daynames li.gc-dayname'); // retrieve individual visual button sizes var buttonSizes = this.getWeekDayEventButtonSizes(visualButtons); for(var i = 0; i < visualButtons.length; i++){ // store index on its corresponding visual button visualButtons[i].index = i; // store date on its corresponding visual button visualButtons[i].date = new Date(this.startDate.getFullYear(), this.startDate.getMonth(), this.startDate.getDate() + i); // set width of visual button if available (css provides default percentage sizing) if(!!buttonSizes && !!buttonSizes[i]){ $(visualButtons[i]).css('width', buttonSizes[i]); } if(visualButtons[i].date.getTime() == context.activeDate.getTime()){ // remove all existing selections $('#gcalendar-viewer-container-' + this.blockID + ' div.gcalendar-viewer-container-body li.gc-daynames li.selected').removeClass('selected'); $('#gcalendar-viewer-container-' + this.blockID + ' div.gcalendar-viewer-container-body li.gc-week li.selected').removeClass('selected'); // add 'selected' class name to current event day trigger if it represents the active day $(visualButtons[i]).addClass('selected'); // add 'selected' class name to current event day if it represents the active day $('#gcalendar-viewer-container-' + this.blockID + ' div.gcalendar-viewer-container-body li.gc-week li.gc-date-' + visualButtons[i].date.getDate()).addClass('selected'); } // add click functionality to visual buttons to facilitate user interraction $(visualButtons[i]).unbind('click').click(function() { // get necessary references to visual day buttons and event containers var visualButtons = $('#gcalendar-viewer-container-' + context.blockID + ' div.gcalendar-viewer-container-body li.gc-daynames li.gc-dayname'); var eventDayContainers = $('#gcalendar-viewer-container-' + context.blockID + ' div.gcalendar-viewer-container-body li.gc-week li.gc-day'); var activeEventDayContainer = eventDayContainers[this.index]; // remove all existing selections $('#gcalendar-viewer-container-' + context.blockID + ' div.gcalendar-viewer-container-body li.gc-daynames li.selected').removeClass('selected'); $('#gcalendar-viewer-container-' + context.blockID + ' div.gcalendar-viewer-container-body li.gc-week li.selected').removeClass('selected'); // select the clicked visual button $(this).addClass('selected'); // select the event container corresponding to the selected visual button $(activeEventDayContainer).addClass('selected'); // set the header text to the selected date var title = context.monthNames[this.date.getMonth()] + ' ' + this.date.getDate() + ', ' + this.date.getFullYear(); $('#gcalendar-viewer-container-' + context.blockID + ' .gc-todays-date > span').html(title); // set the active date to the selected date context.activeDate = new Date(this.date.getTime()); }); } } GCalendarViewer.prototype.setupWeekMonthPopUp = function() { var context = this; // set correct opacity on modal background $('#gcalendar-viewer-container-' + this.blockID + ' div.gc-modal').css('opacity', '0.35'); // define click functionality to fade popup in var menuClickHandler = function() { // fade month popup in $('#gcalendar-viewer-container-' + context.blockID + ' div.gcalendar-viewer-month-popup').fadeIn(400); // center within container var width = $('#gcalendar-viewer-container-' + context.blockID + ' div.gcalendar-viewer-month-popup div.gc-month-back').width(); var height = $('#gcalendar-viewer-container-' + context.blockID + ' div.gcalendar-viewer-month-popup div.gc-month-back').height(); $('#gcalendar-viewer-container-' + context.blockID + ' div.gcalendar-viewer-month-popup div.gc-month-back').css({'margin-top': 0 - Math.round((height + 10) / 2), 'margin-left': 0 - Math.round((width + 10) / 2)}); } $('#gcalendar-viewer-container-' + this.blockID + ' div.gc-title a').unbind('click').click(menuClickHandler); $('#gcalendar-viewer-container-' + this.blockID + ' div.gc-title a span').unbind('click').click(menuClickHandler); // define click on modal background to fade popup out $('#gcalendar-viewer-container-' + this.blockID + ' div.gc-modal').unbind('click').click(function(){ // fade month popout out $('#gcalendar-viewer-container-' + context.blockID + ' div.gcalendar-viewer-month-popup').fadeOut(400); }) $('#gcalendar-viewer-container-' + this.blockID + ' div.gcalendar-viewer-month-popup').unbind('mouseleave').mouseleave(function(){ // fade month popout out $('#gcalendar-viewer-container-' + context.blockID + ' div.gcalendar-viewer-month-popup').fadeOut(400); }); // define click for reset month button $('#gcalendar-viewer-container-' + this.blockID + ' div.gc-month a').attr('title', 'Click to reset to current month'); $('#gcalendar-viewer-container-' + this.blockID + ' div.gc-month a').unbind('click').click(function(){ context.generateNewMonthHTML(0 - context.monthOffset); context.setupWeekMonthPopUp(); }); // define click for previous month button $('#gcalendar-viewer-container-' + this.blockID + ' div.gc-previous-button a').attr('title', 'Click to go to previous month'); $('#gcalendar-viewer-container-' + this.blockID + ' div.gc-previous-button a').unbind('click').click(function(){ context.generateNewMonthHTML(-1); context.setupWeekMonthPopUp(); }); // define click for next month button $('#gcalendar-viewer-container-' + this.blockID + ' div.gc-next-button a').attr('title', 'Click to go to next month'); $('#gcalendar-viewer-container-' + this.blockID + ' div.gc-next-button a').unbind('click').click(function(){ context.generateNewMonthHTML(1); context.setupWeekMonthPopUp(); }); // apply interactive functionality to each day button $('#gcalendar-viewer-container-' + this.blockID + ' div.gcalendar-viewer-month-popup li.gc-activedate').each(function(){ var gCalendarViewer = context; // create date object for current day button this.date = new Date(context.today.getFullYear(), context.today.getMonth() + context.monthOffset, $('a', this).html()); // apply css class to day button to visually indicate interactivity $(this).addClass('gc-has-event'); $('a', this).addClass('gc-has-event'); // define click for day button to load events for the whole week of the selected day $(this).unbind('click').click(function(){ // calculate date offset between today and date clicked var offset = Math.round((this.date - gCalendarViewer.today) / 1000 / 60 / 60 / 24); // retrieve new batch of event data based on date offset gCalendarViewer.gCalendarViewerEventsService.get(offset); // set active date to date clicked gCalendarViewer.activeDate = this.date; // calculate new start/end dates gCalendarViewer.startDate = new Date(this.date.getTime() - this.date.getDay() * 24 * 60 * 60 * 1000); gCalendarViewer.endDate = new Date(gCalendarViewer.startDate.getTime() + 7 * 24 * 60 * 60 * 1000); // visually close month popup $('#gcalendar-viewer-container-' + gCalendarViewer.blockID + ' div.gcalendar-viewer-month-popup').fadeOut(400); }); }); } GCalendarViewer.prototype.setupDayHeader = function() { var context = this; // set the header text to the active date var title = context.monthNames[this.activeDate.getMonth()] + ' ' + this.activeDate.getDate() + ', ' + this.activeDate.getFullYear(); $('#gcalendar-viewer-container-' + this.blockID + ' .gc-todays-date > span').html(title); } GCalendarViewer.prototype.setupDayEvents = function() { var context = this; // add 'selected' class name to current event day if it represents the active day $('#gcalendar-viewer-container-' + this.blockID + ' div.gcalendar-viewer-container-body li.gc-week li.gc-date-' + context.activeDate.getDate()).addClass('selected'); } GCalendarViewer.prototype.setupDayMonthPopUp = function() { var context = this; // set correct opacity on modal background $('#gcalendar-viewer-container-' + this.blockID + ' div.gc-modal').css('opacity', '0.35'); // define click functionality to fade popup in var menuClickHandler = function() { // fade month popup in $('#gcalendar-viewer-container-' + context.blockID + ' div.gcalendar-viewer-month-popup').fadeIn(400); // center within container var width = $('#gcalendar-viewer-container-' + context.blockID + ' div.gcalendar-viewer-month-popup div.gc-month-back').width(); var height = $('#gcalendar-viewer-container-' + context.blockID + ' div.gcalendar-viewer-month-popup div.gc-month-back').height(); $('#gcalendar-viewer-container-' + context.blockID + ' div.gcalendar-viewer-month-popup div.gc-month-back').css({'margin-top': 0 - Math.round((height + 10) / 2), 'margin-left': 0 - Math.round((width + 10) / 2)}); } $('#gcalendar-viewer-container-' + this.blockID + ' div.gc-title a').unbind('click').click(menuClickHandler); $('#gcalendar-viewer-container-' + this.blockID + ' div.gc-title a span').unbind('click').click(menuClickHandler); // define click on modal background to fade popup out $('#gcalendar-viewer-container-' + this.blockID + ' div.gc-modal').unbind('click').click(function(){ // fade month popout out $('#gcalendar-viewer-container-' + context.blockID + ' div.gcalendar-viewer-month-popup').fadeOut(400); }) $('#gcalendar-viewer-container-' + this.blockID + ' div.gcalendar-viewer-month-popup').unbind('mouseleave').mouseleave(function(){ // fade month popout out $('#gcalendar-viewer-container-' + context.blockID + ' div.gcalendar-viewer-month-popup').fadeOut(400); }); // define click for reset month button $('#gcalendar-viewer-container-' + this.blockID + ' div.gc-month a').attr('title', 'Click to reset to current month'); $('#gcalendar-viewer-container-' + this.blockID + ' div.gc-month a').unbind('click').click(function(){ context.generateNewMonthHTML(0 - context.monthOffset); context.setupWeekMonthPopUp(); }); // define click for previous month button $('#gcalendar-viewer-container-' + this.blockID + ' div.gc-previous-button a').attr('title', 'Click to go to previous month'); $('#gcalendar-viewer-container-' + this.blockID + ' div.gc-previous-button a').unbind('click').click(function(){ context.generateNewMonthHTML(-1); context.setupWeekMonthPopUp(); }); // define click for next month button $('#gcalendar-viewer-container-' + this.blockID + ' div.gc-next-button a').attr('title', 'Click to go to next month'); $('#gcalendar-viewer-container-' + this.blockID + ' div.gc-next-button a').unbind('click').click(function(){ context.generateNewMonthHTML(1); context.setupWeekMonthPopUp(); }); // apply interactive functionality to each day button $('#gcalendar-viewer-container-' + this.blockID + ' div.gcalendar-viewer-month-popup li.gc-activedate').each(function(){ var gCalendarViewer = context; // create date object for current day button this.date = new Date(context.today.getFullYear(), context.today.getMonth() + context.monthOffset, $('a', this).html()); // apply css class to day button to visually indicate interactivity $(this).addClass('gc-has-event'); $('a', this).addClass('gc-has-event'); // define click for day button to load events for the whole week of the selected day $(this).unbind('click').click(function(){ // calculate date offset between today and date clicked var offset = Math.round((this.date - gCalendarViewer.today) / 1000 / 60 / 60 / 24); // retrieve new batch of event data based on date offset gCalendarViewer.gCalendarViewerEventsService.get(offset); // set active date to date clicked gCalendarViewer.activeDate = this.date; // calculate new start/end dates gCalendarViewer.startDate = new Date(this.date.getTime()); gCalendarViewer.endDate = new Date(this.date.getTime() + 1 * 24 * 60 * 60 * 1000); // visually close month popup $('#gcalendar-viewer-container-' + gCalendarViewer.blockID + ' div.gcalendar-viewer-month-popup').fadeOut(400); }); }); } GCalendarViewer.prototype.setupEventPopUps = function() { var context = this; var eventLinks = $('#gcalendar-viewer-container-' + this.blockID + ' .gcalendar-viewer-container-body a.gc-event'); for(var i = 0; i < eventLinks.length; i++){ $(eventLinks[i]).fancybox({ centerOnScroll: true }); } } // function to calculate width of individual buttons and return as an array of 7 values // - this functionality was split out so that it can be overidden for customizations as necessary GCalendarViewer.prototype.getWeekDayEventButtonSizes = function(visualButtons) { // determine width of container var containerWidth = $('div.gcalendar-viewer-container-week').width(); // calculate individual visual button width rounded down to nearest integer var individualWidth = Math.floor(containerWidth / 7); // calculate the remaining pixels left from rounding down var remainderWidth = containerWidth - (individualWidth * (visualButtons.length - 1)) - individualWidth; // calculate half the remaining pixels to spread them out between first and last buttons var halfRemainderWidth = Math.floor(remainderWidth / 2); // return an array of widths for each visual button return [individualWidth + (remainderWidth - halfRemainderWidth), individualWidth, individualWidth, individualWidth, individualWidth, individualWidth, individualWidth + halfRemainderWidth]; } GCalendarViewer.prototype.generateNewMonthHTML = function(offset) { // declare variables var i, dayCount = -1, weekCount = 0, date; // update month offset this.monthOffset += offset; // calculate month bounds var monthStart = new Date(this.today.getFullYear(), this.today.getMonth() + this.monthOffset, 1); var startDate = new Date(monthStart.getTime() - monthStart.getDay() * 24 * 60 * 60 * 1000); var monthEnd = new Date(new Date(monthStart.getFullYear(), monthStart.getMonth() + 1, 1).getTime() - 24 * 60 * 60 * 1000); var endDate = new Date(monthEnd.getTime() + (6 - monthEnd.getDay()) * 24 * 60 * 60 * 1000); // setup html container var html = '