HTML5 Drag&Drop

Привет, уважаемые читатели и подписчики моего блога zacompom.ru.

Сегодня мы рассмотрим новую фишку HTML5 — Drag&Drop или как сказать популярным языком, перетаскивание файлов c рабочего стола в браузер. Это одна из наиболее интересных возможностей нового варианта HTML. Я ее опишу как:

  • сделать возможным перетаксивание файлов на элемент web страницы.
  • анализировать перенесенные файлы с помошью JavaScript.
  • загружать и парсить файлы со стороны клиента.
  • асинхронно загружать файлы на сервер используя XMLHttpRequest2
  • показать прогресс бар пока идет загрузка файлов

В этой статье расмотрим первые три пункта. В итоге получим примерно такую форму:

drag1

Поддержка браузеров

Прежде чем начать, нужно отметить что поддержка перетаскивания файлов браузерами будет неравномерной. Код работает в современных браузерах, но вполне возможно API будет меняться.

Ко мне часто поступают вопросы про хостинг, которым я пользуюсь и поэтому решил указать хостинг в статье https://sprinthost.ru. Вы можете попробовать попользоваться хостингом 30 дней бесплатно. Чтобы понять, как будет работать Ваш сайт на этом хостинге просто перенести свой сайт (в этом поможет поддержка хостинга бесплатно) и и таким образом сможете понять подходит хостинг Вам или нет. На этом хостинге находятся сайты с 20 000 тысяч посещаемость и сайты чувствуют себя отлично. Рекомендую! Да, если делать оплату на 1 год то получаете скидку 25%. И что мне нравится - тех. поддержка всегда помогает в технических вопросах, за что им спасибо. Как Вы понимаете не всегда проходит всё гладко и нет желания, чтобы сайт не был доступен тем самым страдал трафик и доход.
  • Последние версии Firefox и Chrome поддерживают все функции и превосходно работают с перетаскиванием.
  • Опера может парсить файлы в JavaScript, но не поддерживает перетаскивание файлов и загрузку с помощю XMLHttpRequuest2
  • IE и десктоповые версии Safari не поддерживают ничего из нужного API.

HTML и CSS

Далее идет код стандартной формы с инпутом типа файл. Единственное HTML5 нововведение в форме это атрибут “multiple” который позволяет пользователю выбирать любое количество файлов.

Со стороны сервера загрузка файлов будет проводиться средствани PHP, но независимо от того какую технологию вы используете на сервере JavaScript код останется тем же. Скрытое поле MAX_FILE_SIZE определяет 300,000 байт, размер будем проверять и на стороне клиента и на стороне сервера, чтобы предотвротить загрузку огромного размера файлов.

<form id="upload" action="upload.php" method="POST" enctype="multipart/form-data">
        <fieldset>
                <legend>HTML Загрузка Файлов</legend>
                <input type="hidden" id="MAX_FILE_SIZE" name="MAX_FILE_SIZE" value="300000" />
                <div>
                        <label for="fileselect">Выберите файлы для загрузки:</label>
                        <input type="file" id="fileselect" name="fileselect[]" multiple="multiple" />
                        <div id="filedrag" >Или перетащите их сюда</div>
                </div>
                <div id="submitbutton">
                        <button type="submit">Загрузить файлы</button>
                </div>
        </fieldset>
</form>

Элемент #filedrag будет использоваться как облясть в которую необходимо пренести файлы. Элемент в CSS стилях скрыт, но он будет отображаться средствами JavaScript если перетаскивание поддерживается браузером:

*{
     margin: 0px;
}
body{
     background: none repeat scroll 0% 0% #EFEFEF;
}
.wrapper{
     background: none repeat scroll 0% 0% #FFFFFF;
     margin: 150px auto;
     border: 2px solid #3DA8BA;
     padding: 10px;
     width: 500px;
}
fieldset{
        border:2px solid #efefef;
}
#filedrag{
        border-radius: 7px 7px 7px 7px;
        border: 2px dashed #3DA8BA;
        color: #555555;
        cursor: default;
        display: none;
        margin: 1em 0pt;
        padding: 1em 0pt;
        text-align: center;
        background:#f9f9f9;
}
#filedrag.hover {
        border-style: solid;
        box-shadow: 0pt 3px 4px #dbdbdb inset;
}
#messages{
        margin-top:10px;
        padding:5px;
        font-size:14px;
}
#messages p{
        border-bottom:1px solid #efefef;
        margin-bottom:5px;
}

Для элемента также определенн класс .hover который меняет стили когдо пользователь перетаксивает файлы на элемент. Браузеры не поддерживают стили :hover в этой ситуации, но мы можем добовлять класс спомощю Javascript когда происходит нужное событие.

File API

