Пятничные сниппеты. JavaScript, продолжение стилизации файл-инпута

8 августа 2008, 11:33 Евгений Белодед JavaScript рейтинг +45-

сниппетыСегодняшние сниппеты — продолжение урока о стилизации файл-инпутов. Мы упростим разметку и добавим возможность динамически создавать дополнительные файл-инпуты.

А в качестве сниппетов будут функции, которые помогут это сделать.

В прошлой реализации стильного файл-инпута нам неободимо было создать оболочку (wrapper) для нашего инпута. Давайте сделаем так, чтобы в разметке не было ничего, кроме самого инпута. А чтобы как-то его идентифицировать, пропишем у него класс «customFileInput».
То есть в разметке останется только
<input type="file" id="File1" class="customFileInput" />

Что мы должны сделать — это найти инпут по классу и завернуть его в обертку, и уже туда добавлять необходимые элементы.
Для того, чтобы найти инпут используем функцию getElementsByClassName(<название класса>):

 function getElementsByClassName(searchClass) {
var classElements = new Array();
var els = document.getElementsByTagName('*');
var elsLen = els.length;
var pattern = new RegExp("(^|s)"+searchClass+"(s|$)");
for (i = 0, j = 0; i < elsLen; i++) {
if ( pattern.test(els[i].className) ) {
classElements[j] = els[i];
j++;
}
}
return classElements;
};


Завернем все инпуты во враппер:

 function WrapEverything()
{
inputs = getElementsByClassName('customFileInput');
for (var i = 0 ; i < inputs.length; i++)
wrap(inputs[i]);

};


Сама функция wrap:

 function wrap(element)
{
wraper = document.createElement('div');
wraper.className = 'wrapper';
fileInput = document.createElement('input');
fileInput.value = '';
fileInput.setAttribute('type','file');
var id = element.getAttribute('id');
wraper.setAttribute('id','wrapper'+id);
fileInput.setAttribute('id',id);
fileInput.className = 'customFile';
fileInput.onchange = function(){ HandleChanges(id) };
fileInput.onmouseover = function() { MakeActive(id) };
fileInput.onmouseout = function() { UnMakeActive(id) };
fileName = document.createElement('div');
fileName.style.display = 'none';
fileName.style.background = 'url(images/icons.png)';
fileName.setAttribute('id','name'+id);
fileName.className = "FileName";
bb = document.createElement('div');
bb.setAttribute('id','bb' + id);
bb.className = 'fakeButton';
bl = document.createElement('div');
bl.setAttribute('id','bl' + id);
bl.className = 'blocker';
wraper.appendChild(bb);
wraper.appendChild(bl);
wraper.appendChild(fileInput);
wraper.appendChild(fileName);
x = element.parentNode;
x.replaceChild(wraper,element);
};


Функция replaceChild заменяет element на wraper, который содержит необходимые нам элементы.

Хочу обратить внимание на то, как привязываются события к элементу fileInput:

fileInput.onmouseout = function() { UnMakeActive(id) };


Если бы мы делали как раньше

fileInput.onmouseout = UnMakeActive(id);

то браузер сообщил бы нам об ошибке.

Это все, что нам надо сделать для того чтобы упростить разметку.

Теперь добавим возможность динамически создавать новые инпуты. Чтобы сделать эту возможность легко адаптируемой под индивидуальные нужды, мы создадим простую кнопку, которая будет вызывать функцию addCustomFileInput(container). container — это блок, в котором будут распологаться все создаваемые инпуты.

Разметка выглядит следующим образом:

 <div id="MyInputs">
<input type="file" class="customFileInput" id="File1" />
</div>
<a href="javascript:addCustomFileInput('MyInputs')">добавить еще</a>


Для того чтобы можно было удалять добавленные инпуты, мы добавляем минусик рядом с самим инпутом. В остальном содержимое функции аналогично функции wrap.

 function addCustomFileInput(container) {
w = document.getElementById(container);
AddInput(w);
};

