C чего начинается WEB Life Сервер ПО ГОСТЮ
Окт 04

Итак, учимся стилизовать


<input type=”file”>


Изменение внешнего вида инпутов, как правило, не вызывает трудностей, но этот вид инпутов отличается от остальных. В первую очередь это связано с безопасностью, во вторую с тем, что каждый браузер по своему отображает этот элемент, и на это почти нельзя повлиять. Как добиться того внешнего вида файл-инпута, который вам нужен и расскажет эта статья.

Для начала давайте посмотрим на то, как отображаются файл-инпуты без применения каких-либо стилей в разных браузерах.

Как видим, во всех браузерах кроме сафари имеется текстовое поле, а справа от него кнопка. Расскажу о различиях. В Опере и IE мы можем написать адрес файла вручную сомневаюсь, что кто-либо когда-либо пользовался этой возможностью. Файерфокс, несмотря на то, что у него есть текстовое поле, не дает нам вписать туда адрес файла. Вместо этого появляется окно выбора файла как при нажатии на кнопку «Обзор».
Давайте теперь выберем в этих полях какой-либо файл.

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

Но cначала ознакомимся с проблематикой.

1. Средствами JS мы не можем сымитировать клик на такой инпут. Вот что говорится об этом в святом писании спецификации DOM:

click
Simulate a mouse-click. For INPUT elements whose type attribute has one of the following values: “button”, “checkbox”, “radio”, “reset”, or “submit”.
No Parameters
No Return Value
No Exceptions

То есть методом click мы можем сымитировать клик почти на всех типах инпутов, но не на файл-инпуте. Это сделано чтобы обезопасить компьютер клиента: в противном случае хозяин сайта мог бы без проблем получать любые файлы с компьютера клиента. Хотя с другой стороны, по клику вызывается только окно выбора файла. Так или иначе, в девелопер-центре файерфокса этот факт обозначен как баг.

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

Основная трудность в следующей проблеме.

2. Мы не можем свободно влиять на размеры кнопок «обзор», чтобы подогнать инпут под размер перекрываемой картинки. В файерфоксе мы вообще не можем изменить внешний вид файл-инпута средствами css кроме высоты. То есть задача заключается определении оптимального размера перекрываемой картинки, чтобы минимальное количество пикселей было некликабельно, а пустые области не реагировали на клик.

Посмотрим на кликабельные области и их размеры в разных браузерах.

Все что внутри голубой обводки - кликабельная область. Замечу, что высоту кнопок мы можем увеличить, а вот ширину — нет.

———————————————–
Проблемы ясны. Переходим к делу.

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

В обычном состоянии:

при наведении:

Теперь для разных типов файлов подготовим иконки и объединим их в один файл.

Итак, сверстаем шаблон инпута:

HTML:

<div class=”blocker”> <!–блок, перекрывающий поле ввода слева от кнопки–>
<input type=”file” id=”File1″ class=”customFile” />
<div id=”BrowseButton” title=”Выбрать файл” class=”fakeButton”>
<div id=”FileName”> <!–сюда мы будем вставлять имя файла и иконку–>

CSS:

<style type=”text/css”>
#File1 {
position: absolute;
}
.customFile {
width: 219px;
margin-left: -140px;
cursor: default;
height: 21px;
z-index: 2;
filter: alphaopacity: 0;
opacity: 0;
}
.fakeButton {
position: absolute;
z-index: 1;
width: 85px;
height: 21px;
background: urlimages/button.jpg no-repeat left top;
float: left;
}

.blocker {
position: absolute;
z-index: 3;
width: 150px;
height: 21px;
background: urlimages/transparent.gif;
margin-left: -155px;
}
#FileName {
position: absolute;
height: 15px;
margin-left: 90px;
font-family: Verdana;
font-size: 8pt;
color: Gray;
margin-top: 2px;
padding-top: 1px;
padding-left: 19px;
}
#activeBrowseButton {
background: urlimages/button_active.jpg no-repeat left top;
display: none;
}
</style>

Результат выглядит приблизительно так:

