A Google Calendar Widget for Google Sites created with Google Apps Script

Mark Allen recently posted on the GEG UK G+ Community asking if there was a better Google Calendar widget for new Google Sites. If you missed it Google Calendar recently had a UI overhaul but this hasn’t yet been applied to the embeddable version which gets used as the calendar option in new Google Sites.

In his post Mark highlighted the Google Calendar Chrome Extension made by Google, which does have a light Material Design look about it. The source code for the extension is available on Github and I was interested to find out if there was a magic Google url they were embedding the calendar with or if the calendar was locally styled by the extension. Looking through the code it was quickly apparent that the extension was making calls to the Google Calendar API and then styling the results.

As Google also recently announced that Google Apps Script Web Apps can be embedded in new Google Sites and given the majority of Chrome Extensions are just a wrapper for HTML/JS/CSS I thought I’d have a look at porting the extension code into Google Apps Script. Below you can see the result with the existing calendar widget on the left and the ported Chrome Extension on the right:

Existing calendar widget on the left and the ported Chrome Extension on the right
Existing calendar widget on the left and the ported Chrome Extension on the right

If you’d like to deploy your own version of this you can copy this script file and follow the setup.

Porting Chrome Extensions

Porting a Chrome Extension to Apps Script is feasible, one headache is when developing Chrome Extensions there are a number of different APIs you can call for things like authentication, storage and sending messages. Rather than commenting these out I created this basic shim that either handled these in an Apps Script way or just did nothing gracefully.

Chrome Extensions can handle internationalization (i18n) well and rather than removing this from the Apps Script project I copied the i18n EN JSON object into the project and provided a method for getMessage.

To include the various .html, .js and .css files in the web app I used Bruce Mcpherson’s ‘Include’ code, which has a number of advantages, in particular, allowing you to use the same code on both the client and the server side. I extended this code with an insert image handler designed to include icon images within the webapp. Previously you could have used Google Drive web hosting for this but as this is no longer available I Base64 encoded the icons into an object (icon.gs) and then included them in the html. The code excerpts for this look like:

An extract from the icon object:

Function for including images:

Which rendered as:

One final trick is as I was including some .js files as Google Apps Script .gs script files I wanted to detect and call functions client side. I did this by detecting if jQuery was loaded:

if (typeof jQuery !== 'undefined') {
   // code to run client side only
}

One place I used this was storing options in localStorage client side and Properties service Server side in a script file that was used server and client side. Because Google Apps Script server calls execute asynchronously this is currently a bit of a mess and I’m sure can be refactored.

Deploying the Calendar Widget

If you’d like to use this Calendar Widget in your own Site follow these steps:

  1. File > Make a copy this Google Apps Script project
  2. In your copy click Resources > Advanced Google Services and switch Calendar API ‘on’. In the same dialog window click ‘Google API console‘ and in the console click ‘Enable APIs and Services‘ and search and enable the Calendar API.
  3. Once done back in the Script Editor click Publish > Deploy > Deploy as web app… and choose your deployment preference
  4. Open the Sites page where you’d like to add the web app.
  5. Select Insert > Embed URL.
  6. Paste in the web app URL and then click ADD.

Once setup the script owner can click on the settings cog in the widget to select which calendars are displayed.