saving input data to global variables - javascript

I'm having trouble with a simple file input.
I'm trying to get the width, height and dataURL of multiple images and save them to global variables, but all that's saved is "undefined".
When I tried to make a "demo-fiddle" the "onchange"-event doesn't even seem to fire.
can anyone help me out?
Here's the code of the demo-fiddle:
var WIDTH = [];
var HEIGHT = [];
var SRC = [];
$(window).load(function()
{
grabData();
displayImgs();
});
function grabData()
{
$("#fileInput").on("change",function(e)
{
var file = e.target.files;
for(var i = 0; i<file.length; i++)
{
var reader= new fileReader();
var img = new Image();
reader.onload = function(e)
{
SRC = e.target.result;
img.onload = function()
{
WIDTH = this.width;
HEIGHT = this.height;
}
}
reader.readAsDataURL(file);
console.log(WIDTH);
}
console.log(WIDTH);
});
}
function displayImgs()
{
/*display images*/
for(var i = 0; i<SRC.length; i++)
{
$("body").append("<img src="+SRC[i]+" width="+WIDTH[i]+" height="+HEIGHT[i]+">");
}
}

try below code, tested in fiddle and working - http://jsfiddle.net/02468Lr9/
var WIDTH = [];
var HEIGHT = [];
var SRC = [];
$(document).ready(function() {
grabData();
;
});
function grabData() {
$("#fileInput").on("change",function(e) {
var file = e.target.files;
for(var i = 0; i<file.length; i++) {
var reader= new FileReader();
var img = new Image();
reader.onload = function(e) {
SRC.push(e.target.result);
img.onload = function() {
alert(this.width);
WIDTH.push(this.width);
HEIGHT.push(this.height);
displayImgs();
}
img.src = e.target.result;
}
reader.readAsDataURL(file[i]);
}
});
}
function displayImgs()
{
/*display images*/
for(var i = 0; i<SRC.length; i++) {
console.log(WIDTH);
$("body").append("<img src="+SRC[i]+" width="+WIDTH[i]+" height="+HEIGHT[i]+">");
}
}

The log result is undefined because you log it outside the onload function, and for that it runs before the images load and the value is still undefined.

Related

Add style to a javascript variable

I got this code from a website and applied to my code:
window.onload = function () {
var fileUpload = document.getElementById("fileupload");
fileUpload.onchange = function () {
if (typeof (FileReader) != "undefined") {
var dvPreview = document.getElementById("dvpreview");
dvPreview.innerHTML = "";
var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.jpg|.jpeg|.gif|.png)$/;
for (var i = 0; i < fileUpload.files.length; i++) {
var file = fileUpload.files[i];
if (regex.test(file.name.toLowerCase())) {
var reader = new FileReader();
reader.onload = function (e) {
var img = document.createElement("IMG");
img.width="300";
img.height ="300";
img.src = e.target.result;
dvPreview.appendChild(img);
}
reader.readAsDataURL(file);
} else {
alert(file.name + " is not a valid image file.");
dvPreview.innerHTML = "";
return false;
}
}
}
}
};
It works properly, but I want some more style to be added to my code. Specially the padding and the object-fit css properties.
I tried to run:
img.objectFit="cover";
img.style.objectFit="cover";
img.css("object-fit","cover");
and a lot more possibilities that i could search and apply, but any of those worked out.
What is the right way to make this work?
var img = document.createElement('img');
img.width = '300';
img.height = '300';
img.style.padding = '20px';
img.style.objectFit = 'fill';
document.body.appendChild(img);

Why is my function only applying SRC property only to the first uploaded image?