Обведенное красным — blocker, файл-инпут показан с половинной прозрачностью.

Теперь при выборе файла событие onchange мы должны вырезать название файла из value нашего файл-инпута, определить тип файла по расширению и сместить фон, чтобы показывалась нужная иконка. Обратите внимание, что в разных операционных системах путь к файлу может быть через прямой слэш в Mac OS, например, или через обратный Виндуз, поэтому чтобы вырезание названия файла работало везде необходимо два регулярных выражения.

function HandleChanges {
file = fileInput.value;
reWin = /.*.*/;
var fileTitle = file.replacereWin, “$1″; //выдираем название файла для windows
reUnix = /.*/.*/;
fileTitle = fileTitle.replacereUnix, “$1″; //выдираем название файла для unix-систем
fileName.innerHTML = fileTitle;

var RegExExt =/.*..*/;
var ext = fileTitle.replaceRegExExt, “$1″;//и его расширение

var pos;
if ext {
switch ext.toLowerCase {
case ‘doc’: pos = ‘0′; break;
case ‘bmp’: pos = ‘16′; break;
case ‘jpg’: pos = ‘32′; break;
case ‘jpeg’: pos = ‘32′; break;
case ‘png’: pos = ‘48′; break;
case ‘gif’: pos = ‘64′; break;
case ‘psd’: pos = ‘80′; break;
case ‘mp3′: pos = ‘96′; break;
case ‘wav’: pos = ‘96′; break;
case ‘ogg’: pos = ‘96′; break;
case ‘avi’: pos = ‘112′; break;
case ‘wmv’: pos = ‘112′; break;
case ‘flv’: pos = ‘112′; break;
case ‘pdf’: pos = ‘128′; break;
case ‘exe’: pos = ‘144′; break;
case ‘txt’: pos = ‘160′; break;
default: pos = ‘176′; break;
};
fileName.style.display = ‘block’;
fileName.style.background = ‘urlimages/icons.png no-repeat 0 -’+pos+’px’;
};

};
function MakeActive {
activeButton.style.display = ‘block’;
};
function UnMakeActive {
activeButton.style.display = ‘none’;
};

Последние две функции MakeActive и UnMakeActive добавляют hover эффект к нашей кнопочке.

Отлично, но осталось несколько проблем. Первая: в разметке большое количество дивов, которые портят семантику.
Вторая: при отключенном js пользователь не увидит, какой файл у него выбран. Давайте в случае отключенного js будем выводить обычный файл-инпут, а всю необходимую нам разметку загружать при загрузке страницы. Приступим:

На странице у нас останется только два элемента:

<div id=”wrapper”>
<input id=”File1″ type=”file”/>
</div>

Если у пользователя будет отключен JavaScript, он увидит обычный файл-инпут. В противном случае произойдет следующее:

window.onload = WindowOnLoad;
var fileInput = document.getElementById’File1′;
var fileName = document.createElement’div’;
fileName.style.display = ‘none’;
fileName.style.background = ‘urlimages/icons.png’;
var activeButton = document.createElement’div’;
var bb = document.createElement’div’;
var bl = document.createElement’div’;
function WindowOnLoad {
var wrap = document.getElementById’wrapper’;
fileName.setAttribute’id’,'FileName’;
activeButton.setAttribute’id’,'activeBrowseButton’;
fileInput.value = ”;
fileInput.onchange = HandleChanges;
fileInput.onmouseover = MakeActive;
fileInput.onmouseout = UnMakeActive;
fileInput.className = ‘customFile’;
bl.className = ‘blocker’;
bb.className = ‘fakeButton’;
activeButton.className = ‘fakeButton’;
wrap.appendChildbb;
wrap.appendChildbl;

wrap.appendChildactiveButton;

wrap.appendChildfileName;
};

Для того, чтобы проще было вникнуть в суть урока можно скачать архив со скриптами урока - fileinputstyling.zip

Оставить комментарий

*
Для того, чтобы убедиться что Вы человек, а не спам-бот, введите пожалуйста ответ.
Анти-спам выражение.