xxxxxxxxxx
<html>
<head>
<meta charset="utf-8">
<style type="text/css">
.skeleton {
display: none;
visibility: hidden;
}
</style>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="//apis.google.com/js/client.js?onload=init"></script>
<script type="text/javscript" src="//apis.google.com/js/api.js"></script>
<script type="text/javscript" src="https://apis.google.com/js/auth.js?onload=init"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
var key = "AIzaSyDNpgpDX4hLq2TdiBqvrKKyqmuLxqeY-L4";
var appId = 'glucose-calendar';
var clientId = '244880377962.apps.googleusercontent.com';
</script>
</head>
<body>
<h1>javascript only fetch google calendar events</h1>
<img src="1x1.gif" />
<h2>Howdy, <span class="username">???</span></h2>
<p>
This demo doesn't implement glucose fetching, just the google auth + google
query seps.
I'd like to know your email address
<span class="email">, so I can look up your calendars</span>.
In later demos, I'm also going to inspect your profile to see if I can find any
glucose records. Then I'm going to graph both events from your calendar and
your glucose records together. This assumes your are a google plus user, and
have a git <tt>phr</tt> link with a file called sugars.csv.
We use d3 to create a results row in a table for each calendar event.
</p>
<div id="content"></div>
<div id="events">
<div id="range">
<h4>Start: <span id="start"></span></h4>
<h4>End: <span id="end"></span></h4>
</div>
<table id="list">
<tbody class="skeleton">
<tr class="event">
<td><span class="v start"></span></td>
<td><span class="v end"></span></td>
<td><span class="v summary"></span></td>
<td><span class="v location"></span></td>
<td><span class="v detail"></span>
<a class="more htmlLink">more</a>
</td>
<td><span class=""></span></td>
<td> </td>
</tr>
</tbody>
<tbody="target">
</tbody>
</table>
</div>
<script type="text/javascript">
// The default "private/full" feed is used to retrieve events from
// the primary private calendar with full projection
var feedUri = 'https://www.google.com/calendar/feeds/bewest@gmail.com/private/full';
var scope = "https://www.google.com/calendar/feeds/";
scope = scope + ' ' + "https://www.googleapis.com/auth/plus.me";
scope = scope + ' ' + "https://www.googleapis.com/auth/userinfo.email";
scope = scope + ' ' + "https://www.googleapis.com/auth/userinfo.profile";
var loginUrl = 'https://accounts.google.com/o/oauth2/auth';
var cb_url = "https://localhost:4545/#oauthCallback";
var opts = {
};
gapi.load('auth', init);
function init ( ) {
// console.log('init', 'setting api key', this, arguments, gapi);
handleClientLoad( );
// gapi.client.setApiKey(key);
// $(document).trigger('auth');
}
$(document).on('auth', function ( ) {
console.log('got auth event from head');
checkAuth( );
});
// Error handler to be invoked when getEventsFeed() produces an error
var handleError = function(error) {
console.log(error);
}
// google.setOnLoadCallback(setup_login);
function handleClientLoad() {
// console.log('setting api key');
gapi.client.setApiKey(key);
window.setTimeout(checkAuth,1);
}
function checkAuth() {
// console.log('checking auth... performing auth');
gapi.auth.authorize({client_id: clientId, scope: scope }, handleAuthResult);
}
function handleAuthResult(authResult) {
// console.log('auth result', this, arguments);
if (authResult && !authResult.error) {
// console.log('success logging in');
makeApiCall();
} else {
// console.log('error logging in', authResult.error);
}
}
function handleAuthClick(event) {
gapi.auth.authorize({client_id: clientId, scope: scope, immediate: false}, handleAuthResult);
return false;
}
var user = { };
function makeApiCall( ) {
// console.log("hooray, can fetch events?");
gapi.client.load('plus', 'v1', function() {
var request = gapi.client.plus.people.get({
'userId': 'me'
});
request.execute(function(resp) {
// console.log('resp', resp);
var heading = document.createElement('h4');
var image = document.createElement('img');
image.src = resp.image.url;
heading.appendChild(image);
heading.appendChild(document.createTextNode(resp.displayName));
document.getElementById('content').appendChild(heading);
});
});
gapi.client.load('oauth2', 'v2', function() {
var request = gapi.client.oauth2.userinfo.v2.me.get( );
request.execute(function (resp) {
// console.log('user info', resp);
user.info = resp;
jQuery('.username').text(resp.result.email);
jQuery('.email').text(resp.result.email).trigger('email');
});
});
gapi.client.load('calendar', 'v3', function() {
// console.log('loaded google calendar support?', this, arguments);
var request = gapi.client.calendar.calendarList.list( );
request.execute(function (resp) {
// console.log('got a calendars list response', resp );
});
});
}
jQuery(document).on('email', function ( ) {
// console.log('email known, fetching calendar data', 'user', user);
var email = user.info.email;
gapi.client.load('calendar', 'v3', function() {
var opts = {
calendarId: email,
singleEvents: 'true',
orderBy: 'startTime',
timeMin: '2010-01-01T00:00:00Z'
};
// console.log('entry list opts', opts);
var events_list = gapi.client.calendar.events.list(opts);
events_list.execute(function (resp) {
// console.log('got a events list response', resp);
user.events = resp.result.items;
list_events(user.events);
});
});
});
function dup_row(skel) {
// console.log('return factory for dup row', this, arguments);
return (function (data, i) {
// console.log('dup row', this, arguments);
var row = skel.clone(true).addClass('row');
for (x in data) {
if (data[x].toString( ) != '[object Object]') {
row.find('.v.' + x).text(data[x]);
} else {
// console.log('???', x, data[x]);
}
}
row.find('.end').text(data.end.dateTime || data.end.date);
row.find('.start').text(data.start.dateTime || data.start.date);
row.find('A.htmlLink').attr('href', data.htmlLink);
// console.log('done with row', row);
return d3.select(jQuery(this).append(row)[0]);
});
}
var iso_day = d3.time.format("%Y-%m-%d");
var parse_dt = /(.*)-(\d\d):(\d\d)$/;
var iso_daytime = d3.time.format("%Y-%m-%dT%H:%M:%S");
function parse_date(d) {
if (d.start.dateTime) {
var p = d.start.dateTime.match(parse_dt);
var s = p[1];
return iso_daytime.parse(s);
}
return iso_day.parse(d.start.date);
};
function list_events(list) {
// console.log('working with list', list);
list.forEach(function (d) { d.ts = parse_date(d); });
var skeleton = jQuery('#list .skeleton').clone(true).removeClass('skeleton');
var duper = dup_row(skeleton);
var timeRange = d3.extent(list, function(d) {
// console.log(this, arguments);
return d.ts; });
jQuery('#range #start').text(timeRange[0]);
jQuery('#range #end').text(timeRange[1]);
var rows = d3.select('#list').selectAll('.row').data(list).enter( ).select(duper);
}
</script>
</body>
</html>
Modified http://d3js.org/d3.v3.min.js to a secure url
https://d3js.org/d3.v3.min.js
https://apis.google.com/js/client.js?onload=init
https://apis.google.com/js/api.js
https://apis.google.com/js/auth.js?onload=init
https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js