Reading and comparing contents of a file in javascript - javascript

I am trying to implement a Search Function for my app.
The search needs to involve several files that are in the server side.
So, I thought about reading each file to check if the search term is contained in them.
Code:
function search()
{
var term = document.getElementById("search-input").value;
var fileInput = document.getElementById("helpfiles");
var fileList = fileInput.files;
for (var i = 0; i < fileList.length; i++)
{
var reader = new FileReader();
reader.readAsText(fileList[i]);
reader.onload = function(e)
{
var text = reader.result;
alert(text) // test purpose only
if(text.indexOf(term) !== -1) // PROBLEM HERE
alert(fileList[i].name)
}
}
}
Until the code line:
alert(text)
everything works well.
The problem happens in the if-statement that it simply does not work as expected.

Related

Comparaison between different input files in javascript, cannot reach global variable

I'm trying to open different JSON files and compare each others values.
To do it, I used this to read the files. But I'm trying to save every data in a global variable 'data'. I think it's a asynchronous mistake but I'm pretty new to javascript and I didn't understand where the error come from.
Here is my code :
var data = {}
function readmultifiles(files) {
var reader = new FileReader();
function readFile(index) {
if( index >= files.length ) return;
var file = files[index];
reader.onload = function(e) {
// get file content
var bin = e.target.result;
bin = JSON.parse(bin);
for(task in bin['values']){
addData(bin['info']['date'],task,bin['values'][task]);
}
// do sth with bin
readFile(index+1);
}
reader.readAsBinaryString(file);
}
readFile(0);
console.log("readmultifiles");
console.log(data);
return data;
}
function addData(date, task, value){
if(data[task] == undefined){
data[task] = {};
}
data[task][date] = value;
}
var fileInput = document.querySelector('#file');
fileInput.addEventListener('change', function() {
console.log(fileInput);
var files = fileInput.files;
readmultifiles(files);
console.log("index");
console.log(data);
console.log(data['task_1']); // I can't display this object because 'undefinned'
});
What happens? When I'm trying to watch 'data', firefox console display me the object but I cannot watch inside the object.
Firefox display
What do I need to do to make a good solution. Should I use timers to wait?

FileReader reads only one file when multiple dropped

I am coding and form with and struggle tor ead each file. What i am getting is onlz one file being read.
Code below does log each iteration (console.log(i)), but does read and log only the last file, no matter what if read as dataURL or as Text
fileInput.on('change',function(){
var files= fileInput.prop('files');
console.log(files);
for(var i = 0; i < files.length; i++){
var reader = new FileReader();
console.log(i);
reader.onload = function(){
console.log(reader.result);
}
reader.readAsDataURL(files[i]);
}
});
I need each of multiple file to be logged in console. Thanks in advace
use let instead of var to properly scope the variable to the loop:
for (let i = 0; i < files.length; i++) { // Use let here
var reader = new FileReader();
console.log(i);
reader.onload = function() {
console.log(reader.result);
}
reader.readAsDataURL(files[i]);
}
You should use let instead of var for reader variable, since var is function scoped.
Didn't you forget the multiple attribute on the input element?

Waiting for FileReader to complete before continuing

So I am starting to work with HTML5 and JS for the first time to do some experiments for a future game. I am using FileReader to read in a local text file that will represent a map, and using a script to return an array of arrays based on the text read in.
The problem is, I am having trouble with undefined variables.. because my code is executing before FileReader is able to read in the input file and do its processing. This is my block that reads in:
document.getElementById('input').addEventListener('change', function() {
var file = this.files[0];
var reader = new FileReader();
reader.onload = function(e) {
let map = readMap(e.target.result);
}
reader.readAsText(file);
}, false);
readMap() is an external function that simply takes the raw text and returns a 2d array based on it. This all works great.. and I tested that by logging inside of the readMap function. The issue is that I am referencing this 'map' variable later on in this file in order to read it, render it, etc. I immediately get 'Uncaught ReferenceError: map is not defined' when loading my code. This makes perfect sense... since the above block did not yet get to execute.. as it is still waiting on the user to select an input file.
Here is one of the few functions that need access to the 'map' later on in the code:
function drawMap() {
let x = 0;
let y = 0;
for(var i=0; i<map.length;i++) {
for(var j=0; j<map[i].length;j++) {
if(map[i][j] === 1) {
ctx.fillRect(x,y,BLOCK_SIZE,BLOCK_SIZE);
x+=BLOCK_SIZE;
}
else if(map[i][j] === 'S') {
player.x = x;
player.y = y;
x+=BLOCK_SIZE;
}
else {
x+=BLOCK_SIZE;
}
}
x=0;
y+=BLOCK_SIZE;
}
}
Im not sure if that helps, but I just wanted to give an example of how I need to use this array.
Being fairly new to JS, I am really not yet finished wrapping my head around the idea of onLoads and callbacks... but my feeling is that they are the way to go about making this work. I assume I need to somehow tell the rest of my code not to execute until the 'map' object is finished being created.
I hope that was clear. Any help is appreciated!
Call the function drawMap() or any other function only after you have received the data, thus within reader.onload callback, if you want to access this map later, make map variable global e.g.:
var map;
document.getElementById('input').addEventListener('change', function() {
var file = this.files[0];
var reader = new FileReader();
reader.onload = function(e) {
map = readMap(e.target.result);
drawMap();
}
reader.readAsText(file);
}, false);
Or you can also pass map variable to drawMap function:
document.getElementById('input').addEventListener('change', function() {
var file = this.files[0];
var reader = new FileReader();
reader.onload = function(e) {
let map = readMap(e.target.result);
drawMap(map);
}
reader.readAsText(file);
}, false);
function drawMap(map) {
let x = 0;
let y = 0;
for(var i=0; i<map.length;i++) {
for(var j=0; j<map[i].length;j++) {
if(map[i][j] === 1) {
ctx.fillRect(x,y,BLOCK_SIZE,BLOCK_SIZE);
x+=BLOCK_SIZE;
}else if(map[i][j] === 'S') {
player.x = x;
player.y = y;
x+=BLOCK_SIZE;
} else {
x+=BLOCK_SIZE;
}
}
x=0;
y+=BLOCK_SIZE;
}
}
there is also FileReaderInstance.onloadend event
reader.onloadend = () => drawMap()

