I want to preview multiple images as they would appear on the post when submitted. This code below works fine for one file. It displays exactly as I would hope it would.
$('input[name="filesToUpload[]"]').on('change', function(event) {
$('body').css('overflow','hidden');
$('body').css('margin-right','1.7rem');
$('.navbar_more').css('margin-right','1.7rem');
$('.post_preview').removeClass('cssdisplaynone');
var checkfiles = $(this)[0].files;
if(checkfiles) {
var filesAmount = checkfiles.length;
for(var i = 0; i < filesAmount; i++) {
var previewHTML = '';
var file = $(this)[0].files[i];
var fileType = file.type;
if(fileType.search('image') >= 0) {
var img = new Image();
var imgsrc = window.URL.createObjectURL(file);
img.src = imgsrc;
img.onload = function(event) {
previewHTML += '<div class="post_file ' + ((i == 1) ? 'post_file_show' : '') + '" style="padding-bottom: ' + ((this.height / this.width) * 100) + '%">';
previewHTML += '<img src="' + imgsrc + '" width="' + this.width + '" height="' + this.height + '" />';
if(filesAmount > 1) {
previewHTML += '<span class="post_count">' + i + '/' + filesAmount + '</span>';
}
previewHTML += '</div>';
$('.post_preview').find('.post_content').append(previewHTML);
}
}
}
}
});
Single File Output:
<div class="post_file post_file_show" style="padding-bottom: 75%"><img src="BLOB URL 1" width="480" height="360"></div>
However, when I try to preview two or more images, for instance, the output isn't what I expect it to be.
Two File Output:
<div class="post_file " style="padding-bottom: 100%"><img src="BLOB URL 2" width="1024" height="1024"><span class="post_count">2/2</span></div>
<div class="post_file " style="padding-bottom: 100%"><img src="BLOB URL 2" width="1024" height="1024"><span class="post_count">2/2</span></div>
<div class="post_file " style="padding-bottom: 75%"><img src="BLOB URL 2" width="480" height="360"><span class="post_count">2/2</span></div>
Three File Output:
<div class="post_file " style="padding-bottom: 100%"><img src="BLOB URL 3" width="1024" height="1024"><span class="post_count">3/3</span></div>
<div class="post_file " style="padding-bottom: 100%"><img src="BLOB URL 3" width="1024" height="1024"><span class="post_count">3/3</span></div>
<div class="post_file " style="padding-bottom: 153.45454545454544%"><img src="BLOB URL 3" width="550" height="844"><span class="post_count">3/3</span></div>
<div class="post_file " style="padding-bottom: 100%"><img src="BLOB URL 3" width="1024" height="1024"><span class="post_count">3/3</span></div>
<div class="post_file " style="padding-bottom: 153.45454545454544%"><img src="BLOB URL 3" width="550" height="844"><span class="post_count">3/3</span></div>
<div class="post_file " style="padding-bottom: 75%"><img src="BLOB URL 3" width="480" height="360"><span class="post_count">3/3</span></div>
This isn't my strong field. I am perfectly content with PHP, but for a good user experience, I need to use javascript to preview images before upload so users could describe the post, rather than have them add it afterwards, which is jarring.
EDIT
Here is updated code that actually resolves almost all the issues. The issues of repeating is gone. The issue of incorrect URL is gone. I got this from How to pass parameters into image load event?.
However, this does pose the problem that this is done async, so the files append out of order... I'm trying to find solution to that right now that isn't "evil" as many posts keep saying...
if($(this)[0].files[i].type.search('image') >= 0) {
var img = new Image();
img.dataurl = objectUrl;
img.j = i;
img.onload = function(event) {
previewHTML += '<div class="post_file ' + ((this.j == 0) ? 'post_file_show' : '') + '" style="padding-bottom: ' + ((this.height / this.width) * 100) + '%">';
previewHTML += '<img src="' + this.dataurl + '" width="' + this.width + '" height="' + this.height + '" />';
if(fileList.length > 1) {
previewHTML += '<span class="post_count">' + (this.j + 1) + '/' + fileList.length + '</span>';
}
previewHTML += '</div>';
$('.post_preview').find('.post_content').append(previewHTML);
previewHTML = '';
}
img.src = objectUrl;
}