function AddInput(container) {
wraper = document.createElement('div');
wraper.className = 'wrapper';
fileInput = document.createElement('input');
fileInput.value = '';
fileInput.setAttribute('type', 'file');
var id = 'customFileInput' + inputNumber;
wraper.setAttribute('id', 'wrapper' + id);
fileInput.setAttribute('id', id);
fileInput.className = 'customFile';
fileInput.onchange = function() { HandleChanges(id) };
fileInput.onmouseover = function() { MakeActive(id) };
fileInput.onmouseout = function() { UnMakeActive(id) };
fileName = document.createElement('div');
fileName.style.display = 'none';
fileName.style.background = 'url(images/icons.png)';
fileName.setAttribute('id', 'name' + id);
fileName.className = "FileName";
bb = document.createElement('div');
bb.setAttribute('id', 'bb' + id);
bb.className = 'fakeButton';
bl = document.createElement('div');
bl.setAttribute('id', 'bl' + id);
bl.className = 'blocker';
deleteButton = document.createElement('div');
deleteButton.className = 'minus';
deleteButton.onclick = function() { DeleteCustomInput(id) };
wraper.appendChild(bb);
wraper.appendChild(bl);
wraper.appendChild(fileInput);
wraper.appendChild(fileName);
wraper.appendChild(deleteButton);
container.appendChild(wraper);
inputNumber++;

};


Если вы хотите, чтобы у вас был не минусик, а свой текст, изменить надо всего лишь эту часть:

deleteButton = document.createElement('div');
deleteButton.className = 'minus';


Теперь, чтобы интегрировать такой файл-инпут, вам достаточно добавить скрипт и стили, а у самого инпута прописать класс customFileInput.

Собственно, все это не так важно, как живой пример.

Архив со примером
ZIP архив, 23КБ
 
Рекламное место, которое может стать вашим

Понравилась статья?

Тогда подпишись на обновления через RSS или воспользуйся
другими способами подписки.

Читать в Яндекс.Ленте Добавить в Google Добавить в Netvibes
  •  

Комментарии — 18