The function successfully creates N image elements with a class of new-avatar-picture, however, it only adds SRC property to the first image. I'm not getting any errors in the console either.
function displayInputImage(input) {
var files = input.files;
for (var i = 0; i < files.length; i++) {
var file = files[i];
var reader = new FileReader();
var x = document.createElement("img");
reader.onload = function(e) {
x.setAttribute("src", e.target.result);
}
reader.readAsDataURL(file);
x.className = "new-avatar-picture";
$('.upload-btn-wrapper').append(x);
}
}
The issue with your logic is due to the fact that onload() of the reader fires after the loop completes, so x will refer to the last element in the set. Hence that single element gets its src set N times.
To fix this you could use a closure:
function displayInputImage(input) {
for (var i = 0; i < input.files.length; i++) {
var $img = $("<img />");
(function($imgElement) {
var reader = new FileReader();
reader.onload = function(e) {
$imgElement.prop("src", e.target.result);
}
reader.readAsDataURL(input.files[i]);
$imgElement.addClass("new-avatar-picture");
$('.upload-btn-wrapper').append($imgElement);
}($img));
}
}
Alternatively you could create the new img elements only after the content of the file is read:
function displayInputImage(input) {
for (var i = 0; i < input.files.length; i++) {
var reader = new FileReader();
reader.onload = function(e) {
$('<img />').addClass('new-avatar-picture').prop('src', e.target.result).appendTo('.upload-btn-wrapper');
}
reader.readAsDataURL(input.files[i]);
}
}
One way to do that is to give each image a new property, I call it temp_src so that the browser will not try to load the images right away.
Then in the .onload event, loop through all images that you have created and give each of them the proper src value, by copying it from its temp_src property.
Something like:
var reader = new FileReader();
function displayInputImage(input) {
var files = input.files;
for (var i = 0; i < files.length; i++) {
var file = files[i];
var x = document.createElement("img");
x.setAttribute("class", "temp_img");
x.setAttribute("temp_src", file);
reader.readAsDataURL(file);
x.className = "new-avatar-picture";
$('.upload-btn-wrapper').append(x);
}
}
reader.onload = function(e) {
var images = document.getElementsByClassName("tmp_img");
images.forEach(function(img) {
img.setAttribute("src", img.temp_src);
});
}

How to use the loop in the file input change event

Hello I have the following code
function fileValidation() {
var fileInput = document.getElementById('filech');
var filePath = fileInput.value;
var allowedExtensions = /(\.jpg|\.jpeg|\.png|\.gif)$/i;
if (!allowedExtensions.exec(filePath)) {
alert('error .jpeg/.jpg/.png/.gif ');
fileInput.value = '';
return false;
} else {
//Image preview
if (fileInput.files && fileInput.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
document.getElementById('imagePreview').innerHTML = '<img src="' + e.target.result + '"/>';
};
reader.readAsDataURL(fileInput.files[0]);
}
}
}
<input id="filech" type="file" name="file_img[]" multiple onchange="return fileValidation()" />
<div id="imagePreview"></div>
To upload photos by
<input id="filech" type="file" name="file_img[]" multiple onchange="return fileValidation()" />
then show
<div id="imagePreview"></div>
I want to show all the pictures and not one
How to use the loop here and thank all
Well as you said you will need a loop, the easiest way would be to use a for loop, like this:
for (var i = 0; i < fileInput.files.length; i++) {
if (fileInput.files && fileInput.files[i]) {
var reader = new FileReader();
reader.onload = function(e) {
document.getElementById('imagePreview').innerHTML += '<img src="' + e.target.result + '"/>';
};
reader.readAsDataURL(fileInput.files[i]);
}
}
Note:
Note that I changed it to document.getElementById('imagePreview').innerHTML +=, so it keep printing all the iterated images, otherwise it will just override the preview with the last image content.
But the best practice is to create an img element on each iteration and append it to the preview div:
for (var i = 0; i < fileInput.files.length; i++) {
if (fileInput.files && fileInput.files[i]) {
var reader = new FileReader();
reader.onload = function(e) {
var img = document.createElement("img");
img.src = e.target.result;
document.getElementById('imagePreview').appendChild(img);
};
reader.readAsDataURL(fileInput.files[i]);
}
}
Demo:
function fileValidation() {
var fileInput = document.getElementById('filech');
var filePath = fileInput.value;
var allowedExtensions = /(\.jpg|\.jpeg|\.png|\.gif)$/i;
if (!allowedExtensions.exec(filePath)) {
alert('error .jpeg/.jpg/.png/.gif ');
fileInput.value = '';
return false;
} else {
//Image preview
for (var i = 0; i < fileInput.files.length; i++) {
if (fileInput.files && fileInput.files[i]) {
var reader = new FileReader();
reader.onload = function(e) {
var img = document.createElement("img");
img.src = e.target.result;
document.getElementById('imagePreview').appendChild(img);
};
reader.readAsDataURL(fileInput.files[i]);
}
}
}
}
<input id="filech" type="file" name="file_img[]" multiple onchange="return fileValidation()" />
<div id="imagePreview"></div>

Grab screenshot of appended blob video

