How to get multiple selected images from Google Picker API - javascript

I want to call back the thumbnail URL of selected images (multiple selected image) from Google Picker using Google Picker API (javascript). But the result only first selected image (1 image only). Anyone can help me to fix this problem?
Screenshot:
Below is my javascript API:
<!-- START PICKER -->
<button type="button" id="pick">Pick File</button>
<pre id="fileInfo"></pre>
<script>
(function() {
/**
* Initialise a Google Driver file picker
*/
var FilePicker = window.FilePicker = function(options) {
// Config
this.apiKey = options.apiKey;
this.clientId = options.clientId;
// Elements
this.buttonEl = options.buttonEl;
// Events
this.onSelect = options.onSelect;
this.buttonEl.addEventListener('click', this.open.bind(this));
// Disable the button until the API loads, as it won't work properly until then.
this.buttonEl.disabled = true;
// Load the drive API
gapi.client.setApiKey(this.apiKey);
gapi.client.load('drive', 'v2', this._driveApiLoaded.bind(this));
google.load('picker', '1', { callback: this._pickerApiLoaded.bind(this) });
}
FilePicker.prototype = {
/**
* Open the file picker.
*/
open: function() {
// Check if the user has already authenticated
var token = gapi.auth.getToken();
if (token) {
this._showPicker();
} else {
// The user has not yet authenticated with Google
// We need to do the authentication before displaying the Drive picker.
this._doAuth(false, function() { this._showPicker(); }.bind(this));
}
},
/**
* Show the file picker once authentication has been done.
* #private
*/
_showPicker: function() {
var accessToken = gapi.auth.getToken().access_token;
var view = new google.picker.DocsView();
view.setIncludeFolders(true);
this.picker = new google.picker.PickerBuilder()
.enableFeature(google.picker.Feature.NAV_HIDDEN)
.enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
.addView(google.picker.ViewId.DOCS_IMAGES)
.setAppId(this.clientId)
.setDeveloperKey(this.apiKey)
.setOAuthToken(accessToken)
.setCallback(this._pickerCallback.bind(this))
.build()
.setVisible(true);
},
/**
* Called when a file has been selected in the Google Drive file picker.
* #private
*/
_pickerCallback: function(data) {
if (data[google.picker.Response.ACTION] == google.picker.Action.PICKED) {
var file = data[google.picker.Response.DOCUMENTS][0],
id = file[google.picker.Document.ID],
request = gapi.client.drive.files.get({
fileId: id
});
request.execute(this._fileGetCallback.bind(this));
}
},
/**
* Called when file details have been retrieved from Google Drive.
* #private
*/
_fileGetCallback: function(file) {
if (this.onSelect) {
this.onSelect(file);
}
},
/**
* Called when the Google Drive file picker API has finished loading.
* #private
*/
_pickerApiLoaded: function() {
this.buttonEl.disabled = false;
},
/**
* Called when the Google Drive API has finished loading.
* #private
*/
_driveApiLoaded: function() {
this._doAuth(true);
},
/**
* Authenticate with Google Drive via the Google JavaScript API.
* #private
*/
_doAuth: function(immediate, callback) {
gapi.auth.authorize({
client_id: this.clientId,
scope: 'https://www.googleapis.com/auth/drive.readonly',
immediate: immediate
}, callback);
}
};
}());
</script>
<script>
function initPicker() {
var picker = new FilePicker({
apiKey: 'MY_API_KEY',
clientId: 'MY_CLIENT_ID-0bsroe3tqbfatoiie3h3qvaqtv4q0f5c.apps.googleusercontent.com',
buttonEl: document.getElementById('pick'),
onSelect: function(file) {
console.log(file);
document.getElementById('fileInfo').innerHTML = file.thumbnailLink;
}
});
}
</script>
<script src="https://www.google.com/jsapi?key=MY_API_KEY"></script>
<script src="https://apis.google.com/js/client.js?onload=initPicker"></script>
<!-- END PICKER -->

