0

I do welcome constructive criticism and suggestions for different methods of completing this task.

I'm trying to write some jQuery that will allow users to preview a file or multiple files within the current window without the DOM being reloaded.

To achieve this, the simplest way I know, to .append() an image element within <div id="gallery">. I found myself struggling to get the file names to be displayed along with the correct picture, the main issue was that the pictures rendered in no particular order (probably whichever file was smallest was rendered first).

Luckily I stumbled across this post, HTML5 FileReader how to return result? and managed to adapt the code so that it rendered the picture instead of the base64 encoding.

$(function(){
		$('#file_input').change(function(e){
    		var files = $(this.files)
    		$(this.files).each(function(i){
        	readFile(files[i], function(e) {
            	var imageSrc = e.target.result
            	$('#output_field').append('<h4>'+files[i].name+'</h4><img class="preview-thumbs" id="gallery-img" src="' + imageSrc + '">');
            })
        });
    });
		function readFile(file, callback){
    	var reader = new FileReader();
    	reader.onload = callback
    	reader.readAsDataURL(file);
		}
});
.preview-thumbs {display: block; padding: 10px 0px; width: 250px;}
.thumb-containers {}
#gallery>.img-container {display: inline-block; border: 3px solid #243d51; padding: 5px; width: 350px; border-radius: 20px; text-align: center;}
h4 {color: red; font-size: 20px; font-weight: bold;}
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<input type="file" id="file_input" class="foo" multiple/>
<div id="output_field" class="foo"></div>

My question here is:

Is there (if any) better way of completing this task?

Cheers in advance, Swift

6
  • 1
    Seems fine to me. Is there anything in particular you don't like about the solution? I could see (super) large images being a problem but I doubt it matters. Commented Jul 17, 2018 at 16:08
  • 1
    Instead of $(this.files).each(...) use files.each(..), this is unnecessary duplication. Commented Jul 17, 2018 at 16:10
  • 1
    And instead of files.each(function(i) { readFile(files[i], ...); });, simply use files.each(function(i, file) { readFile(file, ...); });. Commented Jul 17, 2018 at 16:12
  • @חייםפרידמן many thanks for pointing this out, it is exactly this kind of feedback I am looking for. I am by no means an expert but duplication is never a good thing :) Commented Jul 17, 2018 at 16:15
  • @Halcyon whilst I appreiciate that large files could potentially cause a problem, I have specified a small snippet of CSS which I will post here .preview-thumbs {display: block; padding: 10px 0px; width: 250px;} This means it will automatically scale the images height based on the width parameter. (At least I think that is how it works lol!) Commented Jul 17, 2018 at 16:17

2 Answers 2

1

I recently publish a project that solves the exactly same problems.

I manage the file upload in a separate class that also covers Drag / Drop. Basically, you must return target.result on the "load" event.

const fileReader = new FileReader();
fileReader.addEventListener("load", this.fileReader_load.bind(this, file.name), false);
fileReader.readAsDataURL(file);


fileReader_load(fileName, event) {
    event.target.removeEventListener("load", this.fileReader_load);
    this.onFileLoaded(fileName, event.target.result);
}  

See the full image loader here: https://github.com/PopovMP/image-holder/blob/master/public/js/file-dropper.js

The image preview is easy. Make an image element and set its src to the imageData.

Here is the full source code: https://github.com/PopovMP/image-holder

Sign up to request clarification or add additional context in comments.

3 Comments

Hi there, what is the const for in the first line?
const is introduced in ES6 (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…). It guarantees that the variable is immutable. You may use let or var with the same result. I use const to make my code more "pure". It is very subjective, but if, I have to use let, it means that the code can be improved.
Having a brief read of that page you linked, I can see why one would desire such a type of variable, one that cannot change, at least without going to great lengths.
0
$(function(){
    $('#file_input').change(function(e){
        var files = $(this.files)
        $(files).each(function(i, file){
        readFile(file, function(e) {
            var imageSrc = e.target.result
            $('#output_field').append('<div class=""img-container"> <h4>'+file.name+'</h4><img class="preview-thumbs" id="gallery-img" src="' + imageSrc + '"/></span>');
        })
    });
});
    function readFile(file, callback){
    var reader = new FileReader();
    reader.onload = callback
    reader.readAsDataURL(file);
    }
});

This is the jQuery code amended as per the suggestion in the comments about duplication. If you post that as an answer, I will accept it :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.