How can I add a new div tag for each item in scriptDB?
It looks like the code gets stuck when I get to the "while (results.hasNext())" part, possibly because I am using Apps Script syntax in the script section of the HTML. I am able to make the script work when I substitute the entire while loop with just a simple div.innerHTML...etc. line
the index.html file looks like this:
<form id="myForm">
<p>Name of Alert: <input name="alertName" type="text" /></p>
<select name="frequency">
<option value="everyDay">Every day</option>
<option value="everyWeek">Every week</option>
</select>
<input type="button" value="Submit"
onclick="google.script.run
.withSuccessHandler(updateAlertList)
.processForm(this.parentNode)" />
</form>
<script>
function updateAlertList(results) {
var div = document.getElementById('output');
while (results.hasNext()) {
var result = results.next();
div.innerHTML = '' + result.alertName + '';
}
}
</script>
The Code.gs file has this in it:
function processForm(formObject) {
var formAlertName = formObject.alertName;
var formFrequency = formObject.frequency;
var db = ScriptDb.getMyDb();
var alert = {
alertName: formAlertName,
frequency: formFrequency
};
var record = db.save(alert);
var results = db.query({});
return results;
}
Update: worked when I added this to code.gs
var arrayResults = [];
while (results.hasNext()) {
arrayResults.push(results.next());
}
return arrayResults;
and this to index.html
for (var i=0;i<results.length;i++)
{
alert(results[i].alertName);
div.innerHTML = '' + results[i].alertName + '';
}
You need to process the results (iterator) in the gs and create an array of results to work through in the javascript.
Related
I am quite new to this all, so i am pretty sure this is a simple oversight on my part, but i cant get it to run.
When i deploy the code below and click on the button, it does not do anything. When i inspect the html in my browser, it says "userCodeAppPanel:1 Uncaught ReferenceError: csvHTML is not defined
at HTMLInputElement.onclick"
When i run the function csvHTML from Code.gs, I can see the expected results in my Logger.log, so it seems the problem does not lie in my code.gs
What i am trying to achieve is showing the csv results in html. When all works fine, i will want to work with the data in some other way.
Attached below is my code.
Index.html:
<!DOCTYPE html>
<!-- styles -->
<?!= HtmlService.createHtmlOutputFromFile("styles.css").getContent(); ?>
<div class="content">
<h1>csv representation</h1>
<input class="button" type="submit" onclick="html();" value="Refresh" id="refresh"><br>
<div id="tabel"></div>
<svg class="chart"></svg>
</div>
<!-- javascript -->
<script src="//d3js.org/d3.v3.min.js"></script>
<?!= HtmlService.createHtmlOutputFromFile("chart.js").getContent() ?>
<?!= HtmlService.createHtmlOutputFromFile("main.js").getContent() ?>
<script>
function html()
{
var aContainer = document.createElement('div');
aContainer.classList.add('loader_div');
aContainer.setAttribute('id', 'second');
aContainer.innerHTML = "<div class='loader_mesage'><center>Fetching csv list. Please be patient!<br /> <br /><img src='https://i.ibb.co/yy23DT3/Dual-Ring-1s-200px.gif' height='50px' align='center'></img></center></div>";
document.body.appendChild(aContainer);
google.script.run
.withSuccessHandler(showTable)
.csvHTML();
}
function showTable(tabel)
{
document.getElementById("tabel").innerHTML = tabel;
var element = document.getElementById("second");
element.parentNode.removeChild(element);
}
</script>
and Code.gs:
function doGet(e) {
return HtmlService.createTemplateFromFile("index.html")
.evaluate()
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
// Fecth Data and make a csv output.
function csvHTML()
{
var query = "{ 'query': 'SELECT * FROM `<some table>` limit 1000;', 'useLegacySql': false }";
var job = BigQuery.Jobs.query(query, <projectName>);
var json = JSON.parse(job);
var tabel = json2csv(json);
Logger.log(tabel)
return tabel;
}
function json2csv(json, classes) {
var headerRow = '';
var bodyRows = '';
classes = classes || '';
json.schema.fields.forEach(function(col){
headerRow +=col.name+",";
})
json.rows.forEach(function(row){
row.f.forEach(function(cell){
bodyRows +=cell.v+",";
})
})
return headerRow + bodyRows }
So thanks to the suggestions by TheMaster, i rewritten it into the following:
index.html:
<!-- javascript -->
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
function html()
{
var aContainer = document.createElement('div');
aContainer.classList.add('loader_div');
aContainer.setAttribute('id', 'second');
aContainer.innerHTML = "<div class='loader_mesage'><center>Fetching csv list. Please be patient!<br /> <br /><img src='https://i.ibb.co/yy23DT3/Dual-Ring-1s-200px.gif' height='50px' align='center'></img></center></div>";
document.body.appendChild(aContainer);
google.script.run
.withSuccessHandler(showTable)
.csvHTML();
}
function showTable(tabel)
{
document.getElementById("tabel").innerHTML = tabel;
var element = document.getElementById("second");
element.parentNode.removeChild(element);
}
</script>
<!DOCTYPE html>
<div class="content">
<h1>csv representation</h1>
<input class="button" type="submit" onclick="html();" value="Refresh" id="refresh"><br>
<div id="tabel"></div>
<svg class="chart"></svg>
</div>
Code.gs has not been modified.
It appears that the <?!= htmlService.createHtmlOutputFromFile("styles.css").getContent(); ?> and other createHtmlOutputFromFile were getting in the way. Eventually i need these, but I will figure out how to incorporate that at a later stage.
Thanks for all the advice and help!
Disclaimer: I have zero experience with Google Apps Script, so take this with a grain of salt.
Looking at their documentation for BigQuery, it seems you are not querying the database correctly. I am surprised by your claim that Logger.log() shows the correct output. It does not appear that it should work.
In case I am right, here is what I propose you change your Code.gs file to:
function doGet(e) {
return HtmlService.createTemplateFromFile("index.html")
.evaluate()
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
// Fetch Data and make a csv output.
function csvHTML() {
var results = runQuery('SELECT * FROM `<some table>` limit 1000;');
var tabel = toCSV(results);
Logger.log(tabel);
return tabel;
}
/**
* Runs a BigQuery query and logs the results in a spreadsheet.
*/
function runQuery(sql) {
// Replace this value with the project ID listed in the Google
// Cloud Platform project.
var projectId = 'XXXXXXXX';
var request = {
query: sql,
useLegacySQL: false
};
var queryResults = BigQuery.Jobs.query(request, projectId);
var jobId = queryResults.jobReference.jobId;
// Check on status of the Query Job.
var sleepTimeMs = 500;
while (!queryResults.jobComplete) {
Utilities.sleep(sleepTimeMs);
sleepTimeMs *= 2;
queryResults = BigQuery.Jobs.getQueryResults(projectId, jobId);
}
// Get all the rows of results.
var rows = queryResults.rows;
while (queryResults.pageToken) {
queryResults = BigQuery.Jobs.getQueryResults(projectId, jobId, {
pageToken: queryResults.pageToken
});
rows = rows.concat(queryResults.rows);
}
var fields = queryResults.schema.fields.map(function(field) {
return field.name;
});
var data = [];
if (rows) {
data = new Array(rows.length);
for (var i = 0; i < rows.length; i++) {
var cols = rows[i].f;
data[i] = new Array(cols.length);
for (var j = 0; j < cols.length; j++) {
data[i][j] = cols[j].v;
}
}
}
return {
fields: fields,
rows: rows
};
}
function toCSV(results) {
var headerRow = results.fields.join(',');
var bodyRows = results.rows.map(function(rowData) {
return rowData.map(function(value) {
// for proper CSV format, if the value contains a ",
// we need to escape it and surround it with double quotes.
if (typeof value === 'string' && value.indexOf('"') > -1) {
return '"' + value.replace(/"/g, '\\"') + '"';
}
return value;
});
})
.join('\n'); // join the lines together with newline characters
return headerRow + '\n' + bodyRows;
}
Reminder: I have not tested this, I'm purely writing this based on my knowledge of Javascript and their documentation and sample code.
I have a simple text input where users type anything and after sumbitting text appear on a page and stays there, which I done with localStorage, but after refreshing the page only last typed input is showing, Ill post my code to be more specific:
HTML:
<body>
<input id="NewPostField" type="text" value="">
<button onclick="myFunction()">Post</button>
<div id="Posts"></div>
</body>
JavaScript:
function myFunction() {
var NewPostField =
document.getElementById("NewPostField");
var newPost = document.createElement("p");
localStorage.setItem('text',
NewPostField.value);
newPost.innerHTML = NewPostField.value;
var Posts = document.getElementById("Posts");
Posts.appendChild(newPost);
}
(function() {
const previousText = localStorage.getItem('text');
if (previousText) {
var NewPostField = document.getElementById("NewPostField");
NewPostField.value = previousText;
myFunction();
}
})();
Any help will be great!
It seems that your code is only storing the last value posted.
To store more than one post, one idea is to stringify an array of values to store in localStorage.
Then, parse that stringified value back into an array as needed.
Here's an example:
function getExistingPosts() {
// fetch existing data from localStorage
var existingPosts = localStorage.getItem('text');
try {
// try to parse it
existingPosts = JSON.parse(existingPosts);
} catch (e) {}
// return parsed data or an empty array
return existingPosts || [];
}
function displayPost(post) {
// display a post
var new_post = document.createElement("p");
new_post.innerHTML = post;
posts.appendChild(new_post);
}
function displayExistingPosts() {
// display all existing posts
var existingPosts = getExistingPosts();
posts.innerHTML = '';
inputPost.value = '';
if (existingPosts.length > 0) {
existingPosts.forEach(function(v) {
displayPost(v);
});
inputPost.value = existingPosts.slice(-1)[0];
}
}
function addPost(post) {
// add a post
var existing = getExistingPosts();
existing.push(post);
localStorage.setItem('text', JSON.stringify(existing));
displayPost(post);
}
function clearPosts() {
// clear all posts
localStorage.removeItem('text');
displayExistingPosts();
}
var posts = document.getElementById("posts");
var inputPost = document.getElementById("input_post");
var btnPost = document.getElementById('btn_post');
var btnClear = document.getElementById('btn_clear');
btnPost.addEventListener('click', function() {
addPost(inputPost.value)
});
btnClear.addEventListener('click', clearPosts);
displayExistingPosts();
<input id="input_post" type="text" value="">
<button type="button" id="btn_post">Post</button>
<button type="button" id="btn_clear">Clear</button>
<div id="posts"></div>
Since localStorage isn't supported in StackSnippets, here's a JSFiddle to help demonstrate.
I'm completely new to the subject of JSON and I was wondering how to parse JSON from an input value in my form.
I'm trying to string the inputs into an array like {"task" : "(input) ", "(input) "} {"description" : "(input ", "(input)"}
I tried to follow the same directions as this post: Adding a new array element to a JSON object but they're referring to strings already formulated when I want to be able to parse JSON the same way from an input in my form. I want to be able to save every input and add a new array element the same way.
Bottom code runs smoothly but I'm such a noobie at parsing JSON D: any help is appreciated.
function submitForm() {
var task = myForm.task.value;
var desc = myForm.description.value;
var FormData = {
task: task,
description: desc
};
myJSON = JSON.stringify(FormData);
localStorage.setItem("formJSON", myJSON);
text = localStorage.getItem("formJSON");
obj = JSON.parse(text);
addTask(task);
addDescription(desc);
console.log(FormData);
return false;
};
newArray = [task, description];
var taskArray = [];
var descriptionArray = [];
var task = document.getElementById("task").value;
var description = document.getElementById("description").value;
function addTask(task) {
taskArray.push(task);
console.log(
"Tasks: " + taskArray.join(", "));
}
function addDescription(description) {
descriptionArray.push(description);
console.log("Description: " + descriptionArray.join(", "));
};
<!DOCTYPE html>
<html>
<title>Task Form</title>
<body>
<form class="form-inline" name="myForm" onsubmit=" return submitForm()">
<label class="required">*Task and Description* </label>
<!first text box>
<div class="form-group">
<input type="text" id="task" placeholder="Task">
</div>
<!second comment box>
<div class="form-group">
<input type="text" id="description" placeholder="Description">
</div>
<button type="submit" class="btn btn-default submit">Submit</button>
</form>
<script type="text/javascript " src="json.js "></script>
</body>
</html>
You should be storing the array of all tasks in localStorage, not just a single task. When the user saves a new task, read the JSON from local storage, parse it, add the new task to the array, and save that.
function submitForm() {
var task = myForm.task.value;
var desc = myForm.description.value;
var FormData = {
task: task,
description: desc
};
var arrayJSON = localStorage.getItem("formJSON") || "[]";
var taskArray = JSON.parse(arrayJSON);
taskArray.push(FormData);
localStorage.setItem("formJSON", JSON.stringify(taskArray));
addTask(task);
addDescription(desc);
console.log(FormData);
return false;
};
I tried to build an application in which , there is one HTML page from which I get single input entry by using Submit button, and stores in the container(data structure) and dynamically show that list i.e., list of strings, on the same page
means whenever I click submit button, that entry will automatically
append on the existing list on the same page.
But in this task, firstly I try to catch that input in javascript file, and I am failing in the same. Can you tell me for this, which command will I use ?
Till now my work is :-
HTML FILE :-
<html>
<head>
<script type = "text/javascript" src = "operation_q_2.js"></script>
</head>
<body>
Enter String : <input type= "text" name = "name" id = "name_id"/>
<button type="button" onClick = "addString(this.input)">Submit</button>
</body>
</html>
JAVASCRIPT FILE:-
function addString(x) {
var val = x.name.value;
//var s = document.getElementById("name_id").getElementValue;//x.name.value;
alert(val);
}
EDITED
My New JAVASCRIPT FILE IS :-
var input = [];
function addString(x) {
var s = document.getElementById("name_id").value;//x.name.value;
input.push(input);
var size = input.length;
//alert(size);
printArray(size);
}
function printArray(size){
var div = document.createElement('div');
for (var i = 0 ; i < size; ++i) {
div.innerHTML += input[i] + "<br />";
}
document.body.appendChild(div);
//alert(size);
}
Here it stores the strings in the string, but unable to show on the web page.
See this fiddle: http://jsfiddle.net/MjyRt/
Javascript was almost right
function addString(x) {
var s = document.getElementById("name_id").value;//x.name.value;
alert(s);
}
Try to use jQuery (simpler)
function addString() {
var s = $('#name_id').val();//value of input;
$('#list').append(s+"<br/>");//list with entries
}
<div id='list'>
</div>
Im trying to build a form that calculates a total price based on a series of drop down boxes with string values such as "This option costs £30" i know this is not ideal but im putting this together as a hack for an existing script
For the most part ive got it working however im not sure how to run the each function for each child of #productconfig
I can manually input each of the drop downs ids into an array and that makes the calculation but it would be good if it just worked with all the children of #productconfig
<code>
<div id="#productconfig">
<label>Model Type</label>
<select name="products[220][data][modeltype]" id="data-modeltype-220">
<option value="M-Type £500">M-Type £500</option>
<option value="P-Type £500">P-Type £500</option>
<option value="S-Type £500">S-Type £500</option>
</select>
</div>
</code>
<code>
$(document).ready(function() {
$("#productconfig").children().change(function () {
calculateoptions();
});
calculateoptions();
});
</code>
<code>
function calculateoptions() {
var arr = ["data-modeltype-220"];
var total = 0;
jQuery.each(arr, function () {
var str = $('#' + this).attr("value");
var poundsign = str.indexOf('£');
var poundsign = poundsign + 1;
var lengthofstr = str.length;
var shortstr = str.substr(poundsign, lengthofstr);
total = eval(total) + eval(shortstr);
});
$('#price').html("£" + total);
}
</code>
How about this:
function calculateoptions() {
var total = 0;
jQuery('#productconfig select').each(function () {
total += $(this).val().match(/£(\d+)/)[1];
});
$('#price').html("£" + total);
}
You can use:
$("#productconfig select").each(function(){...});
To select each drop down in the product config div.