HTML href as Google Apps Script variable - javascript

i'm making an index that generates automatically from a Google Spreadsheet.
My script reads two columns, one with names and the other one with links. Then it generates an HTML with all the names as <li><a>"The name"</a></li>.
My idea is to pass the links on the spreadsheet to the href=" " on each name, but I don't know how to do it.
Here is my .gs and .html code, and a link to my spreadsheet (to work on it, you may have to make a copy).
https://docs.google.com/spreadsheets/d/1fEYqPnp9SIS7I2lzeeoEP7Pui4l0dgLD6t7D9Lki9oE/edit?usp=sharing
GS code
function doGet() {
return HtmlService.createHtmlOutputFromFile('index');
}
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Index');
function readData() {
var range = spreadsheet.getRange(1, 1,spreadsheet.getLastRow(), spreadsheet.getLastColumn()).getValues();
Logger.log(range);
return range;
};
function readLinks() {
var links = spreadsheet.getRange(1, 2,spreadsheet.getLastRow(), spreadsheet.getLastColumn()).getValues();
Logger.log(links);
return links;
};
HTML code
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<div>
<ul>
<li id="proced"><a id="link"></a></li>
</ul>
</div>
<script>
function getData(values) {
values.forEach(function(item, index) {
var x = document.getElementById("link");
x.innerHTML += '<li>' + item[0] + '</li>';
});
}
google.script.run.withSuccessHandler(getData).readData();
</script>
</body>
</html>

Below is the modified code
GS code
function doGet() {
return HtmlService.createHtmlOutputFromFile('index');
}
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Index');
function readData() {
var data = spreadsheet.getDataRange().getValues()
Logger.log(data)
return data
}
HTML code
<script>
function getData(values) {
var x = document.getElementById("link");
values.forEach(function(item) {
x.innerHTML += '<li>' + item[0] + '</li>';
});
}
google.script.run.withSuccessHandler(getData).readData();
</script>
Changes
Here are the main changes I made:
.gs
Instead of getting the Names and Links separately, now the function readData gets the corresponding names and links all together by using getDataRange.
This returns a two dimensional array like this:
[
["Google", "http://www.google.com/"],
["Facebook", "http://www.facebook.com/"],
["Twitter", "http://www.twitter.com/"],
["Youtube", "https://www.youtube.com"],
["Instagram", "http://www.instagram.com/"],
["Reddit", "http://www.reddit.com/"],
["Bing", "http://www.bing.com/"],
]
This makes the script faster, but if you want to get the ranges individually then you would need to use getRange("A1:A7") or with your method of getting last rows etc. Then get both ranges. The best thing would be to put them together into a two-dimensional array to pass them to the HTML together, if not it complicates things too much, because you will need to construct a chain of call backs to get the names and then wait for the links and then link them up together on the client-side anyway.
.html
Moved var x = document.getElementById("link"); outside the forEach loop. This stays the same for each item so no need to reinitialize it each time.
Changed forEach arguments to function(item) as you don't use the index.
Since each item is now a one-dimensional array eg => ["Google", "http://www.google.com/"] you can call:
item[0] => "Google"
item[1] => "http://www.google.com/"
So the resulting forEach is:
values.forEach(function(item) {
x.innerHTML += '<li>' + item[0] + '</li>';
});

Related

how to append html page inside current page using google web app?

I know how to include CSS or JS files using app script in a web script. but that way includes files content on page lode.
My question is it possible to include partial html page inside the currently opened page?
app script to include CSS or JS
/* #Include JavaScript & CSS & HTML-Partial-Views */
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename).getContent();
}
and I use like this
<?!= include('Css'); ?>
and here is my attempt.
html
<button onclick="getList("users")">show some html content</button>
<div id="users"></div>
<script>
function getList(users){
var listUsers = google.script.run.showHtml(users);
// how to return showHtml result [list of users]
for (var i; i <= listUsers.length; 1++)
{
document.querySelector("#users").innerHTML += <div>listUsers[i]</div>;
}
}
</script>
gs
function users(sheetName, pageName){
// get users from sheet
var ss= SpreadsheetApp.openById("435yh35h45b35nh6hg5bwh455j");
var dataSheet = ss.getSheetByName(sheetName);
var dataRange = dataSheet.getDataRange().getValues();
return dataRange;
}
From one of the code snippets
// how to return showHtml result [list of users]
Try this:
<button onclick="getList('users')">show some html content</button>
<div id="users"></div>
<script>
function getList(users){
var listUsers = google.script.run
.withSuccessHandler((listUsers) => {
let list = '';
for (var i; i < listUsers.length; i++) {
list += `<div>${listUsers[i]}</div>\n`;
}
document.querySelector("#users").innerHTML = list;
})
.showHtml(users);
}
</script>
Changes done
Replaced "users" by 'users'
Added withSuccessHandler with an arrow function as callback.
The arrow function build a string using a for statement (because it was used in the original code) including a div tag using a template literal.

