1

I am trying to upload multiple images with File API. I want to show picture thumbnails and their names as title tag. The problem is I am not getting correct picture name as title tag. All pictures are showing same name. Here is my Original code...

jQuery, CSS and HTML

var output = document.getElementById("result");

$(document).ready(function ()
{
    //Check File API support
    if (window.File && window.FileList && window.FileReader)
    {
        $('#files').on("change", function (event)
        {
            var files = event.target.files; //FileList object

            var iCount = files.length;

            for (var i = 0, f; i < iCount; i++)
            {
                var file = files[i];
                //Only pics
                if (file.type.match('image.*'))
                {
                    var picReader = new FileReader();

                    picReader.addEventListener("load", function (event)
                    {
                        var picFile = event.target;
                    
                        var div = document.createElement("div");

                        div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
                        "title='" + file['name'] + "'/>";
                        output.insertBefore(div, null);
                        
                    });

                    //Read the image
                    $('#clear, #result').show();
                    picReader.readAsDataURL(file);
                }
                else
                {
                    alert("You can only upload image file.");
                    $(this).val("");
                }
            }
        });
    }
    else
    {
        console.log("Your browser does not support File API");
    }


    $("#upload").on('submit',(function()
    {
        var data = new FormData(this);

        var iUploaded = 0;
        
        setTimeout(function()
        {
            var iCount = document.getElementById('files').files.length;
            
            for (var i = 0; i < iCount ; i++)
            {
                data.append("Index", i);
                $.ajax(
                {
                    url: "upload.php",
                    type: "POST",
                    data: data,
                    contentType: false,
                    cache: false,
                    processData:false,
                    async: false,
                    success: function(response)
                    {
                        var sRes = response.split("|-|");
                        
                        if(sRes['0'] == 'success')
                        {
                            iUploaded = iUploaded + 1;
                            $("#message").html(iUploaded + " of " + sRes['1'] + " Pictures Uploaded")
                        }
                    }
                });
            }
        }, 500);
    }));
    

    $("#files").change(function()
    {
        $("#submit").trigger("click");
    });


    $('#clear').on("click", function ()
    {
        $('.thumbnail').parent().remove();
        $('#result').hide();
        $('#files').val("");
        $(this).hide();
    });
});
body{
            font-family: 'Segoe UI';
            font-size: 12pt;
        }

        header h1{
            font-size:12pt;
            color: #fff;
            background-color: #1BA1E2;
            padding: 20px;

        }
        article
        {
            width: 80%;
            margin:auto;
            margin-top:10px;
        }


        .thumbnail{

            height: 100px;
            margin: 10px;
            float: left;
        }
        #clear{
            display:none;
        }
        #result {
            border: 4px dotted #cccccc;
            display: none;
            float: left;
            margin:0 auto;
        }
        #result > div {
            float: left;
        }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<article>
    <form id="upload" onsubmit="return false">
        <label for="files">Select multiple files: </label><br /><br />
        <input id="files" name="files[]" type="file" multiple/><br /><br />
        <input type="Submit" value="submit" id="submit"></input>
        <button type="button" id="clear">Clear</button><br /><br />
    </form>

    <div id="message"></div>
    <output id="result" />
</article>

I tried to figure it out and come to know that the value of var i changes automatically inside the

