I am trying to print the text multiple files in html. I succeeded in printing the single file. But I am unable to print the text output of a multiple files. Can you please help me in correcting the code?`
<!DOCTYPE html>
<html>
<body>
<h1> Testing programs </h1>
<input type="file" id="fileinput" multiple />
<pre id="file-content"></pre>
<h3>Contents of the file:</h3>
<script type="text/javascript">
function readMultipleFiles(evt) {
//Retrieve all the files from the FileList object
var files = evt.target.files;
if (!files) {
for (var i=0, f; f=files[i]; i++) {
var r = new FileReader();
r.onload = (function(f) {
return function(e) {
var contents = e.target.result;
displayContents(contents);
};
});
r.readAsText(f);
}
} else {
alert("Failed to load files");
}
function displayContents(contents) {
var element = document.getElementById('file-content');
element.innerHTML = contents;
}
document.getElementById('fileinput').addEventListener('change', readMultipleFiles, false)
</script>
</body>
</html>`
There is no need to use closure in provided snippet. As suggested by gurvinder, use innerHTML +=
if condition should be like if (files) as it will be true if length of files is greater than 0
Try this:
function readMultipleFiles(evt) {
var files = evt.target.files;
if (files) {
for (var i = 0; i < files.length; i++) {
var r = new FileReader();
r.onload = function(e) {
var contents = e.target.result;
displayContents(contents);
};
r.readAsText(files[i]);
}
} else {
alert("Failed to load files");
}
}
function displayContents(contents) {
var element = document.getElementById('file-content');
element.innerHTML += contents;
}
document.getElementById('fileinput').addEventListener('change', readMultipleFiles, false);
<h1> Testing programs </h1>
<input type="file" id="fileinput" multiple />
<pre id="file-content"></pre>
<h3>Contents of the file:</h3>
Also refer this fiddle : https://jsfiddle.net/rayon_1990/2cwr4c00/
just replace the displayContents method as
function displayContents(contents) {
var element = document.getElementById('file-content');
element.innerHTML += contents; //observe + before =
}
since it needs to append the files rather than replace the last one
Related
I want to create a web app to make simple actions on a csv. For example, the user would upload a csv file then all columns would show up on a form, the user could select some columns to remove them from the file and finally the user could download the modified file.
I have already done something working but there is definitely room for improvement. The most important one is that in my current solution I have to parse the file two times because Papaparse is asynchronous, one time to get the columns and another time to remove columns from the user input.
Is there a way to parse the file only one time and then use the resulting object through the rest of the code ?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>CSV Manipulator</title>
<link rel="stylesheet" href="style.css" />
</head>
<script src="script.js"></script>
<script src="papaparse/papaparse.min.js"></script>
<body>
<div id="csv_columns">
<label for="file">choose csv file</label>
<input id="input-file" autocomplete="off" type="file" id="file" name="file">
<input type="button" value="download CSV" onclick="downloadCSV()">
</div>
<div id="schema_select">
<form action="#">
<label for="schema">Schema</label>
<select name="schema" id="schema" multiple>
</select>
<button id="submit-option">Submit</button>
</form>
<input type="text" , autocomplete="off" name="csv-file-name" id="csv-file-name">
</div>
</body>
</html>
window.onload = function () {
inputElement = document.getElementById("input-file")
inputElement.onchange = function (event) {
var fileList = inputElement.files;
parseDatatoGetSchema(fileList[0])
}
var newCsvFileName = document.getElementById("csv-file-name").value
var submitOption = document.getElementById("submit-option");
submitOption.addEventListener("click", function (event) {
var columnsToRemove = handleSubmit(event)
console.log(columnsToRemove)
parseDataRemoveColumns(inputElement.files[0], columnsToRemove, newCsvFileName)
});
}
function removeColumns(parsedCsv, columnsToRemove) {
newParsedCsv = []
for (i = 0; i < parsedCsv.data.length; i++) {
newObj = {}
for (key in parsedCsv.data[i]) {
if (!(columnsToRemove.includes(key))) {
newObj[key] = parsedCsv.data[i][key]
}
}
newParsedCsv.push(newObj)
}
return newParsedCsv
}
function showCsvSchema(results) {
//Data is usable here
var schemaForm = document.getElementById("schema")
// ajoute le nœud texte au nouveau div créé
for (i = 0; i < Object.keys(results.data[0]).length; i++) {
var opt = document.createElement('option');
opt.value = Object.keys(results.data[0])[i];
opt.innerHTML = Object.keys(results.data[0])[i];
schemaForm.appendChild(opt);
}
}
function handleSubmit(event) {
event.preventDefault();
var schemaSelect = document.getElementById("schema")
columnsToRemove = [...schemaSelect.selectedOptions].map(o => o.value)
return columnsToRemove
}
function parseDatatoGetSchema(url) {
csvData = []
Papa.parse(url, {
header: true,
dynamicTyping: true,
complete: function (results) {
showCsvSchema(results)
}
});
}
function parseDataRemoveColumns(url, columnsToRemove, newCsvFileName) {
csvData = []
Papa.parse(url, {
header: true,
dynamicTyping: true,
complete: function (results) {
newParsedCsv = removeColumns(results, columnsToRemove)
unParsedNewCsv = Papa.unparse(newParsedCsv)
downloadCSV(unParsedNewCsv, newCsvFileName)
}
});
}
function downloadCSV(unparse_csv, newCsvFileName) {
var csvData = new Blob([unparse_csv], { type: 'text/csv;charset=utf-8;' });
var csvURL = null;
if (navigator.msSaveBlob) {
csvURL = navigator.msSaveBlob(csvData, `${newCsvFileName}.csv`);
}
else {
csvURL = window.URL.createObjectURL(csvData);
}
var tempLink = document.createElement('a');
tempLink.href = csvURL;
tempLink.setAttribute('download', `${newCsvFileName}.csv`);
tempLink.click();
location.reload()
}
There are many solution to to this but I found few or none in javascript on html webpage. I have a data file called sample.txt located where my html file is. My goal is to load txt file into the array that can be used to create a table and displayed on html file. My sample.text file has the following data:
sin 0.2 time 0.22222
cos 0.3 time 0.43434
tan 0.1 time 0.22221
I am new to Javascript and I admit that it is more difficult than other programming languages.
I am familiar with javascript in node.js mode but not in html mode. I managed to create html web page (as shown below) and display basics like text and numbers in script mode. I also managed to load txt file and display it after pressing a button in script mode. This txt load method was the only method that worked for me. require (js) method did not work nor import. How do I create data array from this working mode?
Below is my complete code (corrected),
<!DOCTYPE html>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<title>Read Text File</title>
</head>
<body>
<input type="file" name="inputfile"
id="inputfile">
<br>
<pre id="output"></pre>
<script>
var file = document.getElementById('inputfile');
file.addEventListener('change', () => {
var txtArr = [];
var fr = new FileReader();
fr.onload = function() {
// By lines
var lines = this.result.split('\n');
for (var line = 0; line < lines.length; line++) {
txtArr = [...txtArr, ...(lines[line].split(" "))];
}
}
fr.onloadend = function() {
console.log(txtArr);
document.getElementById('output').textContent=txtArr.join("");
document.getElementById("output").innerHTML = txtArr[1];
console.log(txtArr[1]);
}
fr.readAsText(file.files[0]);
})
</script>
</body>
</html>
Using FileReader, get the string line by line and then split it and merge it into the resultArr as follows:
var file = document.getElementById('inputfile');
file.addEventListener('change', () => {
var txtArr = [];
var fr = new FileReader();
fr.onload = function() {
// By lines
var lines = this.result.split('\n');
for (var line = 0; line < lines.length; line++) {
txtArr = [...txtArr, ...(lines[line].split(" "))];
}
}
fr.onloadend = function() {
console.log(txtArr);
document.getElementById('output').textContent=txtArr.join("");
}
fr.readAsText(file.files[0]);
})
<!DOCTYPE html>
<html>
<head>
<title>Read Text File</title>
</head>
<body>
<input type="file" name="inputfile"
id="inputfile">
<br>
<pre id="output"></pre>
</body>
</html>
The reason the other methods didn't work is because Javascript does not have access to the filesystem. You need a server side language for this, like NodeJS.
Anyway, here's some pure Javascript code that lets you load text files, split result into a text array for each line and split those again to have data arrays for each line of data. As a little bonus, I also added a method to download everything in a text file again:
function loadFile(input, onloadCallback){
const fr = new FileReader();
fr.onload = onloadCallback;
fr.readAsText(input);
}
/* Save file and force download */
function saveFile(data, fileName){
const blob = new Blob([data], {type: 'text/csv'});
if(window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(blob, fileName);
} else {
var elem = window.document.createElement('a');
elem.href = window.URL.createObjectURL(blob);
elem.download = fileName;
document.body.appendChild(elem);
elem.click();
document.body.removeChild(elem);
}
}
/* Working with text files */
function openFile(ev){
loadFile(ev.target.files[0], function(e) {
// Get all the text as a string
const result = e.target.result;
// Make array out of result for each line
const textArray = result.split("\r\n");
// How to add new lines to the array if you want
textArray.push("tan 0.2 time 0.23641");
// Create dataArray for each line
let dataArray = [];
for(let i = 0; i < textArray.length; i++){
const data = textArray[i].split(" ");
dataArray.push(data);
}
// dataArray now contains arrays for each line of data
console.log(dataArray);
// Here's how you'd put a normal array back into a string
const newString = textArray.join("\r\n");
// Finally a way to download a file with the new string inside it
saveFile(newString, 'test.txt');
});
}
tried to find some useful answer in existing threads but nothing is really matching my issue. I guess there is a quick fix to it, i just cannot see it.
I have a HTML form and want to upload the file to my google drive (works great) and save the text fields to my spreadsheet (does not work at all).
I just cannot find any major difference between the two functions, its frustrating!
Below my code, and here is also the [link to my public script][1].
Form:
<!DOCTYPE html>
<form id="myForm">
<input type="text" name="myName" placeholder="Your name..">
<input type="file" name="myFile">
<input type="submit" value="Upload File"
onclick="this.value='Uploading..';
google.script.run.withSuccessHandler(fileUploaded)
.uploadFiles(this.parentNode);
return false;
google.script.run.withSuccessHandler(fileUploaded)
.doPost(this.parentNode);">
</form>
<div id="output"></div>
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
<style>
input { display:block; margin: 20px; }
</style>
[1]: https://script.google.com/d/1K9jGl7ALHCZ93rz8GoeV8t7PE_7vgbNZlLJed1h6ZWyuoon11gIbik24/edit?usp=sharing
server.gs:
function doGet(e) {
var html = HtmlService.createTemplateFromFile("form");
html = html.evaluate();
html.setSandboxMode(HtmlService.SandboxMode.IFRAME);
return html;
}
function uploadFiles(form) {
try {
var dropbox = "Customer Shapes";
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var blob = form.myFile;
var file = folder.createFile(blob);
file.setDescription("Uploaded by " + form.myName);
return "File uploaded successfully " + file.getUrl();
} catch (error) {
return error.toString();
}
}
function doPost(form) { // change to doPost(e) if you are recieving POST data
html.setSandboxMode(HtmlService.SandboxMode.EMULATED);
var name = form.myName;
var url="url...";
var message = 'Ram';
var submitSSKey = '...kHI';
var sheet = SpreadsheetApp.openById(submitSSKey).getActiveSheet();
var lastRow = sheet.getLastRow();
var targetRange = sheet.getRange(lastRow+1, 1, 2, 2).setValues([[name,url]]);
}
Thank You for Your kind help!
Martin
If you are going to use google.script.run, then it's pointless to have a function named doPost(). And it's also pointless to have a submit type input tag: type="submit"
If you want to run a withSuccessHandler(fileUploaded) to change the display, you can't have a button inside of the form. It will cause the display to go blank.
And you don't need two google.script.run calls. You need multiple changes and improvements:
form.html
<form id="myForm">
<input type="text" name="myName" placeholder="Your name..">
<input type="file" name="myFile">
</form>
<input type="button" value="Upload File"
onclick="this.value='Uploading..';
var theForm = document.getElementById('myForm');
google.script.run.withSuccessHandler(fileUploaded)
.processFormData(theForm);">
<div id="output"></div>
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
<style>
input { display:block; margin: 20px; }
</style>
server.gs
function processFormData(form) {
uploadFiles(form.myFile);//Call first function to process the file
var innerArray = [];
var outerArray = [];
innerArray.push(form.myName);
innerArray.push(form.myFile);
outerArray.push(innerArray);//Call second function to write data to SS
writeDataToSS(outerArray);
};
function uploadFiles(theFile) {
try {
var dropbox = "Customer Shapes";
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var blob = theFile;
var file = folder.createFile(blob);
file.setDescription("Uploaded by " + theFile);
return "File uploaded successfully " + file.getUrl();
} catch (error) {
return error.toString();
}
}
function writeDataToSS(values) {
//html.setSandboxMode(HtmlService.SandboxMode.EMULATED);
var url="url...";
var message = 'Ram';
var submitSSKey = '...kHI';
var sheet = SpreadsheetApp.openById(submitSSKey).getActiveSheet();
var lastRow = sheet.getLastRow();
var targetRange = sheet.getRange(lastRow+1, 1, 1, 2).setValues(values);
}
The html file is not a template, it does not have a scriptlet in it. Just use createHtmlOutputFromFile():
function doGet(e) {
var html = HtmlService.createHtmlOutputFromFile("form");
html.setSandboxMode(HtmlService.SandboxMode.IFRAME);
return html;
}
<input type="file" id="input" multiple onchange="handleFiles(event.target)">
<script language="javascript" type="text/javascript">
<!--
function handleFiles(input)
{
for (i = 0; i < input.files.length; i++)
{
var reader = new FileReader();
reader.onload = function()
{
alert(reader.result)
};
reader.readAsText(input.files[i]);
}
}
//-->
</script>
I am trying to display the contents of some files that I upload. It works fine if I select a single file, but if I select multiple files, only the content of one file is displayed, rest all are blank. What am I doing wrong?
You just need to amend it slighty to do the following:
<input type="file" id="input" multiple onchange="handleFiles(event.target)">
<script language="javascript" type="text/javascript">
function handleFiles(input)
{
for (var i = 0; i < input.files.length; i++) { //for multiple files
(function(file) {
var name = file.name;
var reader = new FileReader();
reader.onload = function(e) {
// get file content
var text = e.target.result;
alert(text)
}
reader.readAsText(file, "UTF-8");
})(input.files[i]);
}
}
</script>
Reference: https://stackoverflow.com/a/9815648/3088780
I think jquery help you easily
HTML:
<script src="jquery-2.2.0.min.js"></script>
<input type="file" multiple="multiple" />
<ul id="output">
</ul>
Jquery:
$('input:file[multiple]').change(
function(e){
console.log(e.currentTarget.files);
var numFiles = e.currentTarget.files.length;
for (i=0;i<numFiles;i++){
fileSize = parseInt(e.currentTarget.files[i].size, 10)/1024;
filesize = Math.round(fileSize);
$('<li />').text(e.currentTarget.files[i].name).appendTo($('#output'));
$('<span />').addClass('filesize').text('(' + filesize + 'kb)').appendTo($('#output li:last'));
}
});
reference from : https://stackoverflow.com/a/7719334/5566169
I am just working on a web site for fun and I was wondering if you could use JavaScript to read in a local text file and then display it HTML. So for example if I had a text file saved with my project then could I write a function in JavaScript that reads the entire file and then just displays all that text within on the web page?
I've looked around and tried to find something that will do this, but I don't think I fully understand. I have:
function readFile(fileName){
var fileRead = new ActiveXObject('Scripting.FileSystemObject');
text = fileRead.OpenTextFile(fileName, 1, false, 0);
while(!text.AtEndOfSteam){
text += text.ReadLine();
}
text.Close();
}
I don't know if this is will work or do what I want to do. So my question is, how do I use JavaScript to read in a text file, then display the contents of that text file on a webpage in HTML?
You have to use the File API.
var input = document.getElementById("myFile");
var output = document.getElementById("output");
input.addEventListener("change", function () {
if (this.files && this.files[0]) {
var myFile = this.files[0];
var reader = new FileReader();
reader.addEventListener('load', function (e) {
output.textContent = e.target.result;
});
reader.readAsBinaryString(myFile);
}
});
<input type="file" id="myFile">
<div id="output"></div>
EDIT
After reading your comment, i think this is what you want.
var output = document.getElementById("output");
$("a").on("click", function (e) {
e.preventDefault();
$.ajax(this.href).done(function(data) {
output.textContent = data;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="output"></div>
Link to file
<html>
<head>
<title>reading file</title>
</head>
<body>
<input type="file" id="myFile">
<hr>
<!--<div style="width: 300px;height: 0px" id="output"></div>-->
<textarea style="width:500px;height: 400px" id="output"></textarea>
<script>
var input = document.getElementById("myFile");
var output = document.getElementById("output");
input.addEventListener("change", function () {
if (this.files && this.files[0]) {
var myFile = this.files[0];
var reader = new FileReader();
reader.addEventListener('load', function (e) {
output.textContent = e.target.result;
});
reader.readAsBinaryString(myFile);
}
});
</script>
</body>
</html>