Read csv file using JavaScript and display into an html table - csv

I am a beginner in programming and I could really use your help to understand why this piece of code does not work and fix it. I get no error, simply nothing happens.
I want to read a csv file using JavaScript and display its contents in an html table.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<script type="text/javascript">
var fileInput = document.querySelector('notes.csv');
function read(callback){
var file = fileInput.files.item(0);
var reader = new FileReader();
reader.onload = function (e){
callback(reader.result);
var table = document.createElement("table");
var rows = e.target.result.split("\n");
for (var i = 0; i < rows.length; i++){
var cells = rows[i].split(",");
if (cells.length > 1){
var row = table.insertRow(-1);
for (var j = 0; j < cells.length; j++){
var cell = row.insertCell(-1);
cell.innerHTML = cells[j];
}
}
}
var dvCSV = document.getElementById("dvCSV");
dvCSV.innerHTML = "";
dvCSV.appendChild(table);
}
reader.readAsText(fileInput);
}
</script>
<div id="dvCSV"></div>
</body>
</html>

Related

AmCharts4 - Unable to load file - external JSON file produced from SQL database

I'm struggling to open my json arranged data in AmCharts4. In my previous charts I used very simple script (chart.data = ;), which unfortunately does not work this time. So I'm using chart.dataSource.url function proposed by AmCharts documentation. When, I load example file found on web everything works fine, as soon as I switch to my file the chart is not able to load file. I'm not able to find a similar problem on web, therefore I would be very grateful for help.
Here is my example with working url and my not working file.
Thanks in advance:
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/charts.js"></script>
<script src="https://www.amcharts.com/lib/4/themes/animated.js"></script>
<style>
</style>
</head>
<body>
<div id="chartdiv"></div>
</body>
</html>
<!-- Styles -->
<style>
#chartdiv {
width: 100%;
height: 500px;
}
</style>
<!-- Resources -->
<script src="https://cdn.amcharts.com/lib/4/core.js"></script>
<script src="https://cdn.amcharts.com/lib/4/charts.js"></script>
<script src="https://cdn.amcharts.com/lib/4/themes/animated.js"></script>
<!-- Chart code -->
<script>
am4core.ready(function() {
// Themes begin
am4core.useTheme(am4themes_animated);
// Themes end
var chart = am4core.create('chartdiv', am4charts.XYChart)
// Modify chart's colors
chart.colors.list = [
am4core.color("#264B29"),
am4core.color("#94B255"),
am4core.color("#456C39"),
am4core.color("#C4D563"),
am4core.color("#698F47"),
am4core.color("#F9F871"),
];
chart.legend = new am4charts.Legend()
chart.legend.position = 'top'
chart.legend.paddingBottom = 20
chart.legend.labels.template.maxWidth = 95
var xAxis = chart.xAxes.push(new am4charts.CategoryAxis())
xAxis.dataFields.category = 'year'
xAxis.renderer.cellStartLocation = 0.1
xAxis.renderer.cellEndLocation = 0.9
xAxis.renderer.grid.template.location = 0;
var yAxis = chart.yAxes.push(new am4charts.ValueAxis());
function createSeries(value, name) {
var series = chart.series.push(new am4charts.ColumnSeries())
series.dataFields.valueY = value
series.dataFields.categoryX = 'year'
series.name = name
series.events.on("hidden", arrangeColumns);
series.events.on("shown", arrangeColumns);
var bullet = series.bullets.push(new am4charts.LabelBullet())
bullet.interactionsEnabled = false
bullet.dy = 30;
bullet.label.text = '{valueY}'
bullet.label.fill = am4core.color('#ffffff')
return series;
}
// Add data
//Working url
//chart.dataSource.url = "https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-160/sample_data_serial.json";
//My SQL produced JSON file is not working
chart.dataSource.url = "data/my-file.php";
chart.dataSource.adapter.add("parsedData", function(data) {
var newData = [];
data.forEach(function(dataItem) {
var newDataItem = {};
Object.keys(dataItem).forEach(function(key) {
if (typeof dataItem[key] === "object") {
newDataItem["_id"] = dataItem[key]["#id"];
dataItem[key]["Column"].forEach(function(dataItem) {
newDataItem[dataItem["#name"]] = dataItem["#id"];
});
} else {
newDataItem[key] = dataItem[key];
}
});
newData.push(newDataItem);
});
data = newData;
return data;
});
createSeries('cars', 'The First');
createSeries('motorcycles', 'The Second');
createSeries('bicycles', 'The Third');
//createSeries('bilanca_lsk_lst', 'T4');
function arrangeColumns() {
var series = chart.series.getIndex(0);
var w = 1 - xAxis.renderer.cellStartLocation - (1 - xAxis.renderer.cellEndLocation);
if (series.dataItems.length > 1) {
var x0 = xAxis.getX(series.dataItems.getIndex(0), "yearX");
var x1 = xAxis.getX(series.dataItems.getIndex(1), "yearX");
var delta = ((x1 - x0) / chart.series.length) * w;
if (am4core.isNumber(delta)) {
var middle = chart.series.length / 2;
var newIndex = 0;
chart.series.each(function(series) {
if (!series.isHidden && !series.isHiding) {
series.dummyData = newIndex;
newIndex++;
}
else {
series.dummyData = chart.series.indexOf(series);
}
})
var visibleCount = newIndex;
var newMiddle = visibleCount / 2;
chart.series.each(function(series) {
var trueIndex = chart.series.indexOf(series);
var newIndex = series.dummyData;
var dx = (newIndex - trueIndex + middle - newMiddle) * delta
series.animate({ property: "dx", to: dx }, series.interpolationDuration, series.interpolationEasing);
series.bulletsContainer.animate({ property: "dx", to: dx }, series.interpolationDuration, series.interpolationEasing);
})
}
}
}
});
// end am4core.ready()
</script>
I found a typing error in my-file.php
Anyhow, after I solved typing issue the chart.dataSource.url function still did not work, but It worked using next php include script.
chart.data = <?php include './data/my-file.php'; ?>;

