I'm trying to use ContentService, to serve JSONP in a webpage with Google Apps Script, following the samples provided in this link under "Serving JSONP in Web Pages" sub-topic.
GS code:
function doGet(request) {
var events = CalendarApp.getEvents(
new Date(Number(request.parameters.start) * 1000),
new Date(Number(request.parameters.end) * 1000));
var result = {
available: events.length == 0
};
return ContentService.createTextOutput(
request.parameters.prefix + '(' + JSON.stringify(result) + ')')
.setMimeType(ContentService.MimeType.JSON);
}
HTML/JS Code:
<script src="https://script.google.com/macros/s/AKfycbwZCY0qrZ09szGvKOttA30IaJkdMAZrh_oNnvv0qzCqFWyuO5Wc/exec?start=1325437200&end=1325439000&prefix=alert"></script>
I published it, by deploying the GS code as webapp
, with the following parameters:
- Executing the app as: User accessing the web app
- Who has access to the app: Anyone
Unfortunately, whenever I try to run/open the HTML file containing the code, I got the following error in browser's console, and nothing happens:
How to run this sample provided in Google Apps Script link without errors ?
[OPTIONAL] Investigating the issue in details:
The error found in resources files generate by the browser is as follows:
And the browser translated DOM is as follows:
<html>
<head>
<script src="https://script.google.com/macros/s/AKfycbwZCY0qrZ09szGvKOttA30IaJkdMAZrh_oNnvv0qzCqFWyuO5Wc/exec?start=1325437200&end=1325439000&prefix=alert">
</script>
</head>
<body></body>
</html>
The generated link, in my case is:
"https://script.google.com/macros/s/AKfycbwZCY0qrZ09szGvKOttA30IaJkdMAZrh_oNnvv0qzCqFWyuO5Wc/exec?start=1325437200&end=1325439000&prefix=alert"
If this link is placed in browser address bar, it shows the following message:
which means that the returned authorization response wasn't able to be displayed on browser and being translated as valid DOM.
How to overcome this issue ?
JSONP requires any one of the following to work:
- anonymous access, which isn't available with the "user accessing the webapp" mode - you need to run it as "execute as me".
- a script that doesn't use any services requiring authorization, in which case you can choose "user accessing the webapp." This will only work for users logged into Google, and the only advantage of using it over the previous mode is that any quota for services used will be applied per user rather than across all users of the webapp. In general, prefer option 1 over this.
- a script that has been pre-authorized by the user. This will also only work for logged-in users, but it will let you use any services. See below for how to use this.
I am assuming that you are trying to use 3 - otherwise, use 1 and it will just work. If you do need 3 (for example, a JSONP service that accesses the user's email) you will have to give them the ability to authorize the service before it will work. To do that, add something like this to your doGet():
function doGet(e) {
if (e.parameter.auth)
return HtmlService.createHtmlOutput('Thank you! Now the script can run!');
// ... rest of your code
}
Then you can give users a link to script.google.com/YOUR_SCRIPT_URL?auth=1 which they can visit. (The value 1 doesn't matter... any value will do). They will get the authorization page, and if they accept the authorization they will see your thank you message and the JSONP service will work for them. This only has to be done once... the script will remember the authorization the next time the user visits your page, unless you've changed it to require new permissions or the user has revoked the authorization.
The problem is the jsonp "script" you are trying to execute in your client code is not valid Javascript, as you show, it is the authorisation html web-page. Once authorised it should be fine. Though, as the tutorial says, when deploying the web-app you can execute the app as yourself ("me") and then allow access to "anyone, even anonymous" and you won't get any prompts for authorisation. Though that obviously has somewhat different behaviour, in terms of looking at your calendar vs the user's. Corey G offers a nice way to prompt for authorisation initially.
Serving JSONP in any Web Pages always throws an error :
Uncaught SyntaxError: Unexpected identifier
That may be corrected but is expected, because it's sending data to an external page, out of GAS environment (UiApp or HTMLservice).. if you create a own javascript function on the client side, ServiceContent works well..
the Apps Script code :
function doGet(e) {
// ..more code
lReturn = true;
var mymessage = (lReturn==true) ? "your contact details are saved ! ":" data no saved.. ";
var result = { status: lReturn, message : mymessage };
return ContentService.createTextOutput(
e.parameter.prefix + '(' + JSON.stringify(result) + ')')
.setMimeType(ContentService.MimeType.JSON);`
}
and Javascript code (using JQuery) :
var url = <your Apps Script URL>?prefix=myabc
$.ajax({
type: "GET",
url: url1,
data: {callback:"?"},
dataType: "script"
}).done( function( data ) {
console.log(data); //data returned : UNDEFINED
});
and your own javascript function:
function myabc(data) {
//alert(data);
//alert(data.message);
//var xyz = JSON.stringify(data);
//alert(xyz);
alert(data.message);
}
best regards
@Mlaynes
http://mlaynessanchez.blogspot.com
For ajax calls you must on the server side use setMimeType (ContentService.MimeType.JAVASCRIPT);