W3C File API предостовляет несколько объектов которые мы будем использовать:

  • FileList: предостовляет массив выбранных файлов.
  • File: предстовляет единственный файл.
  • FileReader: интерфейс который позволяет нам считать информацию о файле со стороны клиента и использовать в JavaScript.

JavaScript события

Пришло время писать JavaScript код. Мы не будем использовать JavaScript фреймфроков, поэтому напишем пару фуннкций для сохронения нашего времени. Это функция которая достает нужный элемент по ид и функция выводящая сообщения

/* getElementById */
function $id(id) {
        return document.getElementById(id);
}

/* вывод сообщений */
function Output(msg) {
        var m       = $id("messages");
        m.innerHTML = msg + m.innerHTML;
}

Далее проверим поддержку File API и вызовем функцию инициализации Init():

/* проверка поддержки API */
if (window.File && window.FileList && window.FileReader){
        Init();
}
/* инициализация */
function Init(){

        var fileselect   = $id("fileselect"),
                filedrag     = $id("filedrag"),
                submitbutton = $id("submitbutton");

        /* выбор файла */
        fileselect.addEventListener("change", FileSelectHandler, false);

        /* проверка поддержки XHR2 */
        var xhr = new XMLHttpRequest();
        if (xhr.upload){

                /* сброс файла */
                filedrag.addEventListener("dragover", FileDragHover, false);
                filedrag.addEventListener("dragleave", FileDragHover, false);
                filedrag.addEventListener("drop", FileSelectHandler, false);
                filedrag.style.display = "block";

                /* удаление кнопки сабмитта */
                submitbutton.style.display = "none";
        }

}

Функция Init():

  • Устонавливает обработчик события к изменению инпута типа файл.
  • Отоброжает элемент #filedrag.
  • Устанавливает обработчики событий “dragover” и “dragleave” для динамического изменения стилей элемента #filedrag.
  • Устанавливает обработчик события “drop” для элемента #filedrag.
  • Скрывает кнопку сабмитта формы – он пока не требуется, так как мы будем просто анализировать файлы.

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

Проверка поддержки метода XMLHttpRequest.upload предотврощает проблемы с Оперой. Браузер поддерживает объекты File, FileList и FileReader, но не поддерживает перетаскивание файлов или XMLHttpRequest2. Поэтому мы отоброжаем информацию о файле, но оставляем скрытым элемент #filedrag.

Изменение стилей при переносе

Мало кто испытал перетаскивание файлов в браузер. На самом деле, многие опытные интернет пользователи считают это невозможным. Поэтому написали внутри элемента “перетащите сюда файлы”. А следующая функция будет добвлять класс к элементу, когда файл уже будет находится непосредственно над элементом, тем самым будут меняться стили.

// Файл над нужной областью
function FileDragHover(e){
        e.stopPropagation();
        e.preventDefault();
        e.target.className = (e.type == "dragover" ? "hover" : "");
}

Анализирование перетащенных или выбранных файлов

Будем использовать функцию FileSelectHandler() не зависимо от того обин или несколько файлов были выбранны или перетащенны на элемент #filedrag:

// выбор файла
function FileSelectHandler(e){

        FileDragHover(e);

        // проходимся по объекту FileList 
        var files = e.target.files || e.dataTransfer.files;

        // парсим все объекты типа File
        for (var i = 0, f; f = files[i]; i++){
                ParseFile(f);
        }

}

Функция:

  1. Вызываем функцию FileDragHover() чтобы убрать стиля при hover и предотвратить выполнение событий браузера. Это очень важно, так как браузер может попытаться отобразить файл.
  2. Проходимся по объекту FileList.
  3. Наконец функция проходит по всем объектам типа File в объекте FileList и передает их как аргумент в функцию ParseFile().
function ParseFile(file) {
        Output(
                "<p>File information: <strong>" + file.name +
                "</strong> type: <strong>" + file.type +
                "</strong> size: <strong>" + file.size +
                "</strong> bytes

" ); }

Функция выводит информация используя три основные свойства представленные объектом File только для чтения.

  • .name: имя файла (не включая путь к файлу)
  • .type: MIME тип, например: image/jpeg, text/plain, и т.д.
  • .size: размер файла в байтах

Ну вот как то так!

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

На этом буду заканчивать — до новых встреч!

С Вами был, как и всегда на этом сайте, ваш Юрич!

P.S. В следующей статье я постараюсь описать эффект lightbox как на сайте Facebook. Заходи ко мне на блог чаще!


Обо мне
Юрич:
Занимаюсь созданием сайтов на WordPress более 6 лет. Ранее работал в нескольких веб-студиях и решил делиться своим опытом на данном сайте. Пишите комментарии, буду рад общению.

Заказать сайт