Замена стандартному элементу 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 под курсор мыши при перемещении. Кстати, обнаружить это мне удалось именно благодаря Опере (обычно я пользуюсь Лисой, и это большая случайность что я открыл пример именно Оперой), так как автор забыл установить прозрачность ещё и для неё.

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

Допущения

  1. Размер элемента подменяющего file могут значительно отличаться от размеров самого file’а
  2. Элемент file явлеятся частью формы
  3. Только параноик отключает JavaScript в браузере
  4. Посетитель относится к тем скромным 99% пользователей использующих Firefox, Opera или IE
  5. Решение должно работать по одинаковому алгоритму во всех браузерах, т.е. вариант использования разных средств для IE — document.getElementById(‘SaveForm’).click();, а для FF и Opera — подстановка, неприемлем
  6. Решение может дублироваться на страни

Алгоритм

При наведении мыши на подменяющую кнопку слой с элементом подставляется под курсор, так что бы курсор был в середине слоя, т.о. мы будем точно знать что пользователь не промахнётся мимо кнопки и 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


Categories

Links

Feeds