среда, 29 декабря 2010 г.

Очистка input file

Для загрузки файла на сервер, обычно, используют <input type="file">. Это удобный и проверенный способ, но в нём есть одна проблема - очистка этого поля от выбранного файла. Её нужно делать, если загрузка не обязательна. Т.е. у пользователя должна быть возможность отменить загрузку выбранного им файла.

Обычная очистка значения на <input type="file"> никак не повлияет, поэтому придётся прибегнуть к разным хитростям. В большинстве статей на эту тему предлагается следующее решение:

<form id="fMain" method="post" enctype="multipart/form-data" action="myAction.php">
   <div id="dFile">
      <input type="file">
      <input type="button" value="Очистить" onclick="ClearFile('dFile');" />
   </div>
</form>

function ClearFile(idFileContainer)
{
   var container = document.getElemetnById(idFileContainer);
   //Разметка элементов перезаписывается и текущее значение исчезает
   container.innerHTML = container.innerHTML;
}

Такой подход выполняет поставленную задачу. Однако он обладает одной очень неприятной особенностью. Если пользователь очистит файловое поле, а потом опять выберет файл, то этот файл не отправится на сервер (точную причину такого поведения я не знаю). Это очень серьёзная ошибка в логике работы файлового поля, поэтому я предлагаю менее красивый, но правильно работающий способ:

<form id="fMain" method="post" enctype="multipart/form-data" action="myAction.php">
   <input type="file">
   <input type="button" value="Очистить" onclick="ClearFile('fMain');" />
</form>

function ClearFile(idForm)
{
   var form = document.getElementById(idForm);
   //Массив значений всех элементов формы 
   var values = new Array(form.elements.length);

   //Запись значений всех элементов формы 
   for (var i = 0; i < form.elements.length; i++) 
   {
      values[i] = form.elements.item(i).value;
   }
   

   form.reset(); //Сброс значений всех элементов формы 

   //Восстановление значений всех элементов формы, кроме input file 
   for (var i = 0; i < form.elements.length; i++)
   {
      //Здесь сравнивается тип, т.к. используется один input file
      //Если элементов input file больше, то нужно использовать id
      if(form.elements.item(i).type != 'file')
      {
         form.elements.item(i).value = values[i];
      }
   }
}

Приходится сбрасывать все значения в форме, т.к. сброс значения для отдельного элемента не предусмотрен. Способ громоздкий и текст в форме один раз мигает при перезаписи значений. Зато вышеописанная проблема исчезает. Если у кого-то есть идея получше, то пишите о ней в комментариях обязательно.

4 комментария:

  1. А что если удалить этот input из dom и добавить новый инстанс?

    ОтветитьУдалить
  2. Если в форме только инпуты, то, наверное, сработает. У меня в форме была таблица, а уже в ней инпуты. При таком раскладе ничего не получилось.

    ОтветитьУдалить
  3. Неправда!
    Все работает с простым вариантом: ClearFile
    Возможно, зависит от браузера. У меня Firefox 3.6. А ты в каком пробовал?

    Кроме того, вроде достаточно даже этого:
    document.getElementById('t_picture').value = '';
    Может, правда, в опере будут проблемы. Не помню точно, надо проверять.

    ОтветитьУдалить
  4. Пробовал в Mozilla 3.6, Opera 11.0, Chrome 8 и IE 8. Не работает ни в одном. Если бы работало, я бы такой фигнёй не занимался ))).

    ОтветитьУдалить

Мои записи и на Я.ру — levelost!