use an include to include an html file that contains a script - google-apps-script

I am working on a Google Apps Script. My situation is that I have an index.html file and a few others which should all share a menu on the side.
I therefore have a function as follows
function include(File) {
return HtmlService.createHtmlOutputFromFile(File).getContent();
};
and use
<?!= include('leftMenu'); ?>
to include that in my html files.
The problem I have is that in the included file there is a function called that is defined in my Code.gs
<div class="leftmenu">
Main menu<br>
<?var url = getScriptUrl();?><a href='<?=url?>?page=newInvoice'>New invoice</a><br>
<?var url = getScriptUrl();?><a href='<?=url?>?page=index'>Home</a>
</div>
This function works as I would expect as long as these lines are in the "main" html file but they produce text if they are in the "included" html file.
I hope that makes sense and some one is kind enough to explain what the problem is and hopefully how I can get round it.
Thank you
Neill
14 Dec. 2016 edited to try and explain exactly what my problem is
I have a html file named “newinvoice.html”.
This has javascript functions in it as follows
<script type="text/javascript">
function formSubmit() {
google.script.run.withSuccessHandler(updateUrl).onSubmitButton(document.forms[0]);
}
function updateUrl(url) {
var successMsg = document.getElementById('output');
successMsg.innerHTML = 'New invoice created, saved and sent per Email';
}
</script>
I can move these functions into a separate html file as you suggested. This is called menu_JS.html and is included in my main file with
This works perfectly.
I have a call to one of these these functions - also in the main html “newinvoice.html” This is as follows
<div class="leftmenu">
Main menu<br>
<?var url = getScriptUrl();?><a href='<?=url?>?page=newInvoice'>New invoice</a><br>
<?var url = getScriptUrl();?><a href='<?=url?>?page=index'>Home</a>
</div>
If I move this into a separate file “leftMenu.html” and include that in “newinvoce.html” with
Then the output no longer works.
It appears that the scripts are trying to run before the files are included instead of the include and then the execution as I am used to from PHP.
As always, I appreciate anyone willing to take the time to help me. This is frustrating. Thank you!

Create another HTML file and put the script you want to run client side in that file. Then use the same include statement to include that file.
So make menu_JS.html and place your functions in that, between script tags:
<script>
firstFunction(){
alert("In the first function");
}
secondFunction(){
alert("In the second function");
}
</script>
And in your main HTML template file, preferable after the body loads, place:
<?!= include('menu_JS'); ?>
NOTE that the script is in an HTML file and NOT a Script file.
EDIT: Nov 15 2016
Below is the variation of the function which I have that is working for my needs. Note that I am evaluating the included html file. I had previously used code more similar to your (commented out) and changed it to this some time ago:
function include(filename) {
// return HtmlService.createHtmlOutputFromFile(filename)
return HtmlService.createTemplateFromFile(filename).evaluate()
.getContent();
}
//function includeRaw(filename) {
// return HtmlService.createTemplateFromFile(filename).getRawContent();
//}
And this is how I load the initial html file. This is often in the doGet() function, but may be elsewhere
var result=HtmlService.createTemplateFromFile('GridView').evaluate()
.setTitle('Boxwood Registrations')
.setWidth(1285)
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
return result;

Related

Transfering output from GAS(Google App Script) to html

I'll make the succeeding programs which transfers URL defined by GAS to html.
In this time, I set URL as fix letters for simplification, however,
in the actual situations, URL is generated uniquely in every trial.
function getUrl() {
var url = "https://www.google.co.jp/"
var html = HtmlService.createTemplateFromFile("dialog2").evaluate();
SpreadsheetApp.getUi().showModalDialog(html, "Download File");
}
// error ReferenceError: url is not defined # test.gs:3
html side (dialog2.html)
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
Click here
  <!--↑wanting to get url as a variable letters from the GAS program-->
</body>
</html>
I'm sure that the way of transfering the parameter (this time,url) is the crucial fautor to compile these codes.
If we cannnot get this plan into the practice, please tell me sub plans.
Thank you for checking this question.
I solved this problem by defining the paramerter url as property.
correct code (GAS)
function getUrl() {
var url = "https://www.google.co.jp/"
var html = HtmlService.createTemplateFromFile("dialog2");
html.url = url;
SpreadsheetApp.getUi().showModalDialog(html.evaluate(), "Download File");
}