addEventListener("load", function (event){ // value of “var i” is not the same here as the value coming from outside this function. });

I have no idea why value is changing inside the “load” function.

I Googled to see how others are doing same and ended up with this working example on SitePoint http://www.sitepoint.com/html5-file-drag-and-drop/ In this example I see these 2 major differences which I do not understand (my little knowledge in programming).

1. Syntax of for loop he is using in example

for (var i = 0, f; f = files[i]; i++) {

See he is assigning value to var f instead of applying stop condition. Now my question is how the loop is working without stop condition is specified?

2. Separate function for reading files

He has made a separate function ParseFile(); to read files. When I tried to read files without a separate function for file reading it is not working (as shown in my original code). But when I put that code in a separate function showThumbnail() for reading files and call that function inside loop it is working as it should be (as showing in below snippet). Why is this so?

Anyone here explain these two things to me. Thanks in advance.

I followed the example and rearranged my code which is working as it should be. (Code is in below snippet.)

var output = document.getElementById("result");

$(document).ready(function ()
{
    //Check File API support
    if (window.File && window.FileList && window.FileReader)
    {
        $('#files').on("change", function (event)
        {
            var files = event.target.files; //FileList object

            var iCount = files.length;

            for (var i = 0, f; f = files[i]; i++)
            {
                showThumbnail(f);
            }
        });
    }
    else
    {
        console.log("Your browser does not support File API");
    }


    $("#upload").on('submit',(function()
    {
        var data = new FormData(this);

        var iUploaded = 0;
        
        setTimeout(function()
        {
            var iCount = document.getElementById('files').files.length;
            
            for (var i = 0; i < iCount ; i++)
            {
                data.append("Index", i);
                $.ajax(
                {
                    url: "upload.php",
                    type: "POST",
                    data: data,
                    contentType: false,
                    cache: false,
                    processData:false,
                    async: false,
                    success: function(response)
                    {
                        var sRes = response.split("|-|");
                        
                        if(sRes['0'] == 'success')
                        {
                            iUploaded = iUploaded + 1;
                            $("#message").html(iUploaded + " of " + sRes['1'] + " Pictures Uploaded")
                        }
                    }
                });
            }
        }, 500);
    }));
    

    $("#files").change(function()
    {
        $("#submit").trigger("click");
    });


    $('#clear').on("click", function ()
    {
        $('.thumbnail').parent().remove();
        $('#result').hide();
        $('#files').val("");
        $(this).hide();
    });
});


function showThumbnail(file)
{
    //Only pics
    if (file.type.match('image.*'))
    {
        var picReader = new FileReader();

        picReader.addEventListener("load", function (event)
        {
            var picFile = event.target;
        
            var div = document.createElement("div");

            div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
            "title='" + file['name'] + "'/>";
            output.insertBefore(div, null);
            
        });

        //Read the image
        $('#clear, #result').show();
        picReader.readAsDataURL(file);
    }
    else
    {
        alert("You can only upload image file.");
        $(this).val("");
    }

}
 body{
            font-family: 'Segoe UI';
            font-size: 12pt;
        }

        header h1{
            font-size:12pt;
            color: #fff;
            background-color: #1BA1E2;
            padding: 20px;

        }
        article
        {
            width: 80%;
            margin:auto;
            margin-top:10px;
        }


        .thumbnail{

            height: 100px;
            margin: 10px;
            float: left;
        }
        #clear{
            display:none;
        }
        #result {
            border: 4px dotted #cccccc;
            display: none;
            float: left;
            margin:0 auto;
        }
        #result > div {
            float: left;
        }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<article>
    <form id="upload" onsubmit="return false">
        <label for="files">Select multiple files: </label><br /><br />
        <input id="files" name="files[]" type="file" multiple/><br /><br />
        <input type="Submit" value="submit" id="submit"></input>
        <button type="button" id="clear">Clear</button><br /><br />
    </form>

    <div id="message"></div>
    <output id="result" />
</article>

3
  • put your question first as it is not clear what you want amongst all that guff Commented Feb 20, 2015 at 12:38
  • @AstraBear : Sorry I am not good at English... and this is my question on stackoverflow. Let me edit it and I will try to reformat my question to make it more understandable. Commented Feb 20, 2015 at 12:43
  • @Astra Bear : Dear I have improved the formatting to make it as understandable as I can. Please have a look and tell me if it can help. Commented Feb 20, 2015 at 13:26

2 Answers 2

1

Haven't seen the edits to question before posting + misread it
So for your questions :

  • 1 This for loop is waiting for file[i] to be undefined. :
    for( var i=0, f; f=files[i]; i++).
    If files[x]is undefined, then the loop stops (even if files[x+1] is defined)

  • 2 It is because in your first snippet, your file variable is in the global scope and gets replaced during the iteration. In the second, however, it is linked to the showThumbnail function scope, and then passed in the EventListener.
    To avoid calling an external function, you will need to call a file binded function :

