Замена стандартному элементу input file
Недавно, занимаясь кастомизацией (да простят меня русоведы) стандартных элементов формы, а в частности элемента file, я наткнулся на большую неприятность: он оказался не профпригоден для настройки. Суть вот в чём: от элемента file нам особенно нужно его диалоговое окно “Upload files”, добыть который программными средствами в браузерах Mozilla и Opera невозможно, т.е. команда document.getElementById(‘SaveForm’).click(); ничего не вернёт. Разработчики уверяют что это небезопасно, что спорно. А вот IE меня порадовал, он беспрепятственно отправляет нажатие мыши в элемент file, скорее всего по недосмотру разработчиков, оставивших «ужаснейшую дыру» в Вашей безопасности.
Как я только не изворачивался ничего не получалось. Прогуглив три часа, наткнулся на первое свиду идеальное решение: поместить file в div, сделать div прозрачным (opacity: 0%), обращаю ваше внимание именно на то что сделать его нужно прозрачным, но не невидимым (visibility: hidden), условно говоря opacity: 0% прячет элемент от глаз, а visibility:hidden ещё и от мыши. Но если поиграть с размерами шрифтов, метод начинает терять свою привлекательность, появляется возможность промахнуться мимо невидимой кнопки.
Спустя час, я наткнулся на ещё один пример yamzbrowser (позволяет осуществлять загрузку файлов на сервер из swf-объекта вставленного в html-страницу). Он повторяет первый метод, но! с одной лишь разницей: он подставляет div под курсор мыши при перемещении. Кстати, обнаружить это мне удалось именно благодаря Опере (обычно я пользуюсь Лисой, и это большая случайность что я открыл пример именно Оперой), так как автор забыл установить прозрачность ещё и для неё.
Изучив оба метода, я соединил их в одно и разработал решение для более широкого применения в Сети. И так, присаживайтесь поудобнее мы начинаем.
Допущения
- Размер элемента подменяющего file могут значительно отличаться от размеров самого file’а
- Элемент file явлеятся частью формы
- Только параноик отключает JavaScript в браузере
- Посетитель относится к тем скромным 99% пользователей использующих Firefox, Opera или IE
- Решение должно работать по одинаковому алгоритму во всех браузерах, т.е. вариант использования разных средств для IE — document.getElementById(‘SaveForm’).click();, а для FF и Opera — подстановка, неприемлем
- Решение может дублироваться на страни
Алгоритм
При наведении мыши на подменяющую кнопку слой с элементом подставляется под курсор, так что бы курсор был в середине слоя, т.о. мы будем точно знать что пользователь не промахнётся мимо кнопки и visibility меняется на visible: слой с элементом остаётся невидимым, но доступным для мыши. При перемещении курсора двигаем слой в пределах подменяющей кнопки, по достижению края кнопки visibility получает значение hidden.
Рецепт
HTML
<form>
<div id=”divFile1″ class=”file” onmousemove=”divFileMove(this.id, ‘buttonFile1′,event);”>
<input type=”file” name=”UploadFile” id=”file1″ size=”1″ onchange=”result(this.id, ‘divResult’);” />
</div>
<div id=”divResult”> </div>
<image src=”./images/fileUploadButton.jpg” id=”buttonFile1″ onmouseover=”divFileShow(’divFile1′, event);”/>
</form>
CSS
div.file{
position: absolute;
top: 1000px;
left: 1000px;
-moz-opacity: 0;
filter: alpha(opacity=0);
opacity: 0%;
visibility: hidden;
}
div.file — используется именно класс .file а не id, ввиду допущения номер 6.
top, left: 1000px — прячет слой до того как до него доберётся javascript.
-moz-opacity, filter: alpha, opacity — задаёт прозрачность для FF, IE и Opera соответственно.
visibility: hidden — скрывает от мыши.
JavaScript
Функция divFileShow(divId,e), где divId — id слоя с элементом file, e — event. Функции mouseX и mouseY высчитывают положение мыши относительно левого верхнего угла для всех браузеров.
function divFileShow(divId,e){ var div = document.getElementById(divId); div.style.left = (mouseX(e) - Math.round(div.offsetWidth/2))+ “px”;div.style.top = (mouseY(e) - Math.round(div.offsetHeight/2)) + “px”;
div.style.visibility = “visible”;
}
Функция divFileMove(divId, butId, e), где divId — id слоя, butId — id подменяющей кнопки (необходим для получения габаритов кнопки), e — event
function divFileMove(divId, butId, e){ var div = document.getElementById(divId);
var button = document.getElementById(butId);
var move = true;
var divX = parseInt(div.style.left) + Math.round(div.offsetWidth/2);
var divY = parseInt(div.style.top) + Math.round(div.offsetHeight/2); if (divX < button.offsetLeft || divX > (button.offsetLeft+button.offsetWidth)) {
move = false;
}
if (divY < button.offsetTop || divY > (button.offsetTop + button.offsetHeight)){
move = false;
}
if (move){
div.style.left = (mouseX(e) - div.offsetWidth/2) + “px”;
div.style.top = (mouseY(e) - div.offsetHeight/2) + “px”;
} else {
div.style.visibility = “hidden”;
}
}
Add comment 30 Август 2007