Updating automatically an HTML content when the imported *.json values are changed

I have an HTML code that imports a LOCAL but UPDATABLE *.json content, and it must be updated automatically when the *.json file is updated.
This is the *.HTML code:
<html>
<head>
<script type="text/javascript" src="sample.json"></script>
<script type="text/javascript" >
function load() {
setInterval(function () {
var mydata = JSON.parse(data);
var div = document.getElementById('data');
div.innerHTML = mydata[0].location.altitude;
}, 100);}
</script>
</head>
<body onload="load()">
<div id="data">
</div>
</body>
</html>
and the adapted sample.json file is:
data = '[{"location": {"altitude": 40}}]';
I just wanna see the altitude is changing in the browser(HTML) whenever the sample.json file is updated.
Now the HTML works but only ONCE, I wanna make it dynamic.
What should I do to make the function setInterval work correctly? or maybe this function works only for local changes, not external ones.
Thnks, Sadeq
If you want the browser to get data from a URL even interval, then you need to write code which gets data from a URL in the interval. e.g. with the Fetch API. (At which point you should make it JSON instead of JS).
However HTTP is not fast. You do not want to be polling over HTTP every 100ms. Consider using Websockets to push the data from the server when it changes instead of polling.

Why would this function generate an http: 500 error on one of my files?

I started getting this error in a lot more complicated script and after a while I tried this extremely simple case. When I click the button I get the error: NetworkError: Connection failure due to HTTP 500
and of course I get the same thing in the console. I've moved it to another file and the error goes away.
gs:
function runTwo() {
SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutputFromFile('test'),'Title');
}
function getMessage() {
return 'Hello World';
}
html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<div id='msg1'></div>
<input type="button" value="Click Me" onClick="iveBeenClick();" />
<script>
function iveBeenClick() {
google.script.run
.withFailureHandler(msg=>{document.getElementById("msg1").innerHTML=msg;})
.withSuccessHandler(msg=>{document.getElementById("msg1").innerHTML=msg;})
.getMessage();
}
</script>
</body>
</html>
Just in case it matters, this file has a webapp deployed that works with a Gmail Addon to delete unwanted emails. And here's that code:
function doGet(e) {
Logger.log('query params: ' + Utilities.jsonStringify(e));
if(e.queryString !=='')
{
switch(e.parameter.mode){
case 'dable':
deleteAllBlackListedEmails2();
return ContentService.createTextOutput("delete black list Done!!!!");
break;
case 'append':
const length=appendToBlackList({deletes:e.parameter.bls});
return ContentService.createTextOutput(length);
break;
case 'length':
return ContentService.createTextOutput(getBlackListLength());
break;
default:
return ContentService.createTextOutput("<h1>Unknown Command: " + e.parameter.mode);
}
}else{
return ContentService.createTextOutput("No Query String");
}
}
I'd like to know what the problem is. But I don't know where to go from here. I could certainly live without knowing and it doesn't seem to be affecting the performance of the other functions but it does impact my ability to built interactive tools for analyzing my data because I can't use google.script.run on any of my dialogs. Anyway I thought I'd ask and see if anyone else might be able to get it to fail.
New Information
Problem went away when I removed a library that I just installed. What should I looked for in that library?
The Fix
Because I was unfamiliar with the new dialog I chose to use the head deployment and I really wanted version 31. I don't know why this causes such an error but the script seems to be back to normal now. I was lucky this time.
I just wanted to share with everyone a simple way to avoid the HTTP 500 problem described above. It's fairly simple to reproduce and looking back upon it I can see now that it occurred because I was unfamiliar with the new editor and I made the simple error of not selecting a version. Instead I left it the head deployments which is a problem.
This is my minimum complete verifiable example.
I created a simple library with only one function and I called it the HTTP500Library
The Function:
function selectColumnsSkipHeader() {
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sht=ss.getActiveSheet();
var rng=sht.getActiveRange();
var rngA= sht.getActiveRange().getA1Notation().split(':');
var ul=rngA[0].replace(/\d+/,'');
if(rng.getNumColumns()>1) {
var lr=rngA[1].replace(/\d+/,'');
}
else {
lr=ul;
}
var rngs=ul + rng.getRow() + ':' + lr;
var outrng=sht.getRange(rngs);
outrng.activate();
}
Then I deployed and actually due to a couple of stupid mistakes I have a couple of deployments
Then I created another spreadsheet called the HTTP500 Problem and I put this code into it:
Code.gs:
function onOpen() {
SpreadsheetApp.getUi().createMenu('My Tools')
.addItem('Simple Dialog', 'runTwo')
.addToUi();
}
function runTwo() {
SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutputFromFile('problem'),'Title');
}
function getMessage() {
return 'Hello World';
}
HTML:
function iveBeenClick() {
google.script.run
.withFailureHandler(msg=>{document.getElementById("msg1").innerHTML=msg;})
.withSuccessHandler(msg=>{document.getElementById("msg1").innerHTML=msg;})
.getMessage();
}
</html><!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<div id='msg1'></div>
<input type="button" value="Click Me" onClick="iveBeenClick();" />
<script>
function iveBeenClick() {
google.script.run
.withFailureHandler(msg=>{document.getElementById("msg1").innerHTML=msg;})
.withSuccessHandler(msg=>{document.getElementById("msg1").innerHTML=msg;})
.getMessage();
}
</script>
</body>
</html>
After setting up the problem I tested the dialog that I just created and it worked fine with no problems.
Then I added the library that I just created but because I was unfamiliar with the new editor I mistakenly chose the head deployment. In other words I didn't select a version.
I ran the dialog again and this time I recieved the Network Connection problem with the HTTP 500 error.
The next step should have been to realize that I didn't select the correct version and return to the dialog and do so and that would have fixed the problem.
So I guess the Network connection that cause the problem was the connection to the library. So don't forget to pick the appropriate deploy of your libraries when you install them.
Thank for all the help

