Parse Html using Google App Script - google-apps-script

I am trying to parse html using this script in Google app script
function parse() {
var html = UrlFetchApp.fetch('http://www.merriam-webster.com/').getContentText();
var doc = XmlService.parse(html);
var html = doc.getRootElement();
var element = getElementsByID(html, 'xx');
return element;
}
function getElementById(element, idToFind) {
var descendants = element.getDescendants();
for(i in descendants) {
var elt = descendants[i].asElement();
if( elt !=null) {
var id = elt.getAttribute('id');
if( id !=null && id.getValue()== idToFind) return elt;
}
}
}
But it says:
Error on line 27: Element type "scr" must be followed by either attribute specifications, ">" or "/>". (line 4, file "")
I am trying to parse html and then use getElementById function above.
any ideas?

I found that the best way to parse html in google apps is to avoid using XmlService.parse or Xml.parse. XmlService.parse doesn't work well with bad html code from certain websites.
Here a basic example on how you can parse any website easily without using XmlService.parse or Xml.parse. In this example, i am retrieving a list of president from "wikipedia.org/wiki/President_of_the_United_States"
whit a regular javascript document.getElementsByTagName(), and pasting the values into my google spreadsheet.
1- Create a new Google Sheet;
2- Click the menu Tools > Script editor... to open a new tab with the code editor window and copy the following code into your Code.gs:
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu("Parse Menu")
.addItem("Parse", "parserMenuItem")
.addToUi();
}
function parserMenuItem() {
var sideBar = HtmlService.createHtmlOutputFromFile("test");
SpreadsheetApp.getUi().showSidebar(sideBar);
}
function getUrlData(url) {
var doc = UrlFetchApp.fetch(url).getContentText()
return doc
}
function writeToSpreadSheet(data) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var row=1
for (var i = 0; i < data.length; i++) {
var x = data[i];
var range = sheet.getRange(row, 1)
range.setValue(x);
var row = row+1
}
}
3- Add an HTML file to your Apps Script project. Open the Script Editor and choose File > New > Html File, and name it 'test'.Then copy the following code into your test.html
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<input id= "mButon" type="button" value="Click here to get list"
onclick="parse()">
<div hidden id="mOutput"></div>
</body>
<script>
window.onload = onOpen;
function onOpen() {
var url = "https://en.wikipedia.org/wiki/President_of_the_United_States"
google.script.run.withSuccessHandler(writeHtmlOutput).getUrlData(url)
document.getElementById("mButon").style.visibility = "visible";
}
function writeHtmlOutput(x) {
document.getElementById('mOutput').innerHTML = x;
}
function parse() {
var list = document.getElementsByTagName("area");
var data = [];
for (var i = 0; i < list.length; i++) {
var x = list[i];
data.push(x.getAttribute("title"))
}
google.script.run.writeToSpreadSheet(data);
}
</script>
</html>
4- Save your gs and html files and Go back to your spreadsheet. Reload your Spreadsheet. Click on "Parse Menu" - "Parse". Then click on "Click here to get list" in the sidebar.

To parse the HTML you'll have to sanitize it, your page has a script tag that's written with Javascript as a String, more specifically:
document.write('<scr' + 'ipt src="' + src + '"></scr' + 'ipt>');})
XML parser doesn't understand Javascript code, obviously, so you'll have to sanitize this manually, not a simple thing to do, you can however build a simple RegEx selector, as:
function getElementsByID(element, idToFind) {
var regId = new RegExp( '(<[^<]*id=[\'"]'+ idToFind +'[\'"][^>]*)' );
var result = regId.exec( element );
return result[1] + '>';
}
function parse() {
var html = UrlFetchApp.fetch('http://www.merriam-webster.com/').getContentText();
var element = getElementsByID(html, 'search_box_terms');
return element; // "<input id="search_box_terms" name="query" type="text" placeholder="I'm searching for ..." value="" />"
}
This will return the string of the element the ID you provide. This of course is a simple RegEx and won't work in ALL cases, but will do pretty well for the most of them.

