December 30, 2006
GCalendar: Accessing Google Calendar from JavaScript
Introduction
Some weeks ago Google has added a nice new feature to their GData libraries: JSON data retrieval. This means that we now can retrieve data from some services of Google (Base, Blogger and Calendar for now) without having to proxy it through our servers (if you still don’t know, after thousands of posts about Cross-Domain issues, why you need to do this, just look here).
Why can we do this? Because we can just create a <script>-Element, points the src to the feed URL and tell the GData API what function to call upon load.
var headTag = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = feedurl;
headTag.appendChild(script);
I was a bit sorry to see that Google doesn’t
provide an API for Client side JavaScript. So once again, in one of those “don’t complain,
do it better“-moments I figured it would be nice to write it myself for the Calendar.
Off course some stuff can’t be done with JavaScript, we can only retrieve data, not submit new
data to Google, so we can’t add new entries directly, but hey it’s a start
The library
We start off by modelling the Entry class, as you might easily figure out by the following code we rely on the Prototype library.
var EventEntry = Class.create();
EventEntry.prototype = {
title: null,
content: null,
startDate: null,
endDate: null,
location: null,
initialize: function(entry){
this.title = entry.title.$t;
this.content = entry.content.$t;
this.startDate = DateConverter.rfc3339toDate(entry.gd$when[0].startTime);
this.endDate = DateConverter.rfc3339toDate(entry.gd$when[0].endTime);
this.location = entry.gd$where[0].valueString;
}
};
Next we create a class that takes care of loading the feed, calling the callbacks and so on.
var Calendar = Class.create();
Calendar.prototype = {
uri: "7cghno42lleqpbihmoi5qiikm8%40group.calendar.google.com",
orderby: "starttime",
singleEvents: true,
futureEvents: true,
sortOrder: "ascending",
entries: {},
initialize: function(u){
if(u){this.uri = u;}
},
buildURL: function(){
var str = "http://www.google.com/calendar/feeds/";
str += this.uri;
str += "/public/full-noattendees?orderby=" + this.orderby;
str += "&alt=json-in-script&callback=window.activeCalendar.parseFeed&";
str += "singleevents=" + this.singleEvents;
str += "&sortorder=" + this.sortOrder;
str += "&futureevents=" + this.futureEvents;
return str;
},
loadFeed: function(){
window.activeCalendar = this;
var headTag = document.getElementsByTagName('head')[0];
var script = document.createElement("script");
script.src = this.buildURL();
script.language = "JavaScript";
headTag.appendChild(script);
},
parseFeed: function(json){
e = json.feed.entry;
for(var i=0;i < e.length;i++){
this.entries[i] = new EventEntry(e[i])
}
try {
this.onsuccess(this);
} catch (e) {}
},
onsuccess: function(c){}
};
Notice the first line of the loadFeed? Yep, it’s a workaround, and an ugly one too. The problem
is that we want to have access to the Calendar-object once we have the feed data. So we add it
to the window-object. Anyway, this is the reason why you can load only one calendar at once.
And what would we be without some really ugly utility objects? So here you go, a pretty useless
date converter class:
/**
* Singleton object used to convert Dates from one format to another.
*/
var DateConverter = {
rfc3339toDate: function(t){
t = t.substr(0,19).replace(/-/g,"/").replace("T"," ");
var dt = new Date();
dt.setTime(Date.parse(t));
return dt;
}
};
So after all this code that you don’t have to write (because you can download it all here) now some code you have to write.
How to use it
I tried to keep it as simple as possible, if there are enough requests I may well extend it further, but for now it works nicely as it is. First you have to find out the feed identifier. Take the Feed URL as can be found in Google Calendar in the Calendar details and it will look something like this:
http://www.google.com/calendar/feeds/7cghno42lleqpbihmoi5qiikm8%40group.calendar.google.com/public/basic
Take the bold part and that’s the Feed Identifier that will then be used to create the instance of the Calendar:
var cal = new Calendar("7cghno42lleqpbihmoi5qiikm8%40group.calendar.google.com");
Next thing we need to do is add a callback function that is called once the Feed is loaded, and then kick the request off:
cal.onsuccess = function(c){alert(c);}
cal.loadFeed();
And that’s it
Now let’s see what we can do with it, and the reason I started fiddling with the Calendar in
the first place. My custom frontend to one of my calendars can be seen
here.
- Google’s new Feed API
- Google adds JSON interfaces
- Visual Form Feedback
- Simple PHP Object Persistence
- YUI Blog on JavaScript
January 1st, 2007 at 19:47:01
January 2nd, 2007 at 05:17:03
January 4th, 2007 at 08:26:32
January 6th, 2007 at 20:28:41
January 12th, 2007 at 05:44:15
January 12th, 2007 at 09:02:34
February 10th, 2007 at 20:22:34
Many Thanks Again.
February 13th, 2007 at 02:05:47
April 4th, 2007 at 19:18:43
October 18th, 2007 at 18:53:07
http://www.emeraldforeststudios.com/calendar/
I can’t get your script working. Am I missing something? I know I don’t need to sign up for an API key, that’s just for google maps.
Please direct me.
October 23rd, 2007 at 19:08:47