How can I read a file from an HTML input with js-xlsx?

I have an angular application where I am trying to read and parse a .xlsx file resorting to the js-xlsx JavaScript library. However I am having trouble opening the file on the JavaScript side.
On my html I have a simple input of type file that opens a file chooser where the user can choose an appropriate file. I had trouble using angular directives to send the file to a function on my controller, because ng-change would not update when the user chose a file only when the button of the input is pressed. I ended up having to resort to a mixture of plain old JavaScript together with some angular by adding 'onchange="angular.element(this).scope().handleFile(this)"' to my input.
add-quotation.html:
<div class="container-fluid" ng-controller="addQuotationController">
...
<input type="file" id="file" class="" onchange="angular.element(this).scope().handleFile(this)">
...
</div>
This solved my problem of not being able to send the file from the HTML to the JavaScript side of things. However, I'm having trouble opening the file. I have tried many examples from the official documentation but I haven't succeeded in making it work. This is my current code:
add-quotation.component.js:
$scope.handleFile = function(e) {
var files = e.target.files;
var i,f;
for (i = 0, f = files[i]; i != files.length; ++i) {
var reader = new FileReader();
var name = f.name;
reader.onload = function(e) {
var data = e.target.result;
var workbook = XLSX.read(data, {type: 'binary'});
/* DO SOMETHING WITH workbook HERE */
};
reader.readAsBinaryString(f);
}
}
I tried to debug and found out that the file does indeed get into the method but then an exception occurs when trying to access "e.target.files;"
I'm completely lost in how to fix this and the examples that I've seen are of no help. What am I doing wrong?
You are looking for wrong object rather you should be using e.files. This is because e represents the <input> element; aka the value of this in your onchange attribute: onchange="angular.element(this).scope().handleFile(this)"
$scope.handleFile = function(e) {
console.log(e.files);
var files = e.files;
var i,f;
for (i = 0, f = files[i]; i != files.length; ++i) {
var reader = new FileReader();
var name = f.name;
reader.onload = function(e) {
var data = e.target.result;
var workbook = XLSX.read(data, {type: 'binary'});
/* DO SOMETHING WITH workbook HERE */
};
reader.readAsBinaryString(f);
}
}
you don't need FileReader(), instead use Blob.arrayBuffer()
$scope.handleFile = async function(e) {
var workbook = XLSX.read(await e.files.arrayBuffer(), {type: 'binary'});
// .....
}

Getting the content of each file in multiple file input using jquery

I need to fetch the content of each file in multiple file input using jquery and based on the file content i need to do some modifications in my page. Here is the code I have written to do the same. Here what is happening is If I select 3 files I am getting the content of 3rd file alone. If I use the index number instead of looping I am able to get the contents But If I use looping I am getting the last files content alone. Could someone explain me whats wrong with it ?
<input type="file" name="xsd" id="xsd" multiple="multiple">
$('#xsd').change(function(){
input = document.getElementById('xsd');
for(var i = 0; i < input.files.length ; i++)
{
file = input.files[i];
fr = new FileReader();
fr.readAsText(file);
fr.onload = function(e) {
var filecontent = fr.result;
// My logic here
}
}
});
Your problem is that the onload function is getting it's "fr" from a closure.
You can create a separate closure for each of the onload-callbacks by using an immediately-invoked anonymous function like this:
$('#file').change(function(){
input = document.getElementById('file');
for(var i = 0; i < input.files.length ; i++)
{
(function(i) {
var file = input.files[i];
var fr = new FileReader();
fr.onload = function(e) {
var filecontent = fr.result;
// My logic here
}
fr.readAsText(file);
})(i);
}
});

Categories