Related

How do you pass prompted data as a variable into a google docs bound script?

I have a rather large Google Doc (text file) that is divided into many chapters. It's a book that I am writing and from time to time, as I add chapters (often non-sequentially) I need to renumber all of the chapters. I do so in a two-step process: set all chapter numbers to a dummy placeholder, than replace all of those placeholders with the correct sequential numbers. I have been hard-coding the upper limit of the number of chapters, but now I'd like to change the process and take in a number of chapters from the user. I have written a prompt that does that.
What I cannot get to work is passing that number as a variable back into my script that is bound to the document. I tried to hack some code I have used successfully in a web app using Google script. But it doesn't work in this situation (bound script versus web app) and I can't debug where it is failing as it originates in the index html and Google's debugger won't track that (or I don't know how to make it track it). I have been unable to find any questions at stackoverflow that address the issue of how to pass a prompted variable back into a bound script in a Google Doc. I'm sure it will be obvious to any real programmers that I am "painting by the numbers" with Google script, but I do invest a lot of time trying to teach myself how to do this and your help is much appreciated. I really need to get this to work. The idea of having to manually renumber all these chapters every time I add ten or so is pretty depressing!
My code so far is:
function onOpen() {
var ui = DocumentApp.getUi();
ui.createMenu('Custom')
.addItem('Renumber Chapters', 'showDialog')
.addToUi();
}
function showDialog() {
var html = HtmlService.createHtmlOutputFromFile('Index')
.setWidth(400)
.setHeight(300);
DocumentApp.getUi()
.showModalDialog(html, 'Data Entry');
}
//Finds all numbered chapters and replaces with a placeholder "Chapter_"
function reChapter1(uObj){
var body = DocumentApp.getActiveDocument().getBody();
var numChaps = uObj.numChaps;
var n = numChaps;
var replaceTerm = "Chapter [0-9]+"
for (i = 0; i < n; i++) {
num = i+1
newText = "Chapter_";
Logger.log(newText);
replaceIt(replaceTerm, body);
}
}
function replaceIt(replaceTerm, body) {
var found = body.findText(replaceTerm);
if (found) {
var start = found.getStartOffset();
var end = found.getEndOffsetInclusive();
var text = found.getElement().asText();
text.deleteText(start, end);
text.insertText(start, newText);
}
}
//Finds placeholders and renumbers chapters
function reChapter2(uObj){
var numChaps = uObj.numChaps;
var n = numChaps;
var replaceTerm = "Chapter_"
var body = DocumentApp.getActiveDocument().getBody();
for (i = 0; i < n; i++) {
num = i+1
Logger.log(i);
newText = "Chapter "+num+"";
replaceIt(replaceTerm, body);
}
}
function replaceIt(replaceTerm, body) {
var found = body.findText(replaceTerm);
if (found) {
var start = found.getStartOffset();
var end = found.getEndOffsetInclusive();
var text = found.getElement().asText();
text.deleteText(start, end);
text.insertText(start, newText);
}
}
The html is:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body><center>
Enter the estimated number of current chapters plus ten*<br><br>
<input id="numChaps" type="text" placeholder="##"><br><br>
<button onclick="saveUserInput()">Click to Renumber Chapters.</button><br><br>
<font color=red><center><font size = "2">Click "X" icon on top right hand side of this dialog box to close it.</font><br><br>
<left><font color=black><font size = "2">*For instance, if your book currently has about 30 chapters that you want to renumber, enter 40. The extra ten are just in case you have a bunch of non-sequential chapter numbers and you are not totally sure how many current chapters you have.</font></left>
<script>
function saveUserInput() {
var numChaps = document.getElementById('numChaps').value;
console.log('numChaps: ' + numChaps);
google.script.run
.withSuccessHandler(openNewDoc)
.reChapter1({numChaps:numChaps});
.reChapter2({numChaps:numChaps});
}
function openNewDoc(results){
window.open(results.url, '_blank').focus();//this opens the html input page
}
</script>
</body>
</html>
The working scripts, without the attempt to prompt a user entry of the expected number of chapters is as follows:
function onOpen() {
var ui = DocumentApp.getUi();
ui.createMenu('Renumber Chapters')
.addItem('Run First', 'reChapter2')
.addItem('Run Second', 'reChapter')
.addToUi();
}
function reChapter(){
var n = 30;
var replaceTerm = "Chapter_"
var body = DocumentApp.getActiveDocument().getBody();
for (i = 0; i < n; i++) {
num = i+1
Logger.log(i);
newText = "Chapter "+num+"";
replaceIt(replaceTerm, body);
}
}
// replaces the occurrences
function replaceIt(replaceTerm, body) {
var found = body.findText(replaceTerm);
if (found) {
var start = found.getStartOffset();
var end = found.getEndOffsetInclusive();
var text = found.getElement().asText();
text.deleteText(start, end);
text.insertText(start, newText);
}
}
function reChapter2(){
var n = 30;
var replaceTerm = "Chapter [0-9]+"
var body = DocumentApp.getActiveDocument().getBody();
for (i = 0; i < n; i++) {
num = i+1
newText = "Chapter_";
Logger.log(newText);
replaceIt2(replaceTerm, body);
}
}
// replaces the occurrences
function replaceIt2(replaceTerm, body) {
var found = body.findText(replaceTerm);
if (found) {
var start = found.getStartOffset();
var end = found.getEndOffsetInclusive();
var text = found.getElement().asText();
text.deleteText(start, end);
text.insertText(start, newText);
}
}
I run "Run First" from the "Renumber Chapters" menu and then "Run Second" and that approach works fine as long as I have less than the number of chapters (in the case of this code, 30) hardcoded in the GS.
I have several scripts which I use when I'm writing and I store most of the data in Properties Service. You can access the scripts through a menu and prompt for the data and pass it to PS or you can build a dialog or use the sidebar to enter the data and save in PS.

How can I create a web app where I can read text from a sheet based on dropdown selections?

I am trying to create a role description generator which reads pre-written text from a Google Sheet and assembles it in blocks in a web app through selections (team, role, seniority level, etc.) in dropdown menus.
This is an example of what the data in the sheet looks like:
Team name
Team description
A-team
Description
B-team
Description
...
...
So far, for the team selection, I have created the dropdown menu which reads the data from the sheet, and pulls the names of each team into a dropdown list. But my problem is loading the corresponding team description text into the HTML page. I just can't seem to get it to work.
When pressing the generate button, what should happen is that the description for A-team is loaded, but instead I get [object MouseEvent].
Any suggestions? Thanks in advance! :)
Here's my code:
Code.gs
var url = "*spreadsheet URL*";
function doGet(e) {
return HtmlService.createTemplateFromFile('index')
.evaluate()
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
//get the data for the dropdown list
function valuesForList(list) {
//define the data
var ss = SpreadsheetApp.openByUrl(url)
var teamsSheet = ss.getSheetByName('Data');
var lastRow = teamsSheet.getLastRow();
var teamsRange = teamsSheet.getRange(1, 3, lastRow, 1);
//create a named range
ss.setNamedRange('teamsList', teamsRange);
//get the values from the range
var listValues = ss.getRangeByName(list).getValues();
return listValues;
}
//the function to show the data on the index.html
function PostInfo (userInfo){
//load the data
var ss = SpreadsheetApp.openByUrl(url);
var ws = ss.getSheetByName("Teams");
var data = ws.getRange(2,1,ws2.getLastRow(),2).getValues();
var teamList = data.map(function(r){ return r[0]});
var teamDesc = data.map(function(r){ return r[1]});
var position = teamList.indexOf(userInfo.teams);
if(position > -1){
return teamDesc[position];
} else {
return "Unavailable";
}
}
index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
<?!= HtmlService.createHtmlOutputFromFile('css').getContent(); ?>
<script>
function onListSuccess(list) {
var listLength = list.length;
for (i=0; i<listLength;i++) {
var dropdown = document.getElementById("teams");
var opt = document.createElement("option");
dropdown.options.add(opt);
opt.text = list[i][0];
opt.value = list[i][0];
}
}
function onListSelect(teamDesc){
var text = teamDesc.toString().split(",");
document.getElementById('est').innerHTML = text;
}
</script>
</head>
<body>
<div id="main">
<h1>Role Description Generator</h1>
<p>
<label for="teams">Team:</label>
</p>
<p>
<select name="teams" id="teams" tabindex="2"></select>
</p>
<button id="btn">Generate</button>
<div>
<label for="est">Team description:</label>
<p id="est" name="est"></p>
</div>
</div>
</body>
<script>
function populateList(){
google.script.run.withSuccessHandler(onListSuccess).valuesForList('teamsList');
}
document.getElementById("teams").addEventListener("change", doStuff);
document.getElementById("btn").addEventListener("click", onListSelect);
function doStuff(){
var userInfo = {};
userInfo.teams = document.getElementById("teams").value;
google.script.run.PostInfo(userInfo);
}
window.addEventListener('load', populateList);
</script>
</html>
Modification points:
In your script, when the dropdown list is changed, doStuff() is run. But in this case, google.script.run.PostInfo(userInfo) runs only the function of PostInfo at Google Apps Script. By this, the returned value is not used.
And, when the button is clicked, onListSelect is run. But in this case, teamDesc of onListSelect(teamDesc) is the event object. By this, such value of [object MouseEvent] is shown. I thought that this might be the reason of your issue.
By the way, when I saw your Google Apps Script, I noticed that PostInfo has a modification point. When var data = ws.getRange(2,1,ws2.getLastRow(),2).getValues(); is run, I think that an error occurs. Because ws2 is not declared. In your case, is that ws? I thought that this might be due to your miscopy.
When you want to show the value from PostInfo when the button is clicked, how about the following modification?
Modified script:
HTML&Javascript side:
From:
document.getElementById("teams").addEventListener("change", doStuff);
document.getElementById("btn").addEventListener("click", onListSelect);
function doStuff(){
var userInfo = {};
userInfo.teams = document.getElementById("teams").value;
google.script.run.PostInfo(userInfo);
}
To:
document.getElementById("btn").addEventListener("click", doStuff);
function doStuff(){
var userInfo = {};
userInfo.teams = document.getElementById("teams").value;
google.script.run.withSuccessHandler(onListSelect).PostInfo(userInfo);
}
Google Apps Script side:
From:
var ws = ss.getSheetByName("Teams");
var data = ws.getRange(2,1,ws2.getLastRow(),2).getValues();
To:
var ws = ss.getSheetByName("Teams");
var data = ws.getRange(2,1,ws.getLastRow(),2).getValues();
Note:
In this modidication, it supposes that the Google Apps Script works fine and returns the correct values. Please be careful this.
Reference:
Class google.script.run

Write data array from a google app script function to a HTML paragraph <p> tag

I have this google test sheet with dummy data that I have created for testing purposes
https://docs.google.com/spreadsheets/d/1Hxjr1ai6KWWJyyQLPJ2GRWYgQftyBxJmiKEu25Co2aQ/edit#gid=0
Crypto Data Image
By using google app script I have created a google web app with a HTML drop down box (select in HTML) that gets data from the above google sheet.
https://script.google.com/macros/s/AKfycbzYDDLg6YDNLBo-3jKQpcedU9jLJbxbOUDMh5YayKtVaurN2COq/exec
The google web app successfully displays the users selection from the drop down box in a HTML paragraph tag but the web app fails to display the data array for the selected cryptocurrency. The error message is "undefined".
I have just been doing this google app script stuff for a couple of weeks and I have a hard time understanding why the user selected array with data is not displayed on the HTML page.
My next step will be to try to plot the data the user selects from the HTML drop down box but before I can do that I need to visually confirm that the data is actually there.
If I select nano in the dropdown box this the data I get from the google apps script Logger.log:
[19-02-22 12:02:15:237 PST] The number of columns in sheet = 5
[19-02-22 12:02:15:238 PST] Crypto currencies in sheet = Bitcoin,Ethereum,Nano,Status,,,,,,,,,,,,,,,,,,,,
[19-02-22 12:02:15:241 PST] Dropdown box selection = Nano
[19-02-22 12:02:15:244 PST] Data to plot =0.9,0.8,0.7,0.8,
That tells me that the google app script is working but what is not working is the display of the data in the HTML paragraph tag on the website.
Code.gs
function getSelectList()
{
// puts crypto currency names in dropdown box on website
var ss = SpreadsheetApp.openById("1Hxjr1ai6KWWJyyQLPJ2GRWYgQftyBxJmiKEu25Co2aQ");
var sheet = ss.getSheetByName("Sheet1");
var lastRow = sheet.getLastRow();
var myRange = sheet.getRange("A2:A" + lastRow);
var data = myRange.getValues();
return data;
}
function Selection(crypto_name)
{
var ss = SpreadsheetApp.openById("1Hxjr1ai6KWWJyyQLPJ2GRWYgQftyBxJmiKEu25Co2aQ");
var sheet = ss.getSheetByName("Sheet1");
var name = sheet.getRange('A2:A101').getValues();
var Nc = sheet.getLastColumn();
Logger.log("The number of columns in sheet = " + Nc);
Logger.log("Crypto currencies in sheet = " + [name]);
Logger.log("Dropdown box selection = " + crypto_name);
for (i = 0; i < name.length; i++)
{
if(name[i]== crypto_name)
{
var TS = sheet.getRange(i+2,2,1,Nc).getValues();
Logger.log("Data to plot =" + [TS]);
}
}
return TS ;
}
function doGet()
{
return HtmlService.createHtmlOutputFromFile("Web");
}
Web.html
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<select id="MyBox" onchange="GetMyBox(this)"> </select>
<script>
(function()
{
google.script.run.withSuccessHandler( function (selectList)
{
var select = document.getElementById("MyBox");
for( var i=0; i<selectList.length; i++ )
{
var option = document.createElement("option");
option.text = selectList[i][0];
select.add(option);
}
}
).getSelectList();
}());
function GetMyBox(sel)
{
var crypto_name = sel.value;
document.getElementById("demo1").innerHTML = crypto_name;
var data = google.script.run.Selection(crypto_name);
document.getElementById("demo2").innerHTML = data;
}
</script>
<p id="demo1"></p>
<p id="demo2"></p>
</body>
</html>
This isn't intended to be a complete answer I just took your code and reformatted it a bit based upon what I think you're trying to accomplish. I didn't look at your code precisely but I'm pretty sure you still have some debugging to do.
In the html it looked like you want to use the JQuery ready function so I added some JQuery references to the head. If that wasn't your plan then you might want to change to window.onload.
html:
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body>
<select id="MyBox" onchange="GetMyBox(this)"> </select>
<script>
$(function() {
google.script.run
.withSuccessHandler(selectList)//You can just put the name of the function in this way
.getSelectList();
});
function GetMyBox(sel) {
var crypto_name = sel.value;
google.script.run
.withSuccessHandler(function(data){//you put an anonymous function this way
document.getElementById("demo2").innerHTML = data;
}
.Selection(crypto_name);
}
function selectList(data){
var select = document.getElementById("MyBox");
for( var i=0; i<data.length; i++ ) {
var option = document.createElement("option");
option.text = data[i][0];
select.add(option);
}
</script>
<p id="demo1"></p>
<p id="demo2"></p>
</body>
</html>
Google Script:
function getSelectList() {
// puts crypto currency names in dropdown box on website
var ss = SpreadsheetApp.openById("1Hxjr1ai6KWWJyyQLPJ2GRWYgQftyBxJmiKEu25Co2aQ");
var sheet = ss.getSheetByName("Sheet1");
var lastRow = sheet.getLastRow();
var myRange = sheet.getRange("A2:A" + lastRow);
var data = myRange.getValues();
return data;//this is a 2d array it might be what you want for select options
}
function Selection(crypto_name) {
var ss = SpreadsheetApp.openById("1Hxjr1ai6KWWJyyQLPJ2GRWYgQftyBxJmiKEu25Co2aQ");
var sheet = ss.getSheetByName("Sheet1");
var name = sheet.getRange('A2:A101').getValues();
var Nc = sheet.getLastColumn();
Logger.log("The number of columns in sheet = " + Nc);
Logger.log("Crypto currencies in sheet = " + [name]);
Logger.log("Dropdown box selection = " + crypto_name);
for (i = 0; i < name.length; i++) {
if(name[i]== crypto_name) {
var TS = sheet.getRange(i+2,2,1,Nc).getValues();
Logger.log("Data to plot =" + [TS]);
}
}
return TS ; //this is a 2d array so it's not ready for html yet
}
After spending some time on the problem I figured it out. I will therfore answer my own question since no one is willing to provide a good answer to the question. I think it is important that a working solution to the problem is clearly presented so that anyone in the furure can easily find a solution to a similar question.
function GetMyBox(sel)
{
var crypto_name = sel.value;
document.getElementById("Tag1").innerHTML = crypto_name;
google.script.run.withSuccessHandler(callback).Selection(crypto_name);
}
function callback(whatToWrite)
{
document.getElementById("Tag2").innerHTML = whatToWrite;
}
</script>
<p id="Tag1"></p>
<p id="Tag2"></p>

SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data on App Script web app

I am attempting to create an unordered list on my app script web app by pulling an array from a range on a google sheet.
I have a function in a gs file that works properly when used within the google sheet itself:
function listTest(){
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var invSheet = sheet.getSheetByName('Inventory');
var values = invSheet.getRange(2, 3, 25).getValues();
return JSON.stringify(values);
}
I have a javascript function that I am trying to implement based on the answer given here: Create a <ul> and fill it based on a passed array
my code is pretty much exactly this, minus the options variable:
function makeUL(array) {
// Create the list element:
var list = document.createElement('ul');
for(var i = 0; i < array.length; i++) {
// Create the list item:
var item = document.createElement('li');
// Set its contents:
item.appendChild(document.createTextNode(array[i]));
// Add it to the list:
list.appendChild(item);
}
// Finally, return the constructed list:
return list;
}
I ran a simplified version of it with just one list item, and it works:
function makeList() {
var list = document.createElement('ul');
var item = document.createElement('li');
item.appendChild(document.createTextNode("This is a test."));
list.appendChild(item);
return list;
}
document.getElementById("testDiv").appendChild(makeList());
However, when I try to pull the JSON array into the function to create the unordered list using the method in the link above, I get the error message: SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
My attempt at a function in my html to do this is:
function createList() {
var myJSON = google.script.run.listTest();
var array = JSON.parse(myJSON);
document.getElementById("testDiv").appendChild(makeUL(array));
}
createList();
I started off not using the JSON.stringify method in my listTest function. I was just ending with:
return values;
I was then getting the error 'array is undefined'.
I'm think JSON is the way to go with this, but I'm stuck.
Any help is appreciated.
Check the HTML Documentation for google.script.run. When you call google.script.run.listTest(); it doesn't actually return anything. You have to use the Success Handler which will receive returned data as a parameter. This is why your array is undefined.
EDIT: Updated This hasn't been completely tested:
function listTest(){
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var invSheet = sheet.getSheetByName('Inventory');
var values = invSheet.getRange(2, 3, 25).getValues();
return values;
}
function createList() {
google.script.run.withSuccessHandler(onSuccess)
.listTest();
}
function onSuccess(dataFromListTest){
document.getElementById("testDiv").appendChild(makeUL(dataFromListTest));
}
function makeUL(array) {
var list = document.createElement('ul');
for(var i = 0; i < array.length; i++) {
var item = document.createElement('li');
item.appendChild(document.createTextNode(array[i]));
list.appendChild(item);
}
return list;
}
See a different, basic example here: Gist - Using withSuccessHandler to Return Data
EDIT: Here is another example of an HTML File that calls a script back in the main code and puts that into a list in a div. This has been tested.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
google.script.run.withSuccessHandler(onSuccess)
.getSomeData(); //getSomeData() returns [["Cell 1"],["Cell 2"],["Cell 3"],["Cell 4"],["Cell 5"]] TO onSucess() AS A PARAMETER!
function onSuccess(data) {
var div = document.getElementById('output');
var list = document.createElement('ul'); // Create a <li> node
for(var i = 0; i < data.length; i++){
var item = document.createElement('li');
item.appendChild(document.createTextNode(data[i]));
list.appendChild(item);
}
div.appendChild(list);
}
</script>
</head>
<body>
<div id="output">
</div>
</body>
</html>
See the full example here on Gist with the main code.

How to get the URL of a page where a Google Script Gadget is embedded

I'm looking for a method that allows me to get the URL of the current page where a Google Script Gadget is embedded.
I tried using getActivePage() but that only returns my Google Site's home page. According to this issue: http://code.google.com/p/google-apps-script-issues/issues/detail?id=568 get active site and get active page is defective but that was in September 2011...
Here is my code:
var site = SitesApp.getActivePage();
Am I using getActivePage() incorrectly?
Thank you for your help in advance.
Edit 1 attempt:
var templates = site.getTemplates();
var template;
var names = '';
for (var i = 0; i < templates.length; i++) {
if (templates[i].getName() == 'profile') {
template = templates[i];
break;
}
}
if (template != null) {
var pageName = name;
Logger.log('Found: ' + pageName);
site.createPageFromTemplate(pageName, pageName, template);
}
else {
Logger.log('Not Found');
}
I created the following script
function doGet(e) {
var app = UiApp.createApplication();
var lbl = app.createTextArea();
lbl.setWidth('100%');
lbl.setHeight('100%');
var txt = SitesApp.getActivePage().getUrl();
lbl.setText(txt);
app.add(lbl);
return app;
}
and a couple of pages embedding the Google Script Gadget linked with this script. The script's output is the same as the URL in the internet browser address bar.
#LehanCoetzee code.
var templ = HtmlService.createTemplateFromFile('profile').evaluate();
site.createPageFromTemplate(name + ' ' + surname, name, templ);
'profile' is an html template I created through the apps script editor.
Edit 01:
I created a template page with a Gadget linked to my script above. The script's name is ProfileTemplate. Also I created a new page with the following script.
function doGet(e) {
var app = UiApp.createApplication();
var panel = app.createVerticalPanel();
var tb = app.createTextBox().setName('tb').setId('tb');
var btn = app.createButton().setText('Create').setId('btn');
var out = app.createTextArea().setId('out');
var handler = app.createServerHandler('onBtnClick');
handler.addCallbackElement(panel);
btn.addClickHandler(handler);
panel.add(tb);
panel.add(btn);
panel.add(out);
app.add(panel);
return app;
}
function onBtnClick(e) {
var app = UiApp.getActiveApplication();
var site = SitesApp.getActiveSite();
var out = app.getElementById('out');
var templates = site.getTemplates();
var template;
var names = '';
for (var i = 0; i < templates.length; i++) {
if (templates[i].getName() == 'profiletemplate') {
template = templates[i];
break;
}
}
if (template != null) {
var pageName = e.parameter.tb;
out.setText('Found: ' + pageName);
site.createPageFromTemplate(pageName, pageName, template);
}
else {
out.setText('Not Found');
}
return app;
}
If to open the new page, to type a text, for instance, test1 or test2, and click the Create button, then a new page from the template will be created. The templated page will have have an URL similar to https://sites.google.com/a/..../.../test1 for the text "test1" and the Gadget's output will contain this text.