Загрузка нескольких файлов с помощью jQuery

Я пытаюсь разрешить загрузку нескольких файлов перед публикацией формы. Я бы хотел, чтобы пользователь когда-либо видел только один элемент загрузки файла, и каждый раз, когда файл выбран, показывал новый <li>, содержащий имя файла и изображение/ссылку для удаления этого конкретного файла из коллекции. Есть плагин jQuery MultiFile, который делает то, что я хочу, но я не могу заставить пользовательский стиль работать так, как я хочу, поэтому я использую свой собственный.

Пока у меня есть код ниже. Он успешно добавляет <li>, скрывает элемент загрузки файла с новым выбранным файлом и добавляет пустой элемент загрузки файла на страницу, чтобы пользователь мог выбрать новый файл. Я изо всех сил пытаюсь правильно управлять удалением элементов, и, хотя это не так сложно, я смотрел на это достаточно долго, и теперь мне кажется, что я делаю все это неправильно. Я надеюсь, что у других может быть какое-то понимание, советы по очистке этого (т.е. сделать его более элегантным) и тому подобное. Код ниже.

HTML:

<div id="product-image-area" class="group" style="border-bottom: none; padding-top: 0"> 
    <ul id="photos" class="nobull">    
     <li id="no-product-images-msg" class="" > 
            <%= Html.Image("no-photos.png") %> 
     </li> 
   </ul>
 </div> 
 <div id="upload-area"> 
    <h4 class="st">Upload an image</h4>
    <p class="note">Allowed file types are .gif, .jpg, .jpeg, and .png</p> 
    <p id="file-input" class="st sb"><input class="photo-upload" id="VenuePhotos_0" name="VenuePhotos[]" type="file" /></p> 
 </div>

Скрипт:

$(function () {
     $('.photo-upload').live('change', function () {
         var fileCount = new Number($(this).parent().children('.photo-upload').length);
         $('#photos').append('<li id="venue_photo_' + (fileCount - 1) + '">' + $(this).val() + '<img title="' + (fileCount - 1) + '" src="/vh/public/images/icon-delete.png" class="delete"  /></li>');
         $(this).parent().append(
             $(this).clone().attr('id', 'VenuePhotos_' + fileCount)
         );
         $(this).hide();
     });
     $('.delete').live('click', function (e) {
         var index = $(e).attr('title');
         $('#file-input').children('.photo-upload').remove('#VenuePhotos_' + index);
         $('#photos').children().remove('#venue_photo_' + index);
     });
});

person nkirkes    schedule 20.11.2010    source источник


Ответы (1)


Ответ заключается в замыкании, одной из самых мощных функций JavaScript. Функции, находящиеся внутри других, могут обращаться к переменным окружающих функций.

Вы можете связать свою функцию удаления при добавлении ввода файла вместо использования .live и динамически генерируемых идентификаторов:

$('.photo-upload').live('change', function () {
     var li = $('<li />').text($(this).val()),
         img = $('<img src="/vh/public/images/icon-delete.png" class="delete" />'),
         input = $(this).clone();

     li.append(img);
     $('#photos').append(li);
     $(this).parent().append(input);
     $(this).hide();

     img.click(function() {
         input.remove();
         li.remove();
     });
 });

В этом примере обработчик click для кнопки удаления обращается к оболочкам jQuery (для двух элементов, которые необходимо удалить), которые были получены в родительской функции.

person PleaseStand    schedule 20.11.2010
comment
Ах, так близко. Итак, проблема в том, что при удалении должен быть удален не новый ввод, а предыдущий. Новый пуст, так что все в порядке. Но когда щелкают изображение удаления, я хочу убедиться, что соответствующий (теперь скрытый) элемент файла удален со страницы, чтобы он не был отправлен вместе с коллекцией. Это было причиной доступа к нему по определенному идентификатору. Я поиграю с этим, поскольку событие щелчка работает с вашим предложением, но если у вас есть другие мысли, основанные на этой добавленной информации, кричите. Спасибо! - person nkirkes; 21.11.2010
comment
Итак, я заработал (в Chrome, не тестировал IE или FF), добавив новую переменную для хранения элемента родительского файла, а затем изменил «input.remove» на «parentInput.remove». Вуаля. Отлично, чувак, спасибо за помощь! - person nkirkes; 21.11.2010
comment
Если я хочу сделать то же самое, что и Мэнниш, выбрав несколько файлов одновременно, как мне сделать так, чтобы они все отображались в окне браузера, каждый с соответствующей кнопкой удаления? - person serengeti12; 02.07.2011