I see this line in your _pickerCallback method:
var file = data[google.picker.Response.DOCUMENTS][0]
Looks like copied from the Google example. Here, you always use only the first image of all selected ones.
Remove the [0] and it should work.

I hope I correctly understood your concern that you were able to select multiple images but returned result is only one. If it is, please try using Document.THUMBNAILS.
With this, an array of Thumbnails which describe the attributes of a photo or video will be in the Response.DOCUMENTS field in the callback data.
Important Note: Thumbnails will not be returned if the picked items belong to Google Drive.
Hope that helps!

Agreed with #crymis's answer. But he didn't provide the full solution.
Here is the code of pickerCallbak function:
_pickerCallback: function(data) {
if (data[google.picker.Response.ACTION] == google.picker.Action.PICKED) {
// get all selected files
var files = data[google.picker.Response.DOCUMENTS];
// loop over selected files
for (var i = 0; i < files.length; i++) {
// get file id, and request to get the file
var id = files[i][google.picker.Document.ID],
request = gapi.client.drive.files.get({
fileId: id
});
// execute request for file
request.execute(this._fileGetCallback.bind(this));
}
}
},
Note: to allow multiple selection in google drive picker dialog, you need to enable that feature while building picker with the following method,
.enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
(Kamarul Anuar, which you already did, so don't worry!)

Related

How to implement Gmail API using VueJS

I've recently been reading up on the Gmail API, and i want to implement it onto my web application, howeverf I am struggling to get the source code to work on VueJS.
<!DOCTYPE html>
<html>
<head>
<title>Gmail API Quickstart</title>
<meta charset="utf-8" />
</head>
<body>
<p>Gmail API Quickstart</p>
<!--Add buttons to initiate auth sequence and sign out-->
<button id="authorize_button" style="display: none;">Authorize</button>
<button id="signout_button" style="display: none;">Sign Out</button>
<pre id="content" style="white-space: pre-wrap;"></pre>
<script type="text/javascript">
// Client ID and API key from the Developer Console
var CLIENT_ID = '<YOUR_CLIENT_ID>';
var API_KEY = '<YOUR_API_KEY>';
// Array of API discovery doc URLs for APIs used by the quickstart
var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest"];
// Authorization scopes required by the API; multiple scopes can be
// included, separated by spaces.
var SCOPES = 'https://www.googleapis.com/auth/gmail.readonly';
var authorizeButton = document.getElementById('authorize_button');
var signoutButton = document.getElementById('signout_button');
/**
* On load, called to load the auth2 library and API client library.
*/
function handleClientLoad() {
gapi.load('client:auth2', initClient);
}
/**
* Initializes the API client library and sets up sign-in state
* listeners.
*/
function initClient() {
gapi.client.init({
apiKey: API_KEY,
clientId: CLIENT_ID,
discoveryDocs: DISCOVERY_DOCS,
scope: SCOPES
}).then(function () {
// Listen for sign-in state changes.
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);
// Handle the initial sign-in state.
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
authorizeButton.onclick = handleAuthClick;
signoutButton.onclick = handleSignoutClick;
}, function(error) {
appendPre(JSON.stringify(error, null, 2));
});
}
/**
* Called when the signed in status changes, to update the UI
* appropriately. After a sign-in, the API is called.
*/
function updateSigninStatus(isSignedIn) {
if (isSignedIn) {
authorizeButton.style.display = 'none';
signoutButton.style.display = 'block';
listLabels();
} else {
authorizeButton.style.display = 'block';
signoutButton.style.display = 'none';
}
}
/**
* Sign in the user upon button click.
*/
function handleAuthClick(event) {
gapi.auth2.getAuthInstance().signIn();
}
/**
* Sign out the user upon button click.
*/
function handleSignoutClick(event) {
gapi.auth2.getAuthInstance().signOut();
}
/**
* Append a pre element to the body containing the given message
* as its text node. Used to display the results of the API call.
*
* #param {string} message Text to be placed in pre element.
*/
function appendPre(message) {
var pre = document.getElementById('content');
var textContent = document.createTextNode(message + '\n');
pre.appendChild(textContent);
}
/**
* Print all Labels in the authorized user's inbox. If no labels
* are found an appropriate message is printed.
*/
function listLabels() {
gapi.client.gmail.users.labels.list({
'userId': 'me'
}).then(function(response) {
var labels = response.result.labels;
appendPre('Labels:');
if (labels && labels.length > 0) {
for (i = 0; i < labels.length; i++) {
var label = labels[i];
appendPre(label.name)
}
} else {
appendPre('No Labels found.');
}
});
}
</script>
<script async defer src="https://apis.google.com/js/api.js"
onload="this.onload=function(){};handleClientLoad()"
onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
</body>
</html>
I would like to convert this code into VueJS or atleast get it to work on my vue application. Would anyone be able to help me convert this?
There's nothing stopping you from setting the script tag programmatically in the mounted() hook, with document.createElement(), setAttribute(), document.appendChild() methods. Then wrap your gapi functions inside a try catch statement or use a promise, inspired by this tutorial (google maps): https://markus.oberlehner.net/blog/using-the-google-maps-api-with-vue/