Cannot append option for select form

I want to load option data from a Sheet and append to the select element, but I cannot set the global variable
var select_values = [];
google.script.run.withSuccessHandler(loadOpt).loadData("Test");
function loadOpt(data_arrar) {
const arrayColumn = (arr, n) => arr.map(x => x[n]);
select_values = arrayColumn(data_arrar, 1);
}
var opt = document.getElementById("select_opts");
for (i = 0; i < select_values.length; i++) {
let option = document.createElement("option");
option.value = i;
option.text = select_values[i];
opt.appendChild(option);
}
The result is nothing appended to [select_opts].
I'm update the code.gs.
var TestSheets = SpreadsheetApp.openById("XXX");
function doGet(e) {
if (!e.parameter.page) {
// When no specific page requested, return "home page"
return HtmlService.createTemplateFromFile('Home').evaluate();
}
// else, use page parameter to pick an html file from the script
return HtmlService.createTemplateFromFile(e.parameter['page']).evaluate();
}
function loadData(Sheetname) {
var sheet = TestSheets.getSheetByName(Sheetname);
var rows = sheet.getRange("A1").getValue();
var Columns = sheet.getRange("B1").getValue();
var data_return = [];
for (var i = 0; i <= rows; i++) {
data_return[i] = [];
for (var j = 0; j <= Columns - 1; j++) {
data_return[i][j] = sheet.getRange(i + 2, j + 1).getValue();
}
}
return data_return;
}
Note that function loadData works well & has been tested.
The problem is that Javascript code outside of functions will be called on loading of the HTML document
It will not be reevaluated after running code in functions
If you want your loop to run after function loadData(Sheetname) - you need to put the loop into another function that is called after the execution of function loadData(Sheetname)
Sample:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<script>
var select_values = [];
google.script.run.withSuccessHandler(loadOpt).loadData("Test");
function loadOpt(data_arrar) {
const arrayColumn = (arr, n) => arr.map(x => x[n]);
select_values = arrayColumn(data_arrar, 1);
console.log(" select_values: " + select_values);
callLater();
}
console.log(" select_values in call outside: " + select_values);
function callLater(){
console.log(" select_values in callLater: " + select_values);
var opt = document.getElementById("select_opts");
for (i = 0; i < select_values.length; i++) {
let option = document.createElement("option");
option.value = i;
option.text = select_values[i];
opt.appendChild(option);
}
}
</script>
</body>
</html>