how to covert visualization table of app script to spread sheet google app script code

I have HTML web app where I have converted a spreadsheet to a HTML table. Now I would like to convert this HTML Table to a spreadsheet. Is it possible to convert it back to a spreadsheet?
You can say that I can directly make use of the spreadsheet but the problem is that I have applied some filters. Now whenever I apply a filter to a specific column, it will be displayed so now I want that column to be moved to the new spreadsheet using google app script
Here is my table, how can convert this table to spreadsheet using Google App Script
I use two sheets for this example one sheet is named sht2tbl and the other sheet is named tbl2sht. You need to have both ready to go when you run the code.
Here's sheet2table and table2sheet.gs:
function sheetToTable()//This produces a modeless dialog
{
var s='';
s+='<table width="100%">';
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sht=ss.getSheetByName('sht2tbl');
var rng=sht.getDataRange();
var rngA=rng.getValues();
for(var i=0;i<rngA.length;i++)
{
s+='<tr>';
for(var j=0;j<rngA[0].length;j++)
{
if(i==0)
{
s+='<th id="cell' + i + j + '">' + rngA[i][j] + '</th>';//put ids in each th
}
else
{
s+='<td id="cell' + i + j + '">' + rngA[i][j] + '</td>';//put ids in each td
}
}
s+='</tr>';
}
s+=' </body></html>'
var html=HtmlService.createHtmlOutputFromFile('html2body');//create output from file
html.append(s);//and append s for the rest
SpreadsheetApp.getUi().showModelessDialog(html, 'Sheet to Table')
}
function getParams()//this gives the client side array dimensions
{
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sht=ss.getSheetByName('sht2tbl');
var rng=sht.getDataRange();
var A=[];
A.push(rng.getWidth());
A.push(rng.getHeight());
return (A);//range width and height in an array
}
function putData(data)//this gets cell contents from the client side and displays them on another sheet named 'tbl2sht'
{
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sht=ss.getSheetByName('tbl2sht');
var h=data.length;
var w=data[0].length;
var rng=sht.getRange(1,1,h,w);//create a range properly dimensioned
rng.setValues(data);//use setValues to load sheet
}
This is the file htmltobody.html. It's a lot easier to create javascript this way. But I like to integrate the data creation with server side google script.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
$(function() {
google.script.run
.withSuccessHandler(getCellValues)//returns to get values from client side
.getParams();//get width and height of data array
});
function getCellValues(A)
{
var w=A[0];
var h=A[1];
var data=[];
for(var i=0;i<h;i++)
{
data[i]=[];
for(var j=0;j<w;j++)
{
var s='#cell' + Number(i) + Number(j);
data[i][j]=$(s).text();//use jquery text to get th and td values
}
}
google.script.run
.putData(data);//send data to server side to load data in tbl2sht
}
console.log('My Code');//helps me to find code in chrome console
</script>
</head>
<body>
This is the sht2tbl which was use to create the modeless dialog:
This is the dialog that gets created:
And this is the data from the dialog displayed on a sheet named tbl2sht:

Text to Html list