SAPUI5: How to show a loading dialog box while pushing data to OData Service?

I am building a new SAPUI5 application without pursuing any template approach. What I'm building is just a little form with two fields and a button. AHHhh... "the button".
What about the button? The button has the following code:
<Button text="OK" width="100%" id="__button1" press="insertIntoOData"/>
With that, I expect that when I press the button, the insertIntoOData function is called. And guess what!? It is!
Fantastic!
But the problem is that in the insertIntoOData I want it to show a dialog (which is built with a fragment - check this link) while the OData model handles the insertion of a record. Unfortunately, I haven't managed to get the dialog to be shown. It looks like the insertIntoOData function is called synchronously, and won't show the dialog until the function is done.
When the OData Model finish handling the insertion, a response is processed and the dialog is shown only for a moment because, as you may notice in the following code of insertIntoOData, the navigation is redirected to the master (main) page.
insertIntoOData: function(evt) {
/*
* to prevent namespace issues, reserve 'this' into 'that',
* so the ajax will know who to call inside its scope
*/
var that = this;
//declare the dialog
if (!that._dialog) {
that._dialog = sap.ui.xmlfragment("valac.view.requestloading", null);
that.getView().addDependent(that._dialog);
}
// open dialog
jQuery.sap.syncStyleClass("sapUiSizeCompact", that.getView(), that._dialog);
that._dialog.open();
// get the csrf token from the service url
var csrfToken = this.getCSRFToken("/valacDestination/sap/c4c/odata/v1/c4codata/ValacObjectCollection");
// get the values from the 'form'
var name_var = this.byId("tSubjectInput").getValue();
var description_var = this.byId("tDescriptionArea").getValue();
// create the entry that will be sent with the request
var oEntry = {};
// the description list
oEntry.requestDescription = [];
// the description item that goes inside the list
var entryOfRequestDescription = {};
entryOfRequestDescription.Text = description_var;
oEntry.requestDescription.push(entryOfRequestDescription);
// name is a complex object that needs to be built. Content and language.
oEntry.Name = {};
oEntry.Name.content = name_var;
oEntry.Name.languageCode = "EN";
// fetch the model schema
var oModel = new sap.ui.model.odata.ODataModel("/valacDestination/sap/c4c/odata/v1/c4codata/");
sap.ui.getCore().setModel(oModel);
/* create the entry into the model schema via ajax
* return to the master page if there's a success response
* put a message on the master page.
*/
oModel.create('/ValacObjectCollection', oEntry, null, function(response){
that._dialog.close();
sap.ui.core.UIComponent.getRouterFor(that).navTo("master");
sap.m.MessageToast.show("Object Persisted!", {
duration: 30000000
});
},function(){
that._dialog.close();
sap.m.MessageToast.show("ERROR!", {
duration: 30000000
});
});
}
My question is: How can I show the dialog before the insertIntoOData ends or calls the oModel.create function?
when you enter the insertIntoOData method.
before calling the service set
that._dialog.setBusy(true);
after getting service responce (sucess or error don't matter )set as
that._dialog.setBusy(false);
You can do global busy indicator or component busy indicator, show before oModel.create and hide into the success or error function:
sap.ui.core.BusyIndicator.show(0); <- Parameter is delay time.
sap.ui.core.BusyIndicator.hide(); <- hide
link docs: https://sapui5.hana.ondemand.com/1.44.18/explored.html#/sample/sap.ui.core.sample.BusyIndicator/preview
Only the Dialog show busy.
that._dialog.setBusy(true); <- Show
that._dialog.setBusy(false); <- hide
I've managed to show the busyIndicator.
I rebuilt the insertIntoOData function to be as the following:
insertServiceRequestIntoOData: function(evt) {
var that = this;
var token = null;
var serviceUrl = "URL";
var name_var = this.byId("tSubjectInput").getValue();
var description_var = this.byId("tDescriptionArea").getValue();
var oEntry = {};
/*
* oEntry building process omitted
*/
this.oModel = new sap.ui.model.odata.ODataModel(serviceUrl);
sap.ui.getCore().setModel(this.oModel);
/*
* This is where the magic happens:
* 1) ajax async request to get the token and to show the busy indicator on the screen
* 2) when it's over, make a post to the oData service with the data.
* 3) when it's over, hide the busy indicator and go to the correct page (success or error).
*/
$.ajax({
url: serviceUrl + "/MyCollection";
type: "GET",
async: true,
beforeSend: function(xhr) {
sap.ui.core.BusyIndicator.show(0);
xhr.setRequestHeader("X-CSRF-Token", "Fetch");
},
complete: function(xhr) {
token = xhr.getResponseHeader("X-CSRF-Token");
// begin of odata send
that.oModel.create("/MyCollection", oEntry, null, function(response){
sap.ui.core.BusyIndicator.hide();
sap.ui.core.UIComponent.getRouterFor(that).navTo("insertConfirmation");
that.clearInputs();
},function(){
sap.ui.core.BusyIndicator.hide();
sap.ui.core.UIComponent.getRouterFor(that).navTo("insertErrorConfirmation");
that.clearInputs();
});
}
});
}

Failing to export variable defined in function to another concurrently-ran JS file

I have been reading different posts on Google and SO, but I just can't figure out why this does not work.
There are 2 HTML and 2 JS files involved in this case (explanation given below in words after the code chunks).
1) index.html
<div id="center">
<img id="logo" src="../img/logowshadow.png" alt="logo">
<p id="para">Get your google slides!</p>
<!--Add buttons to initiate auth sequence and sign out-->
<button id="authorize-button" style="display: none;">Sign in</button>
<button id="signout-button" style="display: none;">Sign Out</button>
</div>
<script src="../js/homePage.js"></script>
<script async defer src="https://apis.google.com/js/api.js"
onload="this.onload=function(){};handleClientLoad()"
onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
2) homePage.js
var apiKey = 'AIzaSyCSjg3rrx6Obl4ngZsDlFlV4degUJSMvbw';
var discoveryDocs = ["https://slides.googleapis.com/$discovery/rest?version=v1"];
var clientId = '408869653199-ruoft30vmoqrgpku3us3qd2leb3k6tp1.apps.googleusercontent.com';
var scopes = 'https://www.googleapis.com/auth/presentations.readonly https://www.googleapis.com/auth/drive';
var authorizeButton = document.getElementById('authorize-button');
var signoutButton = document.getElementById('signout-button');
var user;
var authResponse;
var oauthToken;
var pickerApiLoaded = false;
var chosenPresentation = null;
function handleClientLoad() {
// Load the API client and auth2 library
gapi.load('client:auth2', initClient);
//Load the Picker API
gapi.load('picker', onPickerApiLoad);
}
function initClient() {
gapi.auth2.init({
apiKey: apiKey,
discoveryDocs: discoveryDocs,
clientId: clientId,
scope: scopes
}).then(function () {
// Listen for sign-in state changes.
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);
// Set the current Google User
gapi.auth2.getAuthInstance().currentUser.listen(updateUser);
// Handle the initial sign-in state.
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
authorizeButton.onclick = handleAuthClick;
signoutButton.onclick = handleSignoutClick;
});
}
// Callback to make sure that the Picker API has loaded
function onPickerApiLoad() {
pickerApiLoaded = true;
createPicker();
}
// Store the current Google user
function updateUser(gUser) {
user = gUser;
updateToken();
}
// Store the access token
function updateToken() {
authResponse = user.getAuthResponse(true);
oauthToken = authResponse.access_token;
}
function updateSigninStatus(isSignedIn) {
if (isSignedIn) {
authorizeButton.style.display = 'none';
signoutButton.style.display = 'block';
createPicker();
} else {
authorizeButton.style.display = 'block';
signoutButton.style.display = 'none';
}
}
function handleAuthClick(event) {
gapi.auth2.getAuthInstance().signIn();
}
function handleSignoutClick(event) {
gapi.auth2.getAuthInstance().signOut();
}
// Create and render a Picker object for picking user slides
function createPicker() {
if (pickerApiLoaded && oauthToken) {
var picker = new google.picker.PickerBuilder().
addView(google.picker.ViewId.PRESENTATIONS).
setOAuthToken(oauthToken).
setDeveloperKey(apiKey).
setCallback(pickerCallback).
build();
picker.setVisible(true);
}
}
// Callback implementation
function pickerCallback(data) {
var url = 'nothing';
if(data[google.picker.Response.ACTION] == google.picker.Action.PICKED) {
var doc = data[google.picker.Response.DOCUMENTS][0];
url = doc[google.picker.Document.URL].replace('edit', 'present');
var item_name = doc[google.picker.Document.NAME];
alert('You picked ' + item_name);
//export the chosen presentation for use in mobileControl.js
chosenPresentation = doc[google.picker.Document.ID];
alert("chosen: " + chosenPresentation);
exports.chosenPresentation = chosenPresentation;
window.location.replace(url);
}
}
3) mobile.html
<div id="instructions">
<p>Swipe <b>left</b> to go to the previous slide.</p>
<p>Swipe <b>right</b> to go to the next slide.</p>
</div>
<script src="../js/mobileControl.js"></script>
and 4) mobileControl.js
alert("Loaded the JavaScript!"); //Shows up
var m = require('./homePage.js');
alert("imported"); //Does not show up
alert(m.chosenPresentation); //Does not show up
To put in words what my code is trying to achieve: users will be able to sign in to their google accounts, and select a set of Presentation found on their Google drive. I want to pass the Presentation ID on from homePage.js to mobileControl.js, and I attempted to do so using Node's exports. I suspect that it is not working because both scripts are run 'at the same time' (index.html is meant to run on the computer, while mobile.html runs on a mobile device...concurrently). But I am not sure if I am right in identifying the cause, and if so, is there a way to export the variable from within the function after it has been defined? Perhaps I should detect it when the slide has been selected, and only load mobilePage.js after everything in homePage.js has ran?
My apologies for the long read, but my previous attempt at diluting the example obviously failed miserably so...
Update: user #vsenko is totally right in saying that I have mixed up client-side programming and server-side programming, so do read up more on this if you are facing the same issue as me
As far as I can see, you are trying to load .js files with NodeJS specific API (RequireJS API to precise) directly on the web page. This is not going to work because browsers do not implement it natively. To utilize this API you will have to use a preprocessor (Webpack, Browserify or something else).
Other apparent problem with your approach is that you assume that it is possible to transfer data between different devices using something that look like NodeJS modules. But it is not possible, you will have transfer data over the network between your devices directly or though your server.

