The user uploads images with a form. The images should all be displayed in the canvas. Only one of multiple images shows. Maybe the images are not properly loaded?
html:
let value = 0;
var images = [];
function setup() {
createCanvas(320, 270);
background(0);
const form = document.querySelector('form');
frameRate(2);
form.addEventListener('submit', e => {
e.preventDefault();
var preview = document.querySelector('img'); //selects the query named img
var files = form.querySelector('[type=file]').files;
if (files[0]) {
for(let i = 0; i < files.length; i++){
var reader = new FileReader();
reader.onloadend = function () {
//preview.src = reader.result;
images[i] = loadImage(reader.result);
console.log('new image added')
console.log(images[i]);
}
reader.readAsDataURL(files[i]); //reads the data as a URL
}
}
});
}
let cursor = 0;
function draw() {
background(0);
if(images.length > 0){ image(images[cursor], 0, 0, width, height - 20); }
cursor ++;
if(cursor >= images.length){ cursor = 0}
fill(255);
textSize(16);
text(value, 10, height - 10);
console.log(cursor);
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>image_classification</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/p5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/addons/p5.dom.min.js"></script>
<script src="https://unpkg.com/ml5#0.1.1/dist/ml5.min.js"></script>
<script src="sketch.js"></script>
</head>
<body>
<h1>Welcome to the site!</h1>
<form id="imgs" method="post" enctype="multipart/form-data">
images:
<input type="file" name="files[]" multiple>
<input type="submit" value="Upload File" name="submit">
</form>
<br/>
</body>
</html>
I have no idea where the problem even lays. Is it me inserting the images into the array incorrectly, or am I doing something wrong with the asynchronous nature of JavaScript?
Thanks in advance.
Your problem is caused by JavaScript scoping.
Take a look at this part of your code:
for(let i = 0; i < files.length; i++){
var reader = new FileReader();
reader.onloadend = function () {
images[i] = loadImage(reader.result);
}
reader.readAsDataURL(files[i]);
}
Because you're using the var keyword, your reader is actually in function scope. From MDN:
The scope of a variable declared with var is its current execution context, which is either the enclosing function or, for variables declared outside any function, global. If you re-declare a JavaScript variable, it will not lose its value.
This is why your reader variable only appears to work for one of your images.
The simplest fix to this is to use const instead of var here:
const reader = new FileReader();
The const keyword creates variables in block scope which is probably what you expected var to do in the first place.
Related
I am using the LoadBytes function from P5.JS which returns an object but I am unable to access "object" via using ".bytes" or "['bytes']".
For some reason when running a live server it seems to work perfectly.
function get_rom () {
var fileList = document.getElementById("rom").files;
var fileReader = new FileReader();
if (fileReader && fileList && fileList.length) {
url = URL.createObjectURL(fileList[0])
return loadBytes(url)
}
}
function loadarom () {
object = get_rom()
print(object.bytes[1]) // <-- issue here
}
When using loadBytes() the returned object will not immediately have the bytes array populated. You need to use the callback parameter to loadBytes():
let loadBtn;
function setup() {
noCanvas();
noLoop();
loadBtn = createButton("Load Rom");
loadBtn.mousePressed(loadarom);
}
function get_rom(onSuccess) {
let fileList = document.getElementById("rom").files;
// Alternate method using FileReader has been commented out
// let fileReader = new FileReader();
/*
fileReader.addEventListener("load", function () {
// convert image file to base64 string
loadBytes(fileReader.result, onSuccess);
}); */
if (fileList && fileList.length) {
loadBytes(URL.createObjectURL(fileList[0]), onSuccess);
// fileReader.readAsDataURL(fileList[0]);
}
}
function loadarom() {
get_rom(obj => {
print(obj.bytes[0]);
})
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.js"></script>
</head>
<body>
<input id="rom" type="file" />
</body>
</html>
Barley don't need p5.js for such a easy task.
use blob.arrayBuffer()
<script type="module">
var file = new File(['abc'], 'abc.txt')
var bytes = new Uint8Array(await file.arrayBuffer())
console.log(bytes)
</script>
(SO! You should support top level await in a async IIFE fn or start adding type="module" to js-code
I am building an ASP webform application. I used
<asp:FileUpload runat="server" ID="fubillPhoto" onchange="showPreviewBill(this);" />
...to upload a pdf file. I want users to be able to review the uploaded file before submitting the form.
My idea is to create an element. When the user clicks on it a new tab open with PDF file. unfortunately I could not apply my idea... Here is my code:
HTML
<asp:FileUpload runat="server" ID="fuBillPhoto" onchange="showPreviewBill(this);" />
<div runat="server" id="divPdfBill" class="hidden">
<a runat="server" id="pdfBilllink" href="#" target="_blank">click here</a>
</div>
=====
Javascript
function showPreviewBill(input) {
var pdfLink = document.getElementById('#<%=pdfBilllink.ClientID %>');
var file = document.querySelector('#<%=fubillPhoto.ClientID %>').files[0];
var reader = new FileReader();
reader.onloadend = function () {
if (reader.result) {
$('#<%=pdfBilllink.ClientIDMode %>').attr("href", reader.result);
$('#<%=divPdfBill.ClientID %>').attr("class", "");
}
}
$('#<%=pdfBilllink.ClientIDMode %>').attr("href", reader.result);
It does not work! Please advise.
Load data uri from input file control use javascript file api.
Convert data uri to binary.
Show binary data in canvas using PDF.js.
here is a reference on how to do that with code
[link] https://forums.asp.net/t/2062665.aspx?Preview+pdf+file+before+upload
code from above reference website
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="../Scripts/jquery-1.10.2.js"></script>
<script src="https://mozilla.github.io/pdf.js/build/pdf.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#pdfInp").change(function () {
if (this.files && this.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
showInCanvas(e.target.result);
}
reader.readAsDataURL(this.files[0]);
}
});
function convertDataURIToBinary(dataURI) {
var BASE64_MARKER = ';base64,';
var base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
var base64 = dataURI.substring(base64Index);
var raw = window.atob(base64);
var rawLength = raw.length;
var array = new Uint8Array(new ArrayBuffer(rawLength));
for (i = 0; i < rawLength; i++) {
array[i] = raw.charCodeAt(i);
}
return array;
}
function showInCanvas(url) {
// See README for overview
'use strict';
// Fetch the PDF document from the URL using promises
var pdfAsArray = convertDataURIToBinary(url);
PDFJS.getDocument(pdfAsArray).then(function (pdf) {
// Using promise to fetch the page
pdf.getPage(1).then(function (page) {
var scale = 1.5;
var viewport = page.getViewport(scale);
// Prepare canvas using PDF page dimensions
var canvas = document.getElementById('the-canvas');
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
// Render PDF page into canvas context
var renderContext = {
canvasContext: context,
viewport: viewport
};
page.render(renderContext);
});
});
}
});
</script>
</head>
<body>
<form id="form1" >
<p>
<input type='file' id="pdfInp" />
<canvas id="the-canvas" style="border:1px solid black"></canvas>
</p>
</form>
</body>
</html>
<asp:FileUpload runat="server" ID="fubillPhoto" onchange="showPreviewBill(this);"
/>`enter code here`
I'm currently learning JavaScript and I'm struggling to read a txt file and use its contents in the program, what I have so far:
fileBtn.addEventListener("change", function()
{
var content = [];
var file = fileBtn.files[0];
readFile(file, function(data)
{
console.log(JSON.parse(data));
//content.push(JSON.parse(data)) doesn't work, data is undef.
});
});
and a function readFile
function readFile(file, f)
{
var reader = new FileReader();
reader.onload = function(evt)
{
f(evt.target.result);
};
reader.readAsText(file);
}
My txt file is currenty only containing a "1", and it logs this number to the console but I can't work with it, if I try to push it into an array the values is suddenly undefined. My goal is to use the content of the file in the program later on
1 . no need to use JSON.parse if the text file only contain string .
data is containing all the text file content
2 . you need to put var content = [];
globally and not inside the function readFile
follow this snippet of code i think it will solve your problem
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<label for="file-upload" class="custom-file-upload">
Custom Upload
</label>
<input id="file-upload" type="file" />
<input id="log-content" type="button" value="Click Me"/>
</body>
<script>
var content = [];
function readFile(file, f) {
var reader = new FileReader();
reader.onload = function (evt) {
f(evt.target.result);
};
var text = reader.readAsText(file);
}
var fileBtn = document.getElementById("file-upload");
var logContnt = document.getElementById("log-content");
logContnt.addEventListener("click", function () {
alert(content);
})
fileBtn.addEventListener("change", function () {
var file = fileBtn.files[0];
readFile(file, function (data) {
content.push(data);
});
});
</script>
</html>
I would like to start by saying that (coming from c++ and python) I am totally new to JS and so I welcome any wise suggestions regarding my code.
I wish to read a number of files using the HTML5 file API, then open them with JS, perform some manipulation and download the results zipped. My problem is that reading the files seems to be an asynchronous operation, and I don't really see an elegant way to wait for them all to finish and then zip the results.
One possible solution is presented here:
https://stackoverflow.com/a/17491515
but I am wondering if one can do better than using a global flag.
I also have a problem with retrieving the result from the async function as I have no idea how to get back new_file_list in changeCharsInFiles.
Thank you!
Code example:
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body >
<div class="container">
<div class="jumbotron">
<h3>Add Files Here</h3>
<input type="file" id="the-file-field" multiple>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.5/jszip.min.js"></script>
<script src="http://cdn.jsdelivr.net/g/filesaver.js"></script>
<script>
########### SEE JS BELOW #####################
</script>
</body>
JS:
if (window.File && window.FileReader && window.FileList && window.Blob) {
//functions
function zipMyFilesAndSave(file_list){
var zip = new JSZip();
for (var i = 0; i<file_list.length; i+=1)
{
zip.file(file_list[i].name, file_list[i] );
}
zip.generateAsync({type:"blob"}).then(
function (blob) {
saveAs(blob, "hello.zip");
},
function (err) {
jQuery("#blob").text(err);
});
}
function changeCharsInFiles(file_list){
var new_file_list = [];
for (var i = 0; i<file_list.length; i+=1)
{
var file = file_list[i]
var reader = new FileReader();
reader.onload = function() {
//alert(reader.result);
var txt = reader.result;
console.log("txt: ",txt)
var new_txt = ""
var allTextLines = txt.split(/\r\n|\n/);
for (var j = 0; j<allTextLines.length; j+=1)
{
var res = allTextLines[j].replace("a", "A");
res = res.replace("b", "B");
res = res.replace("c", "C");
res = res.replace("d", "D");
new_txt += res + "\n"
}
console.log("new_txt: ", new_txt)
var new_file = new Blob([new_txt], {type: "text/plain"});
new_file_list.push(new_file); //<---------------------------how do I get this back?
}
reader.readAsText(file);
}
return new_file_list;
}
//watcher
$( "#the-file-field" ).change(function() {
console.log("files have been chosen")
var file_list = this.files
file_list = changeCharsInFiles(file_list)
zipMyFilesAndSave(file_list)
});
} else {
alert('The File APIs are not fully supported in this browser.');
}
Try reading up on the Promise class, it was developed to make asynchronous operations easier:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
In your case, you could use it like this:
function changeCharsInFiles(file_list){
let promises = [];
for (let file of file_list) {
let filePromise = new Promise(resolve => {
let reader = new FileReader();
reader.readAsText(file);
reader.onload = () => resolve(reader.result);
});
promises.push(filePromise);
}
Promise.all(promises).then(fileContents => {
// fileContents will be an array containing
// the contents of the files, perform the
// character replacements and other transformations
// here as needed
});
}
This is just a rough outline of the solution. I'd suggest you experiment a bit with Promises first (it can be a fairly deep topic) to figure out the basic principles, and then apply something like the above.
<!DOCTYPE html >
<html>
<head>
<title>Untitled Page</title>
<script src = "https://ajax.googleapis.com/ajax/libs/angularjs/1.3.3/angular.min.js"></script>
</head>
<body>
<input type="file" name="file" id="file">
<script type="text/javascript">
document.getElementById('file').onchange = function(){
// create a new instance of FileReader
var reader = new FileReader();
var file = this.files[0];
var reader = new FileReader();
reader.onload = function(progressEvent){
// By lines
var lines = this.result.split('\n');
for(var line = 0; line < 3; line++){
document.write(lines[line]);
document.write("<br>");
}
};
reader.readAsText(file);
};
</script>
</body>
</html>
this is the code I used to read text file using given as a input. Without given as a input I want to read file which already know path.(eg: "index.html") .How could I want to change this code..