1

I had able to select multiple image file and preview in a div. There are a button on below of each of the image.

Input File HTML

<input type="file" class="span3" id="file[]" name="file[]" multiple />

When I selected TWO image, the number of file will become TWO. But when I using jquery to remove the image div, the number of file is still remain TWO. It show that jquery just remove the div but now remove the number of file.

This is my HTML

IMAGE 1
<div id="image_div0" class="image_div">
<div style="height: 190px;">
<img class="thumb" src="blob:http%3A//localhost%3A8888/902e3e76-d381-4b0a-9c45-f7be3b2eb7c9"/>
</div>
<div>
<button id="btnRemove_0" class="btn btn-primary" type="button">Remove</button>
</div>
</div>

IMAGE 2
<div id="image_div1" class="image_div">
<div style="height: 190px;">
<img class="thumb" src="blob:http%3A//localhost%3A8888/ce22463e-156e-4444-b193-7c1505ee1d6f"/>
</div>
<div>
<button id="btnRemove_1" class="btn btn-primary" type="button">Remove</button>
</div>
</div>

How to dynamically remove clicked image from image file..?

Example I selected three image and preview it. When I click on REMOVE button at first image, it only remove the first image and the number of "3" show in input file will change to "2".

Current I apply opacity for the image when REMOVE button is click.

$('.image_div').find('button').live('click', function(){
            var selected_image_id = $(this).parents().parents().html();
            $(this).parent('div').parent('div').find('div').css({
                'opacity' : 0.3,
            });

            $(this).css('cursor','default')
        });
user3663143
  • 63
  • 2
  • 9

3 Answers3

0

you can also use as

$("#btnRemove_0").click(function{
   $("#image_div0").css('opacity','0.3');
});

this is just an example you can also make dynamically with the unique values of div and button

EDIT

you can also use this via one function only

function hide(id){
 $("#btnRemove_"+id).click(function{
       $("#image_div"+id).css('opacity','0.3');
    });
}
SagarPPanchal
  • 9,839
  • 6
  • 34
  • 62
0

Newer versions of the browsers have the FormData object with which you can maintain a list of files and submit them with an ajax call.

In one of my applications, I build a list of files that are either selected with an <input> box, or drag & dropped in a dropzone:

var filesToUpload = [];

function addFilesToList(files) {
    $.each(files, function() {
        filesToUpload.push(this);
        var $li = $("<li/>").text(this.name);
        $li.appendTo($("#import-dialog .file-list"));
    });
}

The change handler of the <input type="file"> looks like this:

$("#files").on("change", function(e) {
    e.preventDefault();
    e.stopPropagation();
    addFilesToList($("#files").prop("files"));
    $("#import-dialog form")[0].reset();
});

Note that I immediatly reset the form, that clears the <input type="file"> box.

Then I have a handler on the submit event of the form:

$("#import-dialog form").on("submit", function(e) {
    e.preventDefault();
    e.stopPropagation();
    var fd = new FormData();
    fd.append("ajax", "true");
    $.each(filesToUpload, function() {
        fd.append("files[]", this);
    });
    $.ajax({
        url: "import.php",
        type: "POST",
        data: fd,
        processData: false,  // tell jQuery not to process the data
        contentType: false   // tell jQuery not to set contentType
    }).done(function() {
        window.location.reload();
    }).fail(function (jqXHR, textStatus) {
        alert("Error: " + textStatus);
    });
});

I also have a button to clear the list:

$("#im-clear").on("click", function(e) {
    e.preventDefault();
    e.stopPropagation();
    filesToUpload = [];
    $("#import-dialog form")[0].reset();
    $("#import-dialog .file-list").empty();     
});

But in your case, You would just remove one element from the array:

$('.image_div button').live('click', function(){
    var $div = $(this).closest(".image_div"),
        parts = /^image_div([0-9]+)$/.exec($div.attr("id")),
        index = parseInt(parts[1]);
    $div.remove();
    filesToUpload.splice(index,1);
});

UPDATE:

I forgot: You would also need to renumber the following divs:

$('.image_div button').live('click', function(){
    var $div = $(this).closest(".image_div"),
        parts = /^image_div([0-9]+)$/.exec($div.attr("id")),
        index = parseInt(parts[1]);
    $div.remove();
    filesToUpload.splice(index,1);
    $('.image_div').each(function() {
        var parts2 = /^image_div([0-9]+)$/.exec($(this).attr("id")),
            index2 = parseInt(parts2[1]);
        if (index2 > index) {
            $(this).attr("id","image_div" + (index2-1));
        }
    });
});

UPDATE 2:

Oh! I see that there is also an index in the button's ID. I would remove the ID: you can always access the button with the selector "#image_divN button".

