620

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

8 августа 2008, 11:33JavaScriptрейтинг +27-

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

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







В прошлой реализации стильного файл-инпута нам неободимо было создать оболочку (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КБ

Memori.rumister-wong.combobrdobr.rumoemesto.rudel.icio.uszakladki.yandex.rugoogle.com/bookmarks/

RSS Комментарии

занятно, спасибо
sergy, 9 августа 2008, 0:19
Круто, ещё бы плагин для jQuery такой.
switch, 9 августа 2008, 1:45
В сафари под маком не работает кнопка добавить
чя, 10 августа 2008, 23:15
отлично!
drw, 11 августа 2008, 8:55
как href=[http://vremenno.net/samples/updated-file-input-styling/index.htmlk>живой пример. поправить бы
DeadLy, 12 августа 2008, 11:20
Спасибо, поправил.
Жека, 12 августа 2008, 14:22
хорошая статья можно было бы еще скрывать кнопку после выбора файла, а вместо нее вставлять пиктограмму удаления (либо менять сменить надпись на кнопке на "удалить"). Так наверное было бы более понятно для пользователя. А то выходит, что он файл добавил, а кнопка остается активной
PR, 3 сентября 2008, 14:57
Скрипт создает кучу глобальных переменных: bb, bl, fileInput, fileName, и даже i и j. Вроде все здорово, но такая невнимательность к коду к сильно портит впечатление.
Denis, 21 сентября 2008, 17:00
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';
            };
        };
Denis, 21 сентября 2008, 17:51
имелось ввиду:
fileName.innerHTML = fileTitle;                 // а если добавить файл "&#123;.html" ?
Denis, 21 сентября 2008, 17:54
в Сафари 3.1.2 на Маке все работает.
Nesnosne, 22 сентября 2008, 16:09
Самому не когда делать ) но такую идею бы предложил, путь же до файла становится известен, так как расширение функционала - навесить просмотр этого файла с локали при наведении (как на стандартных в jQuery), то есть имя файла видеть это хорошо, но когда десяток подготовлен - не плохо иметь возможность пробежаться по ним и поглядеть, те ли это фотки.
Вячеслав, 23 октября 2008, 10:33

Спонсоры

Wi-Fi точки в твоем городе
Profit-project.ru - заработай на своих сайтах Реклама на сайте
RSS

Популярные статьи

Блогорол