From mdn : reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);

So for you,

picReader.addEventListener("load", (function(aImg) { return function (event)
                    {
                        var picFile = event.target;
                        console.log(picFile);
                        var div = document.createElement("div");

                        div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
                        "title='" + aImg['name'] + "'/>";
                        output.insertBefore(div, null);

                    }; })(file));

Example below :

var output = document.getElementById("result");

$(document).ready(function ()
{
    //Check File API support
    if (window.File && window.FileList && window.FileReader)
    {
        $('#files').on("change", function (event)
        {
            var files = event.target.files; //FileList object

            var iCount = files.length;

            for (var i = 0, f; i < iCount; i++)
            {
                var file = files[i];
                //Only pics
                if (file.type.match('image.*'))
                {
                    var picReader = new FileReader();

                    picReader.addEventListener("load", (function(aImg) { return function (event)
                    {
                        var picFile = event.target;
                        console.log(picFile);
                        var div = document.createElement("div");

                        div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
                        "title='" + aImg['name'] + "'/>";
                        output.insertBefore(div, null);
                        
                    }; })(file));

                    //Read the image
                    $('#clear, #result').show();
                    picReader.readAsDataURL(file);
                }
                else
                {
                    alert("You can only upload image file.");
                    $(this).val("");
                }
            }
        });
    }
    else
    {
        console.log("Your browser does not support File API");
    }


    $("#upload").on('submit',(function()
    {
        var data = new FormData(this);

        var iUploaded = 0;
        
        setTimeout(function()
        {
            var iCount = document.getElementById('files').files.length;
            
            for (var i = 0; i < iCount ; i++)
            {
                data.append("Index", i);
                $.ajax(
                {
                    url: "upload.php",
                    type: "POST",
                    data: data,
                    contentType: false,
                    cache: false,
                    processData:false,
                    async: false,
                    success: function(response)
                    {
                        var sRes = response.split("|-|");
                        
                        if(sRes['0'] == 'success')
                        {
                            iUploaded = iUploaded + 1;
                            $("#message").html(iUploaded + " of " + sRes['1'] + " Pictures Uploaded")
                        }
                    }
                });
            }
        }, 500);
    }));
    

    $("#files").change(function()
    {
        $("#submit").trigger("click");
    });


    $('#clear').on("click", function ()
    {
        $('.thumbnail').parent().remove();
        $('#result').hide();
        $('#files').val("");
        $(this).hide();
    });
});
body{
            font-family: 'Segoe UI';
            font-size: 12pt;
        }

        header h1{
            font-size:12pt;
            color: #fff;
            background-color: #1BA1E2;
            padding: 20px;

        }
        article
        {
            width: 80%;
            margin:auto;
            margin-top:10px;
        }


        .thumbnail{

            height: 100px;
            margin: 10px;
            float: left;
        }
        #clear{
            display:none;
        }
        #result {
            border: 4px dotted #cccccc;
            display: none;
            float: left;
            margin:0 auto;
        }
        #result > div {
            float: left;
        }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<article>
    <form id="upload" onsubmit="return false">
        <label for="files">Select multiple files: </label><br /><br />
        <input id="files" name="files[]" type="file" multiple/><br /><br />
        <input type="Submit" value="submit" id="submit"></input>
        <button type="button" id="clear">Clear</button><br /><br />
    </form>

    <div id="message"></div>
    <output id="result" />
</article>

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

Comments

0

Answer to question 1:

The for loop increments i with 1 on every iteration. When i is not an index of files the returned value will be undefined, which breaks the loop.

Answer to question 2:

I created a fiddle which shows how to put the code of showThumbnail in the for loop. It aslo explains the question.

The reason is behind the addEventListener function, which will run asynchronously with the for loop after load is triggered and has different scope. The function outside the loop is however permanent and the listener can use variables declared in that scope (the argument file).

What you can do however is to bind the listener function to the file object. The scope (this) of the function will be the file. See the fiddle for this to work.

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.