embed google drive picker as a part of page

I want to embed/implement Google Drive as a part of my page; like a normal grid or a table instead of having as a popup. I have took a reference from GoogleAPI page. Also, researched many things for my requirements but nothing would worked for me.
Here is the javascript code that I am using
// The Browser API key obtained from the Google API Console.
// Replace with your own Browser API key, or your own key.
var developerKey = 'xxxxxxxxxxxxxx';
// The Client ID obtained from the Google API Console. Replace with your own Client ID.
var clientId = "xxxxxxxxxxxx.apps.googleusercontent.com"
// Replace with your own project number from console.developers.google.com.
// See "Project number" under "IAM & Admin" > "Settings"
var appId = "xxxxxxxxxxxx";
// Scope to use to access user's Drive items.
var scope = ['https://www.googleapis.com/auth/drive'];
var pickerApiLoaded = false;
var oauthToken;
var picker;
// Use the Google API Loader script to load the google.picker script.
function loadPicker() {
gapi.load('auth', {
'callback': onAuthApiLoad
});
gapi.load('picker', {
'callback': onPickerApiLoad
});
}
function onAuthApiLoad() {
window.gapi.auth.authorize({
'client_id': clientId,
'scope': scope,
'immediate': false
},
handleAuthResult);
}
function onPickerApiLoad() {
pickerApiLoaded = true;
createPicker();
}
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
oauthToken = authResult.access_token;
createPicker();
}
}
// Create and render a Picker object for searching images.
function createPicker() {
if (pickerApiLoaded && oauthToken) {
var view = new google.picker.DocsView()
.setIncludeFolders(true)
.setOwnedByMe(true);
picker = new google.picker.PickerBuilder()
.enableFeature(google.picker.Feature.NAV_HIDDEN)
.enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
.setAppId(appId)
.setOAuthToken(oauthToken)
.addView(view)
.addView(new google.picker.DocsUploadView().setIncludeFolders(true))
.setDeveloperKey(developerKey)
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
}
}
// A simple callback implementation.
function pickerCallback(data) {
if (data.action == google.picker.Action.PICKED) {
var fileId = data.docs[0].id;
alert('The user selected: ' + fileId);
}
}
<button onclick="loadPicker(); return false;">Pick From Google Drive</button>
<div id="result"></div>
<!-- The Google API Loader script. -->
<script type="text/javascript" src="https://apis.google.com/js/api.js"></script>
Use PickerBuilder.toUri() instead of PickerBuilder.build().
It will return picker url and set this to iframe.
According to the issue reported here,
gapi.auth is deprecated. You should use gapi.auth2 instead.
From Google Developers
Use,
gapi.auth2.init({
client_id: 'CLIENT_ID.apps.googleusercontent.com',
scope : scope ,
});
and it will return a Promise
gapi.auth2.GoogleAuth
A full reference can be seen in the Google Developer Page
It sounds like you want to use the Google Drive API rather than the picker API.
This allows you to query drive for files without using the GUI.
https://developers.google.com/drive/v3/web/quickstart/js
The example in this quickstart prints out a list of files from the authorized account onto the page.

