vendor/assets/javascripts/fullcalendar/gcal.js in fullcalendar-rails-2.2.2.0 vs vendor/assets/javascripts/fullcalendar/gcal.js in fullcalendar-rails-2.2.3.0

- old
+ new

@@ -1,7 +1,7 @@ /*! - * FullCalendar v2.2.2 Google Calendar Plugin + * FullCalendar v2.2.3 Google Calendar Plugin * Docs & License: http://arshaw.com/fullcalendar/ * (c) 2013 Adam Shaw */ (function(factory) { @@ -25,12 +25,13 @@ var match; // if the Google Calendar ID hasn't been explicitly defined if (!googleCalendarId && url) { - // detect if the ID was specified as a single string - if ((match = /^[^\/]+@([^\/]+\.)?calendar\.google\.com$/.test(url))) { + // detect if the ID was specified as a single string. + // will match calendars like "asdf1234@calendar.google.com" in addition to person email calendars. + if ((match = /^[^\/]+@([^\/\.]+\.)*(google|googlemail|gmail)\.com$/.test(url))) { googleCalendarId = url; } // try to scrape it out of a V1 or V3 API feed URL else if ( (match = /^https:\/\/www.googleapis.com\/calendar\/v3\/calendars\/([^\/]*)/.exec(url)) || @@ -52,10 +53,11 @@ sourceOptions.editable = false; } // We want removeEventSource to work, but it won't know about the googleCalendarId primitive. // Shoehorn it into the url, which will function as the unique primitive. Won't cause side effects. + // This hack is obsolete since 2.2.3, but keep it so this plugin file is compatible with old versions. sourceOptions.url = googleCalendarId; } }); @@ -69,10 +71,11 @@ function transformOptions(sourceOptions, start, end, timezone, calendar) { var url = API_BASE + '/' + encodeURIComponent(sourceOptions.googleCalendarId) + '/events?callback=?'; // jsonp var apiKey = sourceOptions.googleCalendarApiKey || calendar.options.googleCalendarApiKey; var success = sourceOptions.success; var data; + var timezoneArg; // populated when a specific timezone. escaped to Google's liking function reportError(message, apiErrorObjs) { var errorObjs = apiErrorObjs || [ { message: message } ]; // to be passed into error handlers var consoleObj = window.console; var consoleWarnFunc = consoleObj ? (consoleObj.warn || consoleObj.log) : null; @@ -101,41 +104,54 @@ } if (!end.hasZone()) { end = end.clone().utc().add(1, 'day'); } + // when sending timezone names to Google, only accepts underscores, not spaces + if (timezone && timezone != 'local') { + timezoneArg = timezone.replace(' ', '_'); + } + data = $.extend({}, sourceOptions.data || {}, { key: apiKey, timeMin: start.format(), timeMax: end.format(), + timeZone: timezoneArg, singleEvents: true, maxResults: 9999 }); return $.extend({}, sourceOptions, { googleCalendarId: null, // prevents source-normalizing from happening again url: url, data: data, - timezoneParam: 'timeZone', startParam: false, // `false` omits this parameter. we already included it above endParam: false, // same + timezoneParam: false, // same success: function(data) { var events = []; var successArgs; var successRes; if (data.error) { reportError('Google Calendar API: ' + data.error.message, data.error.errors); } else if (data.items) { $.each(data.items, function(i, entry) { + var url = entry.htmlLink; + + // make the URLs for each event show times in the correct timezone + if (timezoneArg) { + url = injectQsComponent(url, 'ctz=' + timezoneArg); + } + events.push({ id: entry.id, title: entry.summary, start: entry.start.dateTime || entry.start.date, // try timed. will fall back to all-day end: entry.end.dateTime || entry.end.date, // same - url: entry.htmlLink, + url: url, location: entry.location, description: entry.description }); }); @@ -151,6 +167,15 @@ } }); } -}); +// Injects a string like "arg=value" into the querystring of a URL +function injectQsComponent(url, component) { + // inject it after the querystring but before the fragment + return url.replace(/(\?.*?)?(#|$)/, function(whole, qs, hash) { + return (qs ? qs + '&' : '?') + component + hash; + }); +} + + +}); \ No newline at end of file