-
-
-
-
- March 14 addition
-
-
-
Why would data returned by a function not be seen by its successHandler function?
Here is a smaller example:
<!DOCTYPE html>
<html>
<head>
<!-- tinyTestHtml.html -->
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Choose a class</title>
<base target="_top">
<?!= HtmlService.createHtmlOutputFromFile('cssStyle').getContent(); ?>
</head>
<body>
This is the body
<script>
window.onload = function() {
console.log('hah! it ran. ');
google.script.run
.withSuccessHandler(afterServerRepl)
.listCourses();
};
window.afterServerRepl = function(e) {
console.log('Server reply was successful!');
console.log(JSON.stringify(e) );
};
</script>
</body>
</html>
The console logs in listCourses show data found and returned but the successHandler JSON.stringify prints null. This code is from Run a Google apps script automatically upon loading a Google Site? I do not know how to write functions in that format but it was from Alan Wells and was the accepted answer. posted new question GAS Data from server side function not seen in successHandler function in HTML
-
-
-
-
-
- end March 14 addition
-
-
-
-
I found the picker very difficult especially when creating code to share. I have had the Tanaike https://gist.github.com/tanaikech/96166a32e7781fee22da9e498b2289d0 working as written and have used it for only folders or only spreadsheets. I have tried to create a more generalized version and now even though getFiles logs show files found the importData function sees null. There is no code between these two as importData is called from the successHandler.
-
-
-
-
- March 13
-
-
-
this code is pretty much as Tanaike wrote it other than I am passing a mime type. It works when I select folders but fails when I select spreadsheets.
$(function() { console.log('1 unnamed function' ); const rootfolderId = "root"; console.log('2 before call getFiles w 2 rootfolderId: ' + rootfolderId ); console.log(' mimeType: ' + mimeType ); google.script.run .withSuccessHandler(importData) .getFiles(rootfolderId, rootfolderId, mimeType ); console.log('3 after successHandler(importData) .getFiles(rootfolderId' );
The console logging is below
in initialize
1 unnamed function
2 before call getFiles w 2 rootfolderId: root
mimeType: application/vnd.google-apps.spreadsheet
3 after successHandler(importData) .getFiles(
0 in importData e: null
userCodeAppPanel:136 Uncaught TypeError: Cannot convert undefined or null to object
at Function.keys (<anonymous>)
at importData (userCodeAppPanel:136)
at ef (VM9 47138931-mae_html_user_bin_i18n_mae_html_user.js:74)
at VM9 47138931-mae_html_user_bin_i18n_mae_html_user.js:15
at kg.P (VM9 47138931-mae_html_user_bin_i18n_mae_html_user.js:102)
at Kd (VM9 47138931-mae_html_user_bin_i18n_mae_html_user.js:50)
at a (VM9 47138931-mae_html_user_bin_i18n_mae_html_user.js:48)
The logging from the call to getFiles shows lots of data but the successHandler(importData) sees NULL! Where did the data disappear to?
- Problem: the console log message "3 after successHandler(importData) .getFiles(" is written out before the message that importData failed. I guess this is just a timing issue.
-
-
-
-
- end March 13 update
-
-
-
The html
<!DOCTYPE html>
<html>
<head>
<!-- tanaikeFileListHtml.html -->
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>tanaikeFileListHtml</title>
<base target="_top">
<!-- Tanaike's code -->
<!-- https://gist.github.com/tanaikech/96166a32e7781fee22da9e498b2289d0 -->
<style>
... left out for brevity
</style>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.js"></script>
<div id="parent">
<div id="child">
<!--https://stackoverflow.com/questions/30033459/how-to-pass-a-parameter-to-html -->
<!-- <h2 id="myTitle"></h2> -->
<!-- <h2 id="myTitle" class='notVisible'></h2> -->
<h2 class='centeredBold'>Be patient!</h2>
<p class='centeredBold'>
<br />When you select a file or folder the window will close.
To backup select './' at the top of the list.
</p>
<select id="select_file"></select>
<p id="id"></p>
<span class='buttons'>
<button type='button' onclick='buttonClicked()'>Select</button>
<button type='button' onclick='google.script.host.close()'>Close</button>
</span>
<p id='data_in' class='notVisible'>
<?= passType ?>
</p>
</div>
</div>
<script>
var alldata = {};
var mimeType;
var passType;
function initialize() {
console.log('in initialize');
// get input type from the HTML
passType = document.getElementById("data_in").textContent;
passType = passType.replace(/\s/g, ''); // remove spaces
switch ( passType ) {
case 'folder' :
mimeType = 'application/vnd.google-apps.folder';
break;
case 'spreadsheet' :
mimeType = 'application/vnd.google-apps.spreadsheet';
break;
case 'slide' :
mimeType = 'application/vnd.google-apps.presentation';
break;
case 'document' :
mimeType = 'application/vnd.google-apps.document';
break;
case 'form' :
mimeType = 'application/vnd.google-apps.form';
break;
case 'EVERYTHING' :
console.log('passType EVERYTHING, setting mimeType to null');
mimeType = null;
break;
default :
console.log('input inType: ' + passType + ' setting mimeType to null');
mimeType = null;
}
}
// use onload or use jquery to call your initialization after the document loads
window.onload = initialize();
function buttonClicked() {
console.log('In buttonClicked');
var keys = Object.keys(alldata);
console.log('keys: ' + keys);
var selectedId = keys[keys.length-1]
console.log(' going to run returnSelId selectedId: ' + selectedId );
google.script.run
.withSuccessHandler(output)
.returnSelId( selectedId, passType );
console.log('after successHandler(output) .returnSelId(selectedId, inType)' );
google.script.host.close();
}
$(function() {
console.log('1 unnamed function' );
const rootfolderId = "root";
console.log('2 before call getFiles w 2 rootfolderId: ' + rootfolderId );
console.log(' mimeType: ' + mimeType );
google.script.run
.withSuccessHandler(importData)
.getFiles(rootfolderId, rootfolderId, mimeType );
console.log('3 after successHandler(importData) .getFiles(rootfolderId' );
// triggered by change in html select element with id='select_file'
$("#select_file").change(function() {
console.log('4 in $(\'#select_file\').change function' );
var id = $( '#select_file').val();
console.log(' id: ' + id );
var disp = $('#select_file option:selected').text();
if (~disp.indexOf("folder") || ~disp.indexOf("../")) {
$('#select_file > option').remove();
if (alldata[id]) {
var dat = {};
dat[id] = alldata[id];
console.log('5 before importData - dat: ' + dat );
importData(dat);
return;
} else {
console.log('6 after else - id: ' + id );
google.script.run
.withSuccessHandler(importData)
.getFiles(id, rootfolderId, mimeType );
console.log('7 after successHandler(importData) .getFiles(id ' );
return;
}
console.log('8 after ~disp.indexOf("folder") || ~disp.indexOf("../") ' );
return;
} else {
console.log('9 else - files not folders' );
$('#select_file > option').remove();
if (alldata[id]) {
var dat = {};
dat[id] = alldata[id];
console.log('10 before importData' );
console.log(' dat: ' + dat );
importData(dat);
return;
} else {
console.log('11 after else - id: ' + id );
google.script.run
.withSuccessHandler(importData)
.getFiles(id, rootfolderId, mimeType );
console.log('12 after call getFiles' );
return;
}
console.log('13 end else - files not folders' );
return;
}
// Replaced this with buttonClicked()
// google.script.run
// .withSuccessHandler(output)
// .returnSelId(selectedId, mimeType); ??
// .returnSelId(selectedId, inType); ??
});
});
/**
* gets data returned from successful call to getFiles
*/
function importData(e) {
console.log('0 in importData e: ', JSON.stringify(e) );
var key = Object.keys(e)[0];
console.log('1 key: ', key );
console.log('2 alldata[key]: ', alldata[key] );
if (!alldata[key]) alldata[key] = e[key];
console.log('3 alldata[key] set to e[key]' );
if (e[key]["keyparent"]) {
console.log('4 e[key]["keyparent"] exists' );
$('#select_file').append($('<option>')
.html("./" + e[key]["keyname"])
.val(key));
$('#select_file').append($('<option>')
.html("../")
.val(e[key]["keyparent"]));
} else {
console.log('5 e[key]["keyparent"] does not exist' );
$('#select_file').append($('<option>')
.html("./" + e[key]["keyname"])
.val(key));
}
for (var i=0; i < e[key]["files"].length; i++) {
$('#select_file').append($('<option>')
.html(e[key]["files"][i].mimeType == "folder" ? "[Folder]" + e[key]["files"][i].name : e[key]["files"][i].name)
.val(e[key]["files"][i].id)
);
}
}
function output(res) {
console.log('in output w res: ' + res);
$('#id').text(res);
}
</script>
</body>
</html>
The getFiles logging
Mar 9, 2021, 11:19:24 AM Debug - - - - - - - - - Begin getFiles inMimeType: application/vnd.google-apps.spreadsheet
Mar 9, 2021, 11:19:24 AM Debug da: {}
Mar 9, 2021, 11:19:25 AM Debug # files after folders.hasNext: 6
Mar 9, 2021, 11:19:25 AM Debug # files after files.hasNext: 6
Mar 9, 2021, 11:19:25 AM Debug # after sort: ; 5
Mar 9, 2021, 11:19:25 AM Debug # files after both while loops: 11
Mar 9, 2021, 11:19:25 AM Debug # files after both while loops JSON.stringify(data):
Mar 9, 2021, 11:19:25 AM Debug {"0AO8tjYr48IZIUk9PVA":{"keyname":"My Drive","keyparent":null,"files":[{"name":"FluencyTutor","id":"1_1SfrnyRdauXapevULnJ3ijZ-76Ewxnu","mimeType":"folder"},{"name":"Rosters","id":"1VLFlSzSn49TcNkNBjkEMavbxhZ8DEZ1n","mimeType":"folder"},{"name":"Meet Recordings","id":"1V2oiVRCQagj_BlERFuyExNCP-SQ92npA","mimeType":"folder"},{"name":"My book - I want to read better","id":"1_Y7yfTroZWfh_3dQRL_AUtgJ8Ot1vXRf","mimeType":"folder"},{"name":"Google App Scripts","id":"1LSX43dtlbZBeh2B9IOMyRZ8nL4pVNdq8","mimeType":"folder"},{"name":"Classroom","id":"0B-8tjYr48IZIflBPT2IxazdEc0lLZk8wcWxZQUZjbVNST3IyeVVFdTdKRGF6TVNWXzhrVHc","mimeType":"folder"},{"name":"Copy of Explore example","id":"153Osux5K0SYN2DrQ7WTspBFnfKrEl3L1eT8WF5Id2H0","mimeType":"application/vnd.google-apps.spreadsheet"},{"name":"2001-01-01T06:00:00.000Z","id":"1bB4yCQCRxyYpOsx3tzQIktKhiOAhlXAH6oU5gaviQX0","mimeType":"application/vnd.google-apps.spreadsheet"},{"name":"2019-20 ELL contact list","id":"1nzjE4IiCbnYH855pzTJN6TRs91hZVBUq3lioi_i6ZjU","mimeType":"application/vnd.google-apps.spreadsheet"},{"name":"2020-2021 AEL Teacher Rosters","id":"1tS0-s9pY7iVMcvqjpqGykYjs0bJM9VC6Uz3Ggg1QE1I","mimeType":"application/vnd.google-apps.spreadsheet"},{"name":"2020-2021 ESL Teacher Rosters","id":"1Ktuh7oDunCxKQo5Q2-1OY10Zsdc9ILEqPdg62Y4_THg","mimeType":"application/vnd.google-apps.spreadsheet"}]}}
Mar 9, 2021, 11:19:25 AM Debug End getFiles
The getFile code
function getFiles(e, rootFolderId, inMimeType) {
console.log('- - - - - - - - - Begin getFiles inMimeType: ', inMimeType );
var data = {};
var fileArr = [];
var idn = e;
e = e == "root" ? DriveApp.getRootFolder().getId() : e;
data[e] = {};
data[e].keyname = DriveApp.getFolderById(e).getName();
data[e].keyparent = idn == rootFolderId
? null : DriveApp.getFolderById(e).getParents().hasNext()
? DriveApp.getFolderById(e).getParents().next().getId() : null;
data[e].files = [];
var da = idn == "root" ? DriveApp.getRootFolder() : DriveApp.getFolderById(e);
console.log( ' da: ', da );
var folders = da.getFolders();
// console.log('folders.length: ', folders.length ); // undefined
var files = da.getFiles();
// console.log('files.length: ', files.length ); // undefined
while (folders.hasNext()) {
var folder = folders.next();
// console.log('push folder name: ', folder.getName() );
data[e].files.push({name: folder.getName(), id: folder.getId(), mimeType: "folder"});
}
console.log(' # files after folders.hasNext: ', data[e].files.length );
while (files.hasNext()) {
var file = files.next();
// console.log('file.getMimeType(): ', file.getMimeType());
if ( file.getMimeType() === 'folder' ) {;
// do not save any files
} else if ( file.getMimeType() === inMimeType ) {
// console.log('push fileArr name: ', file.getName() );
fileArr.push([file.getName(),file.getId(), file.getMimeType()]);
} else if ( inMimeType === 'EVERYTHING' ) {
fileArr.push([file.getName(),file.getId(), file.getMimeType()]);
}
}
console.log(' # files after files.hasNext: ', data[e].files.length );
let sorted = gasArraySort(fileArr, 0, true);
let numFiles = sorted.length;
console.log('# after sort: ;', numFiles );
for ( i = 0 ; i < numFiles ; i++ ) {
// console.log('pushing sorted[i][0]: ', sorted[i][0] );
data[e].files.push({name: sorted[i][0], id: sorted[i][1], mimeType: sorted[i][2]});
}
console.log(' # files after both while loops: ', data[e].files.length );
console.log(' # files after both while loops JSON.stringify(data): ');
console.log(' ', JSON.stringify(data) );
console.log('End getFiles');
return data;
}
Question 1: I am confused why I would see the log 3 ("3 after successHandler(importData) .getFiles(")which is after the getFiles / successHandler(importData) which apparently failed. Is this a timing issue? Did the log 3 happen before the importData blew up?
Question 2: Why is all the data returned from getFiles not seen in importData?