Extract upcoming events using Google Calendar API

I need to extract the first three upcoming events, in order of date, from Google Calendar to work with a new app I'm creating (a Pebble watchface).
I've used the JavaScript Quickstart at Google Developers to create an html page to extract the information I need. The code is below:-
<html>
<head>
<script type="text/javascript">
// Your Client ID can be retrieved from your project in the Google
// Developer Console, https://console.developers.google.com
var CLIENT_ID = 'CLIENT_ID_HERE';
// This quickstart only requires read-only scope, check
// https://developers.google.com/google-apps/calendar/auth if you want to
// request write scope.
var SCOPES = ['https://www.googleapis.com/auth/calendar.readonly'];
/**
* Check if current user has authorized this application.
*/
function checkAuth() {
gapi.auth.authorize(
{
'client_id': CLIENT_ID,
'scope': SCOPES,
'immediate': true
}, handleAuthResult);
}
/**
* Handle response from authorization server.
*
* #param {Object} authResult Authorization result.
*/
function handleAuthResult(authResult) {
var authorizeDiv = document.getElementById('authorize-div');
if (authResult && !authResult.error) {
// Hide auth UI, then load Calendar client library.
authorizeDiv.style.display = 'none';
loadCalendarApi();
} else {
// Show auth UI, allowing the user to initiate authorization by
// clicking authorize button.
authorizeDiv.style.display = 'inline';
}
}
/**
* Initiate auth flow in response to user clicking authorize button.
*
* #param {Event} event Button click event.
*/
function handleAuthClick(event) {
gapi.auth.authorize(
{client_id: CLIENT_ID, scope: SCOPES, immediate: false},
handleAuthResult);
return false;
}
/**
* Load Google Calendar client library. List upcoming events
* once client library is loaded.
*/
function loadCalendarApi() {
gapi.client.load('calendar', 'v3', listCalendars);
}
/**
* List all calendars and call listUpcomingEvents on each
* calendarID.
*/
function listCalendars()
{
var request = gapi.client.calendar.calendarList.list();
request.execute(function(resp) {
var calendars = resp.items;
appendPre('Check Console');
for (i=0;i<calendars.length;i++)
{
listUpcomingEvents(calendars[i]['id']);
}
});
}
/**
* Print the summary and start datetime/date of the next ten events in
* the authorized user's calendar. If no events are found an
* appropriate message is printed.
*/
function listUpcomingEvents(calendarID)
{
var calendarId = calendarID;
var request_events = gapi.client.calendar.events.list({
'calendarId': calendarId,
'timeMin': (new Date()).toISOString(),
'singleEvents': true,
'showDeleted': false,
'maxResults': 3,
'orderBy': 'startTime'
});
request_events.execute(function(resp) {
var events = resp.items;
for (i = 0; i < events.length; i++)
{
var event = events[i];
var when = event.start.dateTime;
if (!when) {
when = event.start.date;
}
appendPre(event.summary + ' (' + when + ')');
}
})
}
/**
* Append a pre element to the body containing the given message
* as its text node.
*
* #param {string} message Text to be placed in pre element.
*/
function appendPre(message) {
var pre = document.getElementById('output');
var textContent = document.createTextNode(message + '\n');
pre.appendChild(textContent);
}
</script>
<script src="https://apis.google.com/js/client.js?onload=checkAuth">
</script>
</head>
<body>
<div id="authorize-div" style="display: none">
<span>Authorize access to calendar</span>
<!--Button for the user to click to initiate auth sequence -->
<button id="authorize-button" onclick="handleAuthClick(event)">
Authorize
</button>
</div>
<pre id="output"></pre>
</body>
</html>
It works to a certain extent; however, if you have access to more than one calendar there is a problem. Instead of returning only three events taken from any calendar depending on the date, it returns three from EACH calendar so if you have 5 calendars you get 15 results, all grouped by calendar and not sorted by date.
Therefore, I would be grateful if anyone could help with the following:-
How can I fix the code so that I only get the NEXT three upcoming events, no matter which calendar it came from?
Also, how can I get the output to display in the standard format so that each element is recognisable when I call it, such as "event":( "summary": "Party", "start": "date" : 2015-11-30) I'm not sure how it goes.
Thanks very much in advance.

Categories

Resources