Maurice Perry
  • 32,610
  • 9
  • 70
  • 97
0

Jsfiddle: http://jsfiddle.net/techsin/vs7PT/5/

What's happening:...lot

Things to notice..

  1. If you load files and save the reference to them then the files remain. Let's say you load 2 images, then again click button and load 3 more. Then if you haven't gotten the reference to previous 2 files then they are gone. So if you have reference you have files.

  2. You need to make a reader to actually read files. And reader is async, which leads to putting callback handle on onload event of reader. Which fires when it's done. You can not use the same reader for all files loaded especially for multiple files as it actually gets busy reading them and will throw an error. Also, our luck, that onload event data doesn't contain any reference to what file it just read. So to keep track you do the next thing..

  3. The track is kept by using closure which is that even though when onload event fires the variables holding information about file have long gone and replaced. But since we used them in inner function they are kept alive in scope of that inner function. Then we just keep track of files along their data and index number. Index number is tracked via buttons' data attribute

  4. So when item is removed it's index is taken from the button's data and corresponding file is removed by setting array position holding that value to null. This creates array that has only objects which have files that are in the gallery and their data, and empty holes.

  5. so when you want array only consisted of files currently in the gallery then you use the get clean function that returns array full of files out main array by checking if array is null or not and weeding them out.

Code Below:

var files=[];
//once refered,  files are not lost after rechossing files..
$('#file').change(function(v){
     $.each(v.target.files,function(n,i){
        var reader = new FileReader(); //need to create new ones...they get busy..
        reader.readAsDataURL(i);
        reader.onload = (function(i) {
            return function(x) {
                files.push({file:i,data:x.target.result});
                updateList(files.length-1);
            }
        })(i);
     });
});

var thumb= $('.thumb').clone().show(), gallery= $('.gallery');

function updateList(n) {
    var e = thumb.clone();
    e.find('img').attr('src',files[n].data);
    e.find('button').click(removeFromList).data('n',n);
    gallery.append(e);

    function removeFromList() {
        files[$(this).data('n')] = null;
        $(this).parent().remove();
    }    
}

//Get clean Array full of files.: no removed files..nullss...

function getClean() { 
    var arr=[];
    $.each(files,function(n,i) { 
        if ( i !== null ) arr.push(i.file);
    });
    return arr;
}
$('#clean').click(function(){console.log(getClean());});

Click Cleanlist button and check console.

Muhammad Umer
  • 17,263
  • 19
  • 97
  • 168
  • I had go through your solution, but is the number of input file will clear by each time when you select again new image.That not my need. I just want to reduce the number of file input when I click on one remove button on the image. – user3663143 May 22 '14 at 06:52
  • No it doesn't...check the files array it has all the files...and if you want only the files at any point the just run the getClean function or click the button at bottom. – Muhammad Umer May 22 '14 at 06:53
  • The number of files in the file input does clear..but i made an array that holds all the files. Only thin missing to check for multiple files. So if i select file A, B, C. Then they are saved. But if rechoose files C,D,E...now `files` array has A, B, C, C, D, E. However, i hope doesn't choses the same file over and over. – Muhammad Umer May 22 '14 at 06:56
  • Thanks for your solution. Can I do another way that when I click on REMOVE button, it will add OPACITY css for the image. And when I press submit, it will run PHP. Can PHP able to detect which image has OPACITY css in looping..? – user3663143 May 22 '14 at 07:05
  • Php only runs at server so when you click submit button then you would have to send everything to server and yes it's possible that on server you check which elements have opacity then trash them.. But isn't is inefficent to send files to server only to trash them. why no weed out file at client side that you're not gonna need that way your server will be able to save its resources. – Muhammad Umer May 22 '14 at 07:08
  • Yes..I think this too..but I had my solution to preview the image..and I dont know how to applied your solution into my current code.. Can I put my code in jsFiddle..then you explain to me how to implement your code to my code..? – user3663143 May 22 '14 at 07:11
  • i will try but tomorrow ill answer if thats ok – Muhammad Umer May 22 '14 at 07:13
  • No problem..Thanks..will send you the link here – user3663143 May 22 '14 at 07:15
  • I just found that there is a jquery plugin that makes everything nice and clean..http://blueimp.github.io/jQuery-File-Upload/index.html Even has php section that help further along – Muhammad Umer May 22 '14 at 07:17
  • Did you know the way for php to filter out which element has CSS or not..? Any example you have it..? – user3663143 May 22 '14 at 07:28
  • No, I do not know php much. Again shouldn't you be only sending stuff that's needed. take a step back and think about it. – Muhammad Umer May 22 '14 at 15:42