RSS
  • Аватарка
    9 августа 2008 в 0:19 ]]>sergy]]>
    занятно, спасибо
  • Аватарка
    9 августа 2008 в 1:45 switch
    Круто, ещё бы плагин для jQuery такой.
  • Аватарка
    10 августа 2008 в 23:15 чя
    В сафари под маком не работает кнопка добавить
  • Аватарка
    11 августа 2008 в 8:55 ]]>drw]]>
    отлично!
  • Аватарка
    12 августа 2008 в 11:20 DeadLy
    как href=[http://vremenno.net/samples/updated-file-input-styling/index.htmlk>живой пример. поправить бы
  • Аватарка
    12 августа 2008 в 14:22 ]]>Жека]]>
    Спасибо, поправил.
  • Аватарка
    3 сентября 2008 в 14:57 PR
    хорошая статья можно было бы еще скрывать кнопку после выбора файла, а вместо нее вставлять пиктограмму удаления (либо менять сменить надпись на кнопке на "удалить"). Так наверное было бы более понятно для пользователя. А то выходит, что он файл добавил, а кнопка остается активной
  • Аватарка
    21 сентября 2008 в 17:00 Denis
    Скрипт создает кучу глобальных переменных: bb, bl, fileInput, fileName, и даже i и j. Вроде все здорово, но такая невнимательность к коду к сильно портит впечатление.
  • Аватарка
    21 сентября 2008 в 17:51 Denis
    fileName.innerHTML = fileTitle;                 // а если добавить файл "{.html" ?
    И несколько регэкпов когда можно обойтись одним. Функу HandleChanges переписал бы так:
            function HandleChanges(id)
            {
                var fileName = document.getElementById(id).value,
                    elFileName = document.getElementById('name' + id),
                    m = fileName.match(/^.*[\/](.*(?:.(.*)))$/),
                    ext = m[2];
    
                if(!elFileName) return;
    
                elFileName.innerHTML = 'xA0';
                elFileName.firstChild.nodeValue = m[1] || '';
                elFileName.title = fileName;
    
                if (ext){
    
                    var pos = ({
                        doc: 1,
                        bmp: 17, jpg: 33, jpeg: 33, png: 49, gif: 65,
                        psd: 81,
                        mp3: 97, wav: 97, ogg: 97,
                        avi: 113, wmv: 113, flv: 113,
                        pdf: 129,
                        exe: 145,
                        txt: 161
                    }[ext.toLowerCase()] || 177) -1;
    
                    elFileName.style.display = 'block';
                    elFileName.style.background = 'url(images/icons.png) no-repeat 0 -' pos 'px';
                };
            };
    
  • Аватарка
    21 сентября 2008 в 17:54 Denis
    имелось ввиду:
    fileName.innerHTML = fileTitle;                 // а если добавить файл "&#123;.html" ?
  • Аватарка
    22 сентября 2008 в 16:09 Nesnosne
    в Сафари 3.1.2 на Маке все работает.
  • Аватарка
    23 октября 2008 в 10:33 ]]>Вячеслав]]>
    Самому не когда делать ) но такую идею бы предложил, путь же до файла становится известен, так как расширение функционала - навесить просмотр этого файла с локали при наведении (как на стандартных в jQuery), то есть имя файла видеть это хорошо, но когда десяток подготовлен - не плохо иметь возможность пробежаться по ним и поглядеть, те ли это фотки.
  • Аватарка
    8 апреля 2009 в 11:27 castertroy
    Здравствуйте, Евгений, тема полугодичной давности, но, со стилизацией никаких проблем - везде все работает -) за исключением собственно самого процесса передачи файла на сервер. Я интегрировал ваши скрипты в свой продукт, создал простую форму для отправки файла на сервер методом ПОСТ, но данные не обрабатываются, т.е. присвоив файл инпуту какой-то name=item, после нажатия кнопки submit и отправки формы на обработку в массиве $_FILES (в котором собственно и должны находиться сведения о передаваемых файлах) нашего item'a нет.
    (п.с. работаю на PHP)

    Что делать ?
  • Аватарка
    8 апреля 2009 в 11:55 castertroy
    Сам задал вопрос - сам и ответил.

    в функции AddInput() и wrap() добавить строку:
    fileInput.setAttribute('name','имя инпута');
  • Аватарка
    9 апреля 2009 в 15:57 ]]>Евгений]]>
    Вот и пообщались)
  • Аватарка
    21 сентября 2009 в 10:53 vit
    господа, а вы в форму отправки это пробовали встроить?
    Если да, то расскажите , плииз, где искать на сервере отправленные файлы. В папке временных файлов на сервере их нет, и в PHP Variables они не отсвечивают никак...
  • Аватарка
    21 сентября 2009 в 11:05 ]]>Evgenij]]>
    Без проблем встраивал в страницу ASP.NET. Но там все иначе.
  • Аватарка
    23 сентября 2009 в 21:38 vit
    Ага, разобрался, это работает только под эксплорером. Под оперой и гугл-хромом файлы на сервер не передаются :(
  • Эл. почта (используется для Граватарки)
  • Домашняя страница
  • Имя в Твиттере
  • Разрешенные теги Текст сообщения (надо бы заполнить это поле)
  • как выглядит какой тег
    жирный текст <b>жирный текст</b>
    курсивный тект <i>курсивный тект</i>
    зачеркнутый текст <s>зачеркнутый текст</s>
    подчеркнутый текст <u>подчеркнутый текст</u>
    ссылка <a href="адрес">ссылка</a>
    function foo() { ... }
    <pre><code>function foo() { ... } </code></pre>