The Drive and Google Apps scripting features have developed over time and I have tried using
- Google Apps Script UI Service
- Google Apps Script HTMLService
- Custom App called through the Google Drive interface
- Google Drive Filepicker
- Google Drive SDK through Javascript
For me, using the Google Drive SDK has proven the simplest to build into a responsive user interface and best performing for the user.
The UI Service approach provided an early introduction to interacting with Google Apps script but it is very limited in function and locks the user interface into the script. It carries all the overheads of generating the user interface at run time as well.
HTMLService does provide the familiarity of HTML/CSS/JS development but has limitations and performance impacts caused by CAJA.
Calling a Google Apps Script from the Google Drive user interface suits users who spend there time interacting with Drive directly but selection of action on folder/file becomes a multiclick operation and subsequent user interface has the limitations of HTMLService .
The filepicker provided for Google Drive is functional and has the advantage of being ready to use with good performance. However the pop-up iframe approach may not suit all design styles and customisation is limited. In particular, presenting the file/folder list initially random order slows down the user interaction.
The direct use of the Google Drive SDK has been simplified recently by improved documentation of the authorisation process. I took the quickstart example and built an html page of links from folder names corresponding to people of interest. It is then simple to incorporate this into a comprehensive user interface for the business user.
Performance and flexibility is the key for this approach. I get a few hundred folder references generate in 3 seconds and can then have a js expert work in there usual toolset to develop responsive bootstrap, jQuery or whatever interface style is required.
Modifed Quickstart example.
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<script type="text/javascript">
var CLIENT_ID = '70v406.apps.googleusercontent.com';
var SCOPES = 'https://www.googleapis.com/auth/drive';
/**
* Called when the client library is loaded to start the auth flow.
*/
function handleClientLoad() {
console.log('handleClientLoad:'+new Date().getTime())
window.setTimeout(checkAuth, 1);
}
/**
* Check if the current user has authorized the application.
*/
function checkAuth() {
console.log('CheckAuth:'+new Date().getTime())
gapi.auth.authorize(
{'client_id': CLIENT_ID, 'scope': SCOPES, 'immediate': true},
handleAuthResult);
}
/**
* Called when authorization server replies.
*
* @param {Object} authResult Authorization result.
*/
function handleAuthResult(authResult) {
console.log('handleAuthResult:'+new Date().getTime())
var authButton = document.getElementById('authorizeButton');
authButton.style.display = 'none';
if (authResult && !authResult.error) {
// Access token has been successfully retrieved, requests can be sent to the API.
getItems();
} else {
// No access token could be retrieved, show the button to start the authorization flow.
authButton.style.display = 'block';
authButton.onclick = function() {
gapi.auth.authorize(
{'client_id': CLIENT_ID, 'scope': SCOPES, 'immediate': false},
handleAuthResult);
};
}
}
/* List folders based on a search
* specify the owning folder and mimetype = folder in the search parameter (q)
* set maxResults (can do paged calls if actual results exceed 1000)
*/
function getItems() {
console.log('getItems:'+new Date().getTime())
var start = new Date();
var request = gapi.client.request({
'path': 'drive/v2/files',
'method': 'GET',
'params': {
'q': 'mimeType="application/vnd.google-apps.folder" and "0B90FGJizRd-gX25PTS1CTUF0eHM" in parents and trashed = false',
'maxResults': '400'
}
});
request.execute(listItems);
console.log("elapsed: "+(new Date()-start))
}
/* Sort the result returned from drive api into title order
* insert html paragraph for each title
*/
function listItems(resp) {
console.log('listitems:'+new Date().getTime())
var start = new Date().getTime();
var result = resp.items.sort(function(a, b){
var nameA=a.title.toLowerCase(), nameB=b.title.toLowerCase()
if (nameA < nameB) //sort string ascending
return -1
if (nameA > nameB)
return 1
return 0 //default return value (no sorting)
});
console.log('items: '+result.length)
var i = 0;
var element = document.getElementById("div1"); // insertion point in html
for (i=0;i<result.length;i++) {
var para = document.createElement("p"); // create a link element in a para
var aref = document.createElement("a");
var node = document.createTextNode(result[i].title);
aref.setAttribute('href',result[i].alternateLink); // link to driver folder
aref.appendChild(node);
para.appendChild(aref);
element.appendChild(para);
}
console.log("elapsed: "+(new Date().getTime()-start));
}
</script>
<script type="text/javascript" src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script>
</head>
<body>
<input type="button" id="authorizeButton" style="display: none" value="Authorize" />
<h1>List</h1>
<div id='div1'></div>
</body>
</html>