I want to make a html which will auto get the information for a *.txt file
something1
something2
something3
and output into this html file
<!DOCTYPE html>
<html>
<head>
<title>List</title>
</head>
<body>
<ul>
#here to output#
</ul>
</body>
</html>
I prefer to use JavaScript. Some help is appreciated.
You have to request the file using AJAX call. Then you need to iterate through each line of response and generate DOM element (li in this case) and input line inside of it. After that insert each li element into your ul list.
You can achieve it using jQuery as you are probably new to JavaScript it's probably the easiest way.
What you need to do is request the file first:
$.ajax('url/to/your/file', {
success: fileRetrieved
});
Now after the file is retrieved jQuery will call fileRetrieved method, so we have to create it:
function fileRetrieved(contents) {
var lines = contents.split('\n');
for(var i = 0; i < lines.length; i += 1) {
createListElement(lines[i]);
}
}
Now for each line from the file function fileRetrieved will call createListElement function passing line of text to it. Now we just need to generate the list element and inject it into DOM.
function createListElement(text) {
var into = $('ul');
var el = $('<li></li>').html(text);
el.appendTo(into);
}
Of course you don't want to retrieve into element each time createListElement is called so just store it somewhere outside the function, it's your call, I'm just giving you the general idea.
Here is an example of the script (without AJAX call of course as we can't simulate it):
var into = $('#result');
function fileRetrieved(contents) {
var lines = contents.split('\n');
for (var i = 0; i < lines.length; i += 1) {
createListElement(lines[i]);
}
}
function createListElement(text) {
var el = $('<li></li>').html(text);
el.appendTo(into);
}
var text = $('#text').html();
fileRetrieved(text);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- This element simulates file contents-->
<pre id="text">
fdsafdsafdsa
fdsafd
safdsaf
dsafdsaf
dsafdsafds
afdsa
</pre>
<div id="result"></div>
Try this
<html>
<head>
<title>List</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<ul id="renderTxt_list">
</ul>
<input type="button" id="lesen" value="Read Data" />
</body>
<script>
$(document).ready(function(){
$("#lesen").click(function() {
$.ajax({
url : "testTxt.txt",
dataType: "text",
success : function (data) {
$html = "";
var lines = data.split("\n");
for (var i = 0, len = lines.length; i < len; i++) {
$html += '<li>'+lines[i]+'</li>';
}
$("body ul").append($html);
}
});
});
});
</script>
</html>
You need to request the file first, and then append it to your chosen place in the document.
You can for example use jQuery's get (or any other function like the native fetch), and then inject it into the ul element:
$.get("*.txt").then(x => $("ul").html("<li>" + x.split('\n').join('</li><li>') + "</li>"))
Let's break this solution by steps:
First, we need to request the external file:
$.get("*.txt")
Read about jQuery's get here. Basicly it will request the file you asked for using network request, and return a promise.
In the Promise's then, we can do stuff with the request's result after it is resolved. In our case we want to first break it by lines:
x.split('\n')
split will return an array that will look like this: ["line 1, "line 2", "line 3"].
JS arrays have the join method, which concat them to string while putting the string you want between the items. So after we do this:
x.split('\n').join('</li><li>')
We only need to add the <li> element to the start and end of the string like this:
"<li>" + x.split('\n').join('</li><li>') + "</li>"
Finally we appent it to your chosen element using jQuery's html.

Parsing json from external url Html and JS only

<html>
<body>
<div id="output">hi</div>
</body>
<script>
var link="http://mywp.com/cilacap/api/get_posts/";
var jcontent= JSON.parse(link);
var output=document.getElementById('output');
output.innerHTML=jcontent.id' ';
</script>
</html>
It only shows "hi".
Can someone tell me how to show JSON items such as "id" and "postDate"
with looping but without PHP scripting?
Thanks
Few syntactical errors, below is the right one.
<html>
<body>
<div id="output">hi</div>
</body>
<script>
var link='{"url":"http://mywp.com/cilacap/api/get_posts/", "id":"url_id_01"}';
var jcontent= JSON.parse(link);
var output=document.getElementById('output');
output.innerHTML=jcontent.id + ' ';
</script>
</html>
JSON Data(var link), was not parsable.
JSON Data(var link), didnt contained any attribute called id.
String concatenation in last line(output.innerHTML), was wrong.
Try removing the quotes from:
output.innerHTML=jcontent.id' ';
and change it to:
output.innerHTML += jcontent.id;
Providing that the link is valid it should work now.
You can also write:
console.log(jcontent);
and check if the console displays the value, or any errors that have occurred.
That url is a string, not json.
Use Ajax to get the data ( using jquery)
var link;
$.ajax({
url: "test.html",
}).done(function(data) {
link = data;
});
Then, extract the data;
output.innerHTML=jcontent.id;
Is for the value. You get the key like this:
ES7
Object.entries(jcontent)
.forEach(keyValuePair =>
{
// Push to HTML
var t = document.createTextNode(keyValuePair[0] + ' : ' + keyValuePair[1]);     // Create a text node
output.appendChild(t);   
});
ES6
Object.keys(jcontent)
.map(key => [key, jcontent[key]])
.forEach(keyValuePair =>
{
// Push to HTML
var t = document.createTextNode(keyValuePair[0] + ' : ' + keyValuePair[1]);     // Create a text node
output.appendChild(t);   
});
ES5 (Most likely your case)
Use function instead of arrow functions for es5:
Object.keys(jcontent)
.map(function(key){ [key, jcontent[key]] })
.forEach(function(keyValuePair)
{
// Push to HTML
var t = document.createTextNode(keyValuePair[0] + ' : ' + keyValuePair[1]);     // Create a text node
output.appendChild(t);   
});
Access the value:
keyValuePair[0] // key
keyValuePair[1] // value
Ps
If you want to use the es7 or es6 method, have a look at babeljs

External Javascript File Fetch?

I am currently using this code:
var wordRandomizer = {
run: function (targetElem) {
var markup = this.createMarkup();
targetElem.appendChild(markup);
},
createMarkup: function () {
var that = this;
var frag = document.createDocumentFragment();
this.elem = document.createElement('span');
var button = document.createElement('button');
button.innerText = 'Change Item';
button.addEventListener('click', function () {
that.changeItem();
});
frag.appendChild(this.elem);
frag.appendChild(button);
return frag;
},
changeItem: function () {
var rand = this.getRandInt(1, this.items.length) - 1;
console.log(rand);
this.elem.innerText = this.items[rand];
},
getRandInt: function (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
},
items: ['itemA', 'itemB', 'itemC', 'itemD']
};
wordRandomizer.run(document.body);
I code is a button which when pressed grabs one of the items in the list. However, I don't want the items to show on the same page as the generator as people simply look at the source code. How can I make it so once the button is pressed it grabs the random item from another location where people cannot view them all using the source code.
If it helps, you can see the code in action here - http://jsbin.com/ESOdELU/1/edit
I will give you a solution using PHP since it is a free scripting language and is the most likely to be supported by a host or default web server...
For starters, here is the code to include jquery and the basic AJAX script
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/JavaScript">
$(document).ready(function(){
$("#generate").click(function(){
$("#madlibs p").load("script.php");
});
});
</script>
Here is the code for script.php
<?php
header("Cache-Control: no-cache");
// For testing you can use an inline array like the lines below
// Just remove the comment slashes "//" from the beginning of the line
// and comment out the external declarations
//$actors = array('Denzel Washington','Michael J. Fox','Jim Carey','Boris Kodjoe');
//$roles = array('Mental Patient','Homeless Musician','Drag Queen Detective','Tormented Mathematician');
// In production, you would put these in a text file or a database.
// For $actors, put an entry on each line of a text file and save it as 'leads.txt'
// Do the same with a separate file for $roles (roles.txt).
$actors = file("leads.txt");
$roles = file("roles.txt");
// This selects a random element of each array on the fly
echo $prefixes[rand(0,count($actors)-1)] . " stars as a "
. $suffixes[rand(0,count($roles)-1)] . " in the next blockbuster film.";
// Example output:
// Michael J. Fox stars as a Tormented Mathematician in the next blockbuster film.
?>
Put this in the body of your page and be sure to style everything up for display.
<body>
<div id="madlibs"><p> </p></div>
<button id="generate">Surprise Me!</button>
</body>
A couple of notes:
- You can include your basic layout HTML in the script.php file and then would only need the ID of the DIV in which you will be displaying the result $("#madlibs")
You can use any server side language to achieve the same result, just swap out the external file call to the appropriate name and extension (.asp, .cfm, etc.)
Here is a link to the original tutorial that helped me with a similar project:
http://www.sitepoint.com/ajax-jquery/
I hope this helps. Sorry, but I couldn't come up with a purely Java of JavaScript solution on lunch.

Categories

Resources