reader.onload: Looping Jquery function - javascript

I was wondering if it is possible to get this right. I am using a Jquery cropping tool (cropit). I am trying to put multiple file inputs into several cropper instances at once. Unfortunately it doesnt work that well.
For example, if I upload three images, the first two croppers are empty and the last one gets one of the images randomly. Here is the function:
function handleCropit(files) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
var count = counterCropit();
var reader = new FileReader();
reader.onload= function(e){ $('#image-cropper'+count).cropit('imageSrc', e.target.result);};
reader.readAsDataURL(file);
}
}

Figured it out!
function handleCropit(files) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
var count = counterCropit();
var croper = $('#image-cropper'+count);
var reader = new FileReader();
reader.onload= (function (yo) {return function(e){ yo.cropit('imageSrc', e.target.result);}})(croper);
reader.readAsDataURL(file);
}
}

Related

Importing data to localstorage

Could anybody help me out sorting the following code or help me in the right direction?
It needs to import data from a .txt file and store it into localstorage as key & value.
Key is before ':' and value comes after it. A new key / value is separated after each ','.
Sample data from .txt file is:
nl-step1chapter1Question6:U2FsdGVkX19bRT84xShxK+29ypgj1d6ZHt+2DVBCUtY=,nl-step1chapter1Question1:U2FsdGVkX1+/Sv61L69bLvQGTkf1A9Uy4jgJ3KZTkzI=,nl-step1chapter1Question4:U2FsdGVkX1+9SVVOvTKeZuaQGj58L5WnEgL8htS0c7U=,jft:320982da-f32a-46a2-a97c-605ebe305518,nl-step1chapter1Question5:U2FsdGVkX19pi8A+PQZ7rBNCWrFeCwl2HdXpV+wWkFk=,nl-step1chapter1Question2:U2FsdGVkX19hnRnpmP3omzYNU0jXd3NtsHM+mvGYBnc=,nl-step1chapter1Question3:U2FsdGVkX1+hPbMRN+x19y7pF73eXoxG0qK1igZYZbA=
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script type="application/x-javascript">
$(function importData() {
document.getElementById('file').onchange = function () {
//debugger;
var file = this.files[0];
var reader = new FileReader();
reader.onload = function (progressEvent) {
//console.log(this.result.split(','));
var lines = this.result.split(',');
var list = [];
for (var line = 0; line < lines.length; line++) {
list.push(lines[line]);
localStorage.setItem([line],lines);
}
};
reader.readAsText(file);
};
});
</script>
Any help is much appreciated!
The way you are using FileReader doesn't seem correct to me. This is how your importData() function should be:
$(function importData() {
document.getElementById('file').onchange = function (event) {
var input = event.target;
var reader = new FileReader();
reader.onload = function () {
var text = reader.result;
var lines = text.split(',');
for (var line = 0; line < lines.length; line++) {
let elements = lines[line].split(':');
localStorage.setItem(elements[0], elements[1]);
}
};
reader.readAsText(input.files[0]);
};
});
It will insert the elements in the localStorage as you described. For example: key = step1chapter1Question1 and value = U2FsdGVkX1+/Sv61L69bLvQGTkf1A9Uy4jgJ3KZTkzI=