refresh data read from text file with out page refresh

i am a novice at Java and JS so this will be very basic.
I've got this code that creates a text file in a specific directory. i only got as far as creating an actuale file, however, as the text file will be frequantely updated, i need the page to refresh/reload the text file and display it's data (just in the blank page). How do i do this, with out user needed to click refresh (auto refresh in sense, however, i've tried auto refresh and it does not seem to reload JS and/or display text file's content)
Create Text file/Read/Display content/Refresh and/or Reload - no user refresh
<script>
function createFile()
{
var object = new ActiveXObject("Scripting.FileSystemObject");
var file = object.CreateTextFile("C:/Documents and Settings/galimbek.sagidenov/My Documents/Practice HTML_Photoshop_java/BroadcastTest.txt", false);
file.WriteLine('Hello World');
file.WriteLine('Hope is a thing with feathers, that perches on the soul.');
file.Close();
}
</script>
this will not accomplished by using client side javascript only you have to use server side code:
server ex (using node.js):
server :
var http = require("http"),
fs=require("fs");
http.createServer(function(request, response) {
fs.writeFileSync("C:/Documents and Settings/galimbek.sagidenov/My Documents/Practice HTML_Photoshop_java/BroadcastTest.txt", 'Hello World\r\nHope is a thing with feathers, that perches on the soul.');
}).listen(8888);
client
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
$(function(){
$.get("http://localhost:8888",function(){
console.log("writing to file successeded");
})
})
</script>

Google App Scripts : Javascript code inside the HTML file not functioning

I have been trying to write a small Google App Script which has the Google+ badge as shown here. For this I have a plain HTML file where I have included the HTML as shown on that page. The HTML page is as follows :
<html>
<body>
<div class="g-plus" data-href="{Page-Link}" data-rel="publisher"></div>
<script type="text/javascript">
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/plusone.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
alert("Added Badge!");
})();
</script>
</body>
</html>
The result is a blank page. There is no badge added to the page . I assume this is because the javascript function is not being run( I added an alert and there wasnt any pop-up ).I am not able to figure out why the function is not being run.
Any help is appreciated.
Unfortunately I'm not too experienced with Javascript so I'm guessing here. I've programmed in coffeescript a while ago and its compiler automatically wraps the generated code in an anonimous function just as in your code. This function is called so:
(function() {//...}).call(this);
Maybe this works.
Alternatively you might want to move the alert test above the badge generation. This would show if the javascript is run at all. Maybe the error lies in your badge creation code.
My final idea would be to name your function and register it as a callback on body.onload . It's always a good idea to let the browser load the page before accessing the dom