When saving a screenshot of large video files on a canvas, it seems that it cannot get its blob. It is working fine when the video blob has been displayed on the container.
Here's a JSFiddle without timeout (does not work)
Here's a JSFiddle with timeout (works)
$('#txtFileUpload').on('change', function() {
var countFiles = $(this)[0].files.length;
for (var ctr = 0; ctr < countFiles; ctr++) {
var reader = new FileReader();
readerOnLoad(reader, ctr, $(this)[0], this.files[0]);
}
});
var readerOnLoad = function(reader, ctr, fileInput, files) {
reader.onloadend = (function(ctr) {
return function(e, ctr) {
var videoIdClass = 'thumb-video-' + ctr;
var $video = $('<video />', {
'src': e.target.result,
'id': videoIdClass,
'class': videoIdClass,
}).appendTo($('.video-container')).wrap('<div class="thumb-container"></div>');
setVideoCapture($video);
};
})(ctr);
reader.readAsDataURL(fileInput.files[ctr]);
}
var setVideoCapture = function(videoElement) {
var $output;
var $canvas = document.createElement('canvas');
var $img = document.createElement('img');
$output = $('#output');
$video = videoElement.get(0);
$canvas.width = $video.videoWidth * 2;
$canvas.height = $video.videoHeight * 2;
$canvas.getContext('2d').drawImage($video, 0, 0, $canvas.width, $canvas.height);
$img.src = $canvas.toDataURL();
$output.prepend($img);
}
A quick fix would be set a timeout on the setVideoCapture method like this:
This works.
var setVideoCapture = function(videoElement) {
setTimeout(function() {
var $output;
var $canvas = document.createElement('canvas');
var $img = document.createElement('img');
$output = $('#output');
$video = videoElement.get(0);
$canvas.width = $video.videoWidth * 2;
$canvas.height = $video.videoHeight * 2;
$canvas.getContext('2d').drawImage($video, 0, 0, $canvas.width, $canvas.height);
$img.src = $canvas.toDataURL();
$output.prepend($img);
}, 2000, videoElement)
}
Weird that it has to be INSIDE the setVideoCapture method and not when triggering the setVideoCapture method like this:
This does not work.
reader.onloadend = (function(ctr) {
return function(e, ctr) {
var videoIdClass = 'thumb-video-' + ctr;
var $video = $('<video />', {
'src': e.target.result,
'id': videoIdClass,
'class': videoIdClass,
}).appendTo($('.video-container')).wrap('<div class="thumb-container"></div>');
setTimeout(setVideoCapture($video), 3000, $video);
};
})(ctr);
But of course using a setTimeout is not a recommended fix. What should be is that setVideoCapture method should only be triggered when the $video element has already been appened and displayed on the container.
Nevermind, I was able to fix this by:
$video.addEventListener('loadeddata', function() {
// do something here
}, false);

Send default image with ajax

Hi guys how can i convert a image to object in this code for example:
var img = $('<img id="dynamic">');
img.attr('src', 'http://macreationdentreprise.fr/wp-content/uploads/2012/06/ouvrir-un-restaurant.jpeg');
var obj=img.ConvertToObject();
// so i can now use obj.filename; and obj.data;
The reason to do that is if i wan't to upload this image automatically if the input file isn't set:
<input id="picture_zone_upload_input_ID" type="file" name="picture_zone_upload_input" class="picture_zone_upload_input" multiple title="Choose a file to upload"/>
EDIT
function configure_zone_upload() {
$("#picture_zone_upload_input_ID").change(function (event) {
$.each(event.target.files, function (index, file) {
var reader = new FileReader();
reader.onload = function (event) {
object = {};
object.filename = file.name;
object.data = event.target.result;
//alert("index: " + index);
upload_img_count++;
configure_upload_img(object.data, upload_img_count);
files.push(object);
};
reader.readAsDataURL(file);
});
var files = event.target.files;
for (var x = 0; x < files.length; x++) {
data.append(x, files[x]);
}
//alert(files.length);
AJAX_upload_Profile(data, upload_img_count);
});
}
If there isn't a input file how can i set the my default image to send it with ajax ??
EDIT2
If event.target.files; is null how can i set file from new image:
var files = event.target.files;
for (var x = 0; x < files.length; x++) {
data.append(x, files[x]);
}
//alert(files.length);
AJAX_upload_Profile(data, upload_img_count);
I guess you can do this:
object.filename = file.name || defaultImg;
where defaultImg is a variable which contains a default img with src.
somthing like:
reader.onload = function (event) {
object = {};
object.defaultImg = $('<img>',{"src" : "defaultImg/path/img.jpeg"}); // <--declare here
object.filename = file.name
object.data = event.target.result || object.defaultImg; //<---use it here;
//alert("index: " + index);
upload_img_count++;
configure_upload_img(object.data, upload_img_count);
files.push(object);
};

Categories