Issue in a for loop, get only the last item [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 5 years ago.
I´m using fileReader to read the content of all selected files. After reading them with the fileReader API, I append the content to the DOM. That works perfectly.
It creates one p element per file.
Now I want to store each file content to local storage as well. Unfortunately, It stores only the last item. What´s going wrong? Thank you for your tips.
JS
$("input[name='uploadFile[]']").on("change", function() {
var files = !!this.files ? this.files : [];
if (!files.length || !window.FileReader)
return;
for (var i = 0; i < files.length; i++) {
(function(file) {
var name = file.name;
var reader = new FileReader();
reader.onload = function(e) {
var textObject = event.target.result.replace(/\r/g, "\n");
var textHTML = event.target.result.replace(/\r/g, "<br/>");
var text = e.target.result;
var p = document.createElement("p");
p.innerHTML = textHTML;
$('#results').append(p);
localStorage.setItem('letter'+ i, JSON.stringify(textObject));
};
reader.readAsText(file, 'ISO-8859-1');
})(files[i]);
}
});
The problem is that, by the time the onload is fired, i has been changed by the loop. This means that localStorage.setItem('letter'+ i will always refer to the last element in the array. You actually have the correct fix already in place -- the immediately invoked function expression -- but you need to add i as a parameter as well.
(function(file, index) {
var name = file.name;
var reader = new FileReader();
reader.onload = function(e) {
var textObject = event.target.result.replace(/\r/g, "\n");
var textHTML = event.target.result.replace(/\r/g, "<br/>");
var text = e.target.result;
var p = document.createElement("p");
p.innerHTML = textHTML;
$('#results').append(p);
localStorage.setItem('letter'+ index, JSON.stringify(textObject));
};
reader.readAsText(file, 'ISO-8859-1');
})(files[i], i);
There is also another solution if you can use let
let allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. This is unlike the var keyword, which defines a variable globally, or locally to an entire function regardless of block scope.
Here is what it could look like:
for (let i = 0; i < files.length; i++) {
let file = files[i];
let name = file.name;
let reader = new FileReader();
reader.onload = function(e) {
var textObject = e.target.result.replace(/\r/g, "\n");
var textHTML = e.target.result.replace(/\r/g, "<br/>");
var text = e.target.result;
var p = document.createElement("p");
p.innerHTML = textHTML;
$('#results').append(p);
localStorage.setItem('letter'+ i, JSON.stringify(textObject));
};
reader.readAsText(file, 'ISO-8859-1');
}

Is it possible to load a specific file type using Javascript?

I have a function that is loading a user selected file using the Javascript File API, but I want to limit the type of file that can be loaded. Is this possible and how do I go about doing it? So for example, I only want the user to be able to load a DAT file. Here's my function loading the file.
function readFile(file){
var reader = new FileReader();
var holder;
var holderArray = [];
var fileArray = [];
reader.readAsText(file, "UTF-8");
reader.onload = function(){
file = reader.result;
file = file.split(/\s+/g);
formatFile(holderArray, 3, holder, file, fileArray);
for(var i = 0; i < 2; i++){
formatFile(holderArray, 1, holder, file, fileArray);
}
for(var i = 0; i < 2; i++){
formatFile(holderArray, 2, holder, file, fileArray);
}
var meh = file.length / fileArray.length;
for(var i = 0; i < meh; i++){
formatFile(holderArray, 5, holder, file, fileArray);
}
fileArray.pop();
plume = new Plume(fileArray[0], fileArray[4], fileArray[3]);
$("#eventDate").val(plume.dateTime);
$("#eventLat").val(plume.startLat);
$("#eventLon").val(plume.startLong);
$("#eventDictionary").val(plume.dict);
$("#eventSymbol").val(plume.symbol);
fileArray = fileArray.splice(5);
plume.graphic = fileArray;
}
}
$("#load").on("click", function(){
$("#eventNameInput").val("");
var selectedFile = $("#selectedFile");
selectedFile = selectedFile[0].files[0];
if(selectedFile){
readFile(selectedFile);
$("#fileDetails").show();
}
})
Sure. You can declare MIME type in "accept" attribute For example this input will upload images :
<input type="file" name="img" accept="image/*">
for .dat you can do this (.dat is unknown MIME type):
<input type="file" name="img" accept=".dat">

JS $.get method file with path

I want to load a *.csv file from a path which the user can choose.
The path I get: C:\\Users\\...
But the $.get method can't read this path. What does the path have to look like?
$.get(pathAndFile, function (data) {...
If you wanted to read CSV data in JavaScript from a computer you would need to instruct the user to select the file (there is no way around this, with the possible exception of a virus). However once a user selected a file you can read and parse CSV data with a small amount of JavaScript like this (demo)
With this HTML:
<input type="file" id="file" name="file" />
<table id="rows"></table>
And this JavaScript:
var output = $('#rows');
$('#file').on('change', function(evt) {
var files = evt.target.files;
for (var i = 0, f; f = files[i]; i++) {
// Only process text files.
if (!f.type.match('text/.*')) {
alert('Unsupported filetype:'+f.type);
continue;
}
var reader = new FileReader();
reader.onloadend = function(evt) {
var rows, row, cols, col, html;
if (evt.target.readyState == FileReader.DONE) {
output.empty();
rows = evt.target.result.match(/[^\r\n]+/g);
for(row = 0; row < rows.length; row++) {
cols = rows[row].split(',');
html = '<tr>';
for(col = 0; col < cols.length; col++) {
html += '<td>'+cols[col]+'</td>';
}
html += '</tr>';
output.append(html);
}
}
};
// Read in the text file
reader.readAsBinaryString(f);
}
});
You can generate an HTML table from the contents of a CSV file (this is based on this excellent site)
function getFile(fileToRead) {
var reader = new FileReader();
reader.readAsText(fileToRead);
// Handle errors load
reader.onload = loadHandler;
reader.onerror = errorHandler;
}
function loadHandler(event) {
var csv = event.target.result;
createChart(csv);
}

Variable isn't increementing on file reader

I'm trying to do thumbnails for the images uploaded. I want to create diferents classes for the thumbs, for this, I'm trying to use de i of the loop. But this assume just the final value. Why? Thanks
for (var i = 0; i < inp.files.length; i++) {
//create the thumbnails
var reader = new FileReader();
reader.onload = function (e) {
$('.thumbs').append('<div class="thumb_item" id="c'+ i +'"></div>');
$('<img />').attr({'src': e.target.result}).addClass('img_thumb').appendTo('.thumb_item:last');
};
reader.readAsDataURL(this.files[i]);
}
Why can't you apply the same technique pointed out in the comment?
reader.onload = (function(index)
{
return function (e)
{
$('.thumbs').append('<div class="thumb_item" id="c'+ index +'"></div>');
$('<img />').attr({'src': e.target.result}).addClass('img_thumb').appendTo('.thumb_item:last');
};
})(i);
Thanks for all, I solved this way:
for (var i = 0; i < inp.files.length; i++) {
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function (theFile) {
var count = i;
return function (e) {
$('.thumbs').append('<div class="thumb_item" id="c'+ count +'"></div>');
$('<img />').attr({'src': e.target.result}).addClass('img_thumb').appendTo('.thumb_item:last');
};
})(i);
reader.readAsDataURL(this.files[i]);
}

Categories

Resources