Issue Converting HTML Table into CSV Format

Trouble converting a series of HTML Tables into a single CSV document.
Everything works fine until I get to a multi-line in my html.
The converter takes: <td> Restarted the following servers for maintenance:
-Car Care: CarCareServer -DWA: DWAHost, Server-1, Terminal -Homemasters: Homemasters, SRV0 -Monolith: Monolith, Server </td>
And converts it into: 5 new CSV cells (one for each line). But, what I need is for all this text to be funneled into one, single, CSV cell.
Please help!
Here's my converter.
$('#CSVFiltDownBtn').click(function() {
var titles = [];
var data = [];
/*
* Get the table headers, this will be CSV headers
* The count of headers will be CSV string separator
*/
$('#filtered_table thead:first th').each(function() {
titles.push($(this).text());
});
/*
* Get the actual data, this will contain all the data, in 1 array
*/
$('#filtered_table td').each(function() {
//data.push($(this).text());
var cellData = $(this).text();
//var cleanData = escape(cellData);
var cleanData = cellData.replace(/,/g, "").replace(/-/g, "").replace(/<br>/g, "");
data.push(cleanData);
});
/*
* Convert our data to CSV string
*/
var CSVString = prepCSVRow(titles, titles.length, '');
CSVString = prepCSVRow(data, titles.length, CSVString);
/*
* Make CSV downloadable
*/
var downloadLink = document.createElement("a");
var blob = new Blob(["\ufeff", CSVString]);
var url = URL.createObjectURL(blob);
downloadLink.href = url;
downloadLink.download = "data.csv";
/*
* Actually download CSV
*/
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
});
The tables are tricky to demonstrate because their numbers, and the numbers of columns, are dictated by the user (it's a filtered list), and I'm converting multiple resulting tables into a single CSV.
All tables have the same numbers of columns, and the same headers.
My primary issue is how to make sure these multi-lined td's are converting into a single CSV block.
Thoughts?
Don't use jQuery's text use the native innerText.
Replace
var cellData = $(this).text();
With
var cellData = this.text();
See the snippet below for a quick and dirty demo of the difference:
var div = document.querySelector("div");
console.log(div.innerText);
console.log($("div").text());
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
Some
Text
</div>
I don't know the CSV parser you are using, so I made one showing you the technique, following the example here: https://en.wikipedia.org/wiki/Comma-separated_values#Example .
/* js/external.js */
//<![CDATA[
var doc, bod, I, S, Q, special, unspecial, csv; // for use on other loads
addEventListener('load', function(){
doc = document; bod = doc.body;
I = function(id){
return doc.getElementById(id);
}
S = function(selector, within){
var w = within || doc;
return w.querySelector(selector);
}
Q = function(selector, within){
var w = within || doc;
return w.querySelectorAll(selector);
}
special = function(str){
return str.replace(/&/g, '&').replace(/'/g, '&apos;').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>');
}
unspecial = function(str){
return str.replace(/&/g, '&').replace(/&apos;/g, "'").replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>');
}
csv = function(tableElement, linkElement){
var thead_tr = Q('thead>tr', tableElement), tfoot_tr = Q('tfoot>tr', tableElement), tbody_tr = Q('tbody>tr', tableElement), s = '';
for(var i=0,c=thead_tr,row,col,l=c.length; i<l; i++){
row = thead_tr[i].childNodes;
for(var n=0,a=[],q=row.length; n<q; n++){
col = row[n];
if(col.nodeType === 1)a.push('"'+unspecial(col.innerHTML).replace(/"/g, '""')+'"');
}
s += a.join(',')+'\n';
}
for(var i=0,c=tbody_tr,l=c.length; i<l; i++){
row = tbody_tr[i].childNodes;
for(var n=0,a=[],q=row.length; n<q; n++){
col = row[n];
if(col.nodeType === 1)a.push('"'+unspecial(col.innerHTML).replace(/"/g, '""')+'"');
}
s += a.join(',')+'\n';
}
for(var i=0,c=tfoot_tr,l=c.length; i<l; i++){
row = tfoot_tr[i].childNodes;
for(var n=0,a=[],q=row.length; n<q; n++){
col = row[n];
if(col.nodeType === 1)a.push('"'+unspecial(col.innerHTML).replace(/"/g, '""')+'"');
}
s += a.join(',')+'\n';
}
linkElement.href = URL.createObjectURL(new Blob([s], {type:'text/csv'}));
}
csv(I('wiki_cars'), I('downloadLink'));
});
//]]>
/* css/external.css */
*{
box-sizing:border-box; padding:0; margin:0;
}
html,body{
width:100%; height:100%;
}
body{
position:relative; background:#ccc;
}
table{
background:#fff; border-collapse:collapse;
}
th,td{
border:1px solid #000; padding:3px 5px;
}
#link_container{
text-align:center; margin:7px 0;
}
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
<head>
<meta charset='UTF-8' /><meta name='viewport' content='width=device-width, height=device-height, initial-scale:1' />
<title>Test Template</title>
<link type='text/css' rel='stylesheet' href='css/external.css' />
<script type='text/javascript' src='js/external.js'></script>
</head>
<body>
<div id='link_container'><a id='downloadLink' download='data.csv'>Click to Test</a></div>
<table id='wiki_cars'>
<thead>
<tr>
<th>Year</th><th>Make</th><th>Model</th><th>Description</th><th>Price</th>
</tr>
</thead>
<tfoot>
<tr>
<th>total</th><th></th><th></th><th></th><th>17699.00</th>
</tr>
</tfoot>
<tbody>
<tr>
<td>1997</td><td>Ford</td><td>E350</td><td>ac, abs, moon</td><td>3000.00</td>
</tr>
<tr>
<td>1999</td><td>Chevy</td><td>Venture "Extended Edition"</td><td></td><td> 4900.00</td>
</tr>
<tr>
<td>1999</td><td>Chevy</td><td>Venture "Extended Edition, Very Large"</td><td></td><td>5000.00</td>
</tr>
<tr>
<td>1996</td><td>Jeep</td><td>Grand Cherokee</td><td>"MUST SELL! air, moon roof, loaded"</td><td>4799.00</td>
</tr>
</tbody>
</table>
</body>
</html>
I did add a footer to that table. Hopefully this helps!
PS
Personally, I wouldn't use the download attribute, since it won't work on Safari on iOS. You can always create a CSV file on your Server. .csvs should attempt to download automatically if you link to them, since the Browser won't know what to do with that file type.

Transferring HTML data between pages

Been really stressed out for a while, as I'm very new to coding and can't figure out how to transfer some paragraph data across pages.
Here is my code on my first page:
<!DOCTYPE>
<html>
<head>
<h1>z</h1>
</head>
<body>
<p>test</p>
<p id="goalPage"></p>
<script type="text/javascript">
var t = Math.floor((Math.random() * 1) + 1);
if (t === 1) {document.getElementById("goalPage").innerHTML = "Your goal page is Data 1";}
else {alert('Unprecedented failure. Please reload the page and report the bug to me.');}
function testJS() {
var b = document.getElementById('goalPage').value,
url = 'file:///C:/Users/Admin/Desktop/Coding%20Data%20Files/data1.html?name=load' + encodeURIComponent(b);
document.location.href = url;
}
</script>
On my second page, this is my code:
<!DOCTYPE>
<html>
<head>
<h1>w</h1>
</head>
<body>
<p id="goalPage"></p>
<script>
window.onload = function () {
var url = document.location.href,
params = url.split('?')[1].split('&'),
data = {}, tmp;
for (var i = 0, l = params.length; i < l; i++) {
tmp = params[i].split('=');
data[tmp[0]] = tmp[1];
}
document.getElementById('goalPage').innerHTML = data.load;
}
</script>
</body>
</html>
I used many other forum answers to try to get a working solution, however I could not. Any help would be appreciated.

How to put the data taken from google custom search API to checkbox list

I have a code which takes data from google custom search API, There is no wrong with the custom search API part, it retrieves data without any error
<html>
<head>
<title>JSON Custom Search API Example</title>
</head>
<body>
<div id="content"></div>
<script>
var pageName = new Array();
var pageLink = new Array();
var pageDetails = new Array();
function hndlr(response) {
for (var i = 0; i < response.items.length; i++) {
var item = response.items[i];
pageName[i] = item.title;
pageLink[i] = item.link;
pageDetails[i] = item.htmlSnippet;
}
}
// Some codes
var search_query = 'https://www.googleapis.com/customsearch/v1?key=MY_KEY&cx=XXXXXXXXX&q='+query+'&start=1&callback=hndlr';
s = document.createElement('script');
s.src = search_query;
document.getElementsByTagName('head')[0].appendChild(s);
</script>
</body>
</html>
Required data are saved in the pageName, pageLink and pageDetails arrays.
Now I want display them with chechboxes and allow user to select them.
I need to take the links of the selected sites(pageLink variable) and pass it to anothe file using POST method
I tried using bellow code just before end of the body tag()
<form action="b.php" method="post">
<script>
for (var j = 0; j < 5; j++) {
document.write("<input type='checkbox' name='formDoor[]' id='"+j+"' value= '' />"+pageName[j]+"<br />");
document.getElementById(j).value = pageLink[j];
}
</script>
<input type="submit" name="formSubmit" value="Submit" />
</form>
But in the other file, it says variables are undefined. seems like variables doesn't pass to the 'b.php' file
Can anyone please tell me how to do this?
Your current code for adding checkboxes would likely be executed before the search result arrives (i.e.: before hndlr is executed), so all arrays are still empty. The solution would be to move the checkbox creation code into the hndlr function.
Here's the fixed page.
<html>
<head>
<title>JSON Custom Search API Example</title>
</head>
<body>
<div id="content"></div>
<form id="bform" action="b.php" method="post">
<input type="submit" name="formSubmit" value="Submit" />
</form>
<script>
var pageName = new Array();
var pageLink = new Array();
var pageDetails = new Array();
function hndlr(response) {
var f=document.getElementById('bform'), prev=f.children[0];
for (var i = 0; i < response.items.length; i++) {
var ele, item = response.items[i];
pageName[i] = item.title;
pageLink[i] = item.link;
pageDetails[i] = item.htmlSnippet;
ele = document.createElement('BR');
f.insertBefore(ele, prev);
prev = ele;
ele = document.createTextNode(pageName[i]);
f.insertBefore(ele, prev);
prev = ele;
ele = document.createElement('INPUT');
ele.type = 'checkbox';
ele.name = 'formDoor[]';
ele.id = i;
ele.value = encodeURI(pageLink[i]);
f.insertBefore(ele, prev);
prev = ele;
}
}
// Some codes
var search_query = 'https://www.googleapis.com/customsearch/v1?key=MY_KEY&cx=XXXXXXXXX&q='+query+'&start=1&callback=hndlr';
s = document.createElement('script');
s.src = search_query;
document.getElementsByTagName('head')[0].appendChild(s);
</script>
</body>
</html>