Drag & Drop с использованием HTML5

Владимир | | HTML, JavaScript, Web разработка.

html5 drag drop

К сожалению, на сегодняшний день использовать HTML5 довольно сложно. Стандарт в состоянии разработки и далеко не все браузеры поддерживают его возможности. Тем не менее, интересных нововведений в нём много и о них полезно знать. Поэтому сегодня я расскажу о моих экспериментах с перетаскиванием объектов (Drag & Drop).

Хочу предупредить. Приведённый ниже код работает в последних версиях Firefox и Google Chrome, в IE8 и Opera поддержка этих возможностей отсутствует.

Сразу даю ссылки на демонстрационную страничку и архив с примером.

Source

Чтобы просто разобраться с принципом работы D&D я решил сделать страничку с текстовыми блоками, которые можно будет перетаскивать из одного контейнера в другой.

Сама страница (index.html) имеет следующую разметку.

<!DOCTYPE html>
<html>
<head>
    <meta charset=utf-8>
    <title>HTML5 Drag & Drop</title>
    <link rel="stylesheet" href="styles.css">
    <script src="jquery-1.4.2.min.js"></script>
    <script src="init.js"></script>
</head>
<body>
    <div class="wrapper">
        <div id="block1">
            <div class="textBlock">Текст 1</div>
            <div class="textBlock">Текст 2</div>
            <div class="textBlock">Текст 3</div>
        </div>
        <div id="block2"></div>
    </div>
</body>

Как видите, на странице размещено два контейнера (block1 и block2). В первом находятся три блока с различным текстом. Второй контейнер пуст, в него можно будет перетягивать блоки.

Прежде всего, сделаем блоки «перетягиваемыми». Для этого нужно установить для соответствующего тега атрибут draggable="true" и назначить обработчик события dragstart.

Например (используется библиотека jQuery)

$('.textBlock')
    .attr('draggable', 'true')
    .bind('dragstart', function(event) {
        event.originalEvent.dataTransfer.setData('text/plain', $(this).html());
        return true;
    });

Кроме установки атрибута и обработчика необходимо сохранить данные, которые мы перетягиваем в объекте dataTransfer. Доступ к нему можно получить через объект event, который передаётся в первом параметре обработчика.

Для сохранения данных используется метод setData, в первом параметре которого нужно указать формат данных, а во втором – сами данные. К сожалению, как показала практика, разные браузеры поддерживают разные форматы. В стандарте речь идет только о двух: text/plain и text/uri-list. Firefox поддерживает шесть. В общем, чтобы пример нормально работал и в Firefox и в Chrome, я остановился на text/plain.

Теперь нужно подготовить контейнер к приёму объектов.

Для этого необходимо назначить ему обработчики событий dragenter, dragleave, dragover и drop. Причём первые три должны возвращать false, чтобы заблокировать стандартное поведение браузера.

В результате у меня получился следующий код.

$('#block2')
	.bind('dragenter', function(event) {
		$(this).addClass('dropHere');
		return false;
	})
	.bind('dragleave', function(event) {
		$(this).removeClass('dropHere');
		return false;
	})
	.bind('dragover', function(event) {
		return false;
	})
	.bind('drop', function(event) {
		$(this).removeClass('dropHere');
		var data = event.originalEvent.dataTransfer.getData('text/plain');
		$(this).append($('<div class="textBlock">' + data + '</div>'));
		return true;
	});

В обработчиках событий dragenter и dragleave выполняется установка и снятие CSS класса, который подсвечивает блок, когда над ним находится перетаскиваемый объект.

Событие drop возникает, когда пользователь отпускает левую клавишу мыши. При этом объект, который мы перетаскиваем, сам по себе не вставится. Но мы можем получить доступ к данным, которые были сохранены в dataTransfer. Для этого используется метод getData и в его параметре необходимо указать тип данных. После этого, с помощью append вставляем объект.

Как видите, принцип достаточно простой, и поддержка реализована неплохо. Например, работает перетаскивание из Chrome в Firefox и из Word в Firefox.

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

  • Знаете какой минус во всем этом?
    При добавлении поддержки различных стандартов, браузеры становятся всё больше и неповоротливее.

  • Знаете какой минус во всем этом?
    При добавлении поддержки различных стандартов, браузеры становятся всё больше и неповоротливее.

  • xandeadx

    При добавлении поддержки различных стандартов, браузеры становятся всё больше и неповоротливее.

    наверное именно поэтому, из версии к версии, браузеры покоряют новые скоростные вершины 🙂

    • наверное именно поэтому, из версии к версии, браузеры покоряют новые скоростные вершины 🙂

      ссылочка битая (по крайней мере у меня страничка пустая)
      но я понял, что вы имели ввиду. Рост скорости браузеров обусловлен ростом возможностей оборудования.
      На моем первом компе стояло 128 Мб памяти. Я на 98% уверен, что последние версии современных браузеров захлогли бы в такой среде.

      • Serator

        Celeron 766 MHz + 128 оперативки легко тянут ту же лису 3.6.3 (да хоть 3-ю альфу 3.7). Ускорение достигается не только за счет того, что используется лучшее железо, а еще и за счет того, что то, что раньше делалось на js (к примеру), поддерживается нативно + аппаратное ускорение + оптимизация алгоритмов и движков (рендеринга, js, графических). Просто нужно и свои скрипты писать так, чтобы процессор не нагружался под 100%, а не надеяться на то, что браузер сам все оптимизирует.

        • Такие тесты вещь хорошая, но тестировать можно по-разному 🙂

          Из собственного опыта. На машине Celeron 1,7ГГц + 256 ОЗУ Google Chrome работает раза в 2 быстрее FF (субъективно, конечно, но разница видна невооруженным взглядом). В тоже время Core 2 Duo T7100 + 2ГБ ОЗУ и разницу между этими браузерами в скорости заметить практически невозможно.

          А вообще, сравнивать браузеры сами по-себе может быть и правильно с теоретической точки зрения, но на практике посетитель заходит на страницу, например, с объемным флеш-роликом, и тот же FF начинает кушать под 200 МБ памяти. Какая разница посетителю кто память съел? Флеш-плеер или сам браузер? Он открыл страницу — начал тормозить компьютер.

          В общем, без апгрейда железа обойтись не получится.

        • Serator

          Ну 200 метров может и Chrom скушать, но проблема не в этом. Если у Chrom'а каждая вкладка / расширение / плагин — отдельный процесс и при закрытии выделенная память высвобождается, то в Fx не все так гладко, но плагины уже выделили в отдельный процесс, остались вкладки и расширения. Как только это сделают, так и нагрузка между Chrom'ом и Fx будет соизмеримая, ИМХО 🙂

        • Может быть. Но у меня сложилось впечатление, что в FF поддержка XUL сама по себе какое-то количество ресурсов потребляет. Правда, конкретных цифр не видел.

  • xandeadx

    При добавлении поддержки различных стандартов, браузеры становятся всё больше и неповоротливее.

    наверное именно поэтому, из версии к версии, браузеры покоряют новые скоростные вершины 🙂

    • наверное именно поэтому, из версии к версии, браузеры покоряют новые скоростные вершины 🙂

      ссылочка битая (по крайней мере у меня страничка пустая)
      но я понял, что вы имели ввиду. Рост скорости браузеров обусловлен ростом возможностей оборудования.
      На моем первом компе стояло 128 Мб памяти. Я на 98% уверен, что последние версии современных браузеров захлогли бы в такой среде.

      • Serator

        Celeron 766 MHz + 128 оперативки легко тянут ту же лису 3.6.3 (да хоть 3-ю альфу 3.7). Ускорение достигается не только за счет того, что используется лучшее железо, а еще и за счет того, что то, что раньше делалось на js (к примеру), поддерживается нативно + аппаратное ускорение + оптимизация алгоритмов и движков (рендеринга, js, графических). Просто нужно и свои скрипты писать так, чтобы процессор не нагружался под 100%, а не надеяться на то, что браузер сам все оптимизирует.

        • Такие тесты вещь хорошая, но тестировать можно по-разному 🙂

          Из собственного опыта. На машине Celeron 1,7ГГц + 256 ОЗУ Google Chrome работает раза в 2 быстрее FF (субъективно, конечно, но разница видна невооруженным взглядом). В тоже время Core 2 Duo T7100 + 2ГБ ОЗУ и разницу между этими браузерами в скорости заметить практически невозможно.

          А вообще, сравнивать браузеры сами по-себе может быть и правильно с теоретической точки зрения, но на практике посетитель заходит на страницу, например, с объемным флеш-роликом, и тот же FF начинает кушать под 200 МБ памяти. Какая разница посетителю кто память съел? Флеш-плеер или сам браузер? Он открыл страницу — начал тормозить компьютер.

          В общем, без апгрейда железа обойтись не получится.

        • Serator

          Ну 200 метров может и Chrom скушать, но проблема не в этом. Если у Chrom'а каждая вкладка / расширение / плагин — отдельный процесс и при закрытии выделенная память высвобождается, то в Fx не все так гладко, но плагины уже выделили в отдельный процесс, остались вкладки и расширения. Как только это сделают, так и нагрузка между Chrom'ом и Fx будет соизмеримая, ИМХО 🙂

        • Может быть. Но у меня сложилось впечатление, что в FF поддержка XUL сама по себе какое-то количество ресурсов потребляет. Правда, конкретных цифр не видел.

  • Евгений Smarty

    В картинке правильно бы написать drag, а не drug.

  • Евгений Smarty

    В картинке правильно бы написать drag, а не drug.

  • Хотелось бы высказать свои наблюдения насчет скорости браузеров. Железо HP dv5, AMD Turion x2 2.2 GHz, 256 Mb ATI, 3 Gb оперативки, машина мощная, но FF с парой плагинов для Web разработки очень медленно работает, а тот же Хром летает как истребитель (по сравнению с FF), — это все очень хорошо видно не вооруженным глазом, спец.тестов не делал.
    К чему я это все? В данный момент Хром более оптимизирован и более шустро работает, не только за счет железа, но и своих программных решений. ИМХО.

    Статья интересная, захотелось применить это где нибудь, только пока не знаю где 🙂

    • Serator

      На hacks.mozilla.org есть статья про новый движок js в Fx — JägerMonkey. Работа над ним еще идет, но в будущем скорость Chrom'а и Fx будет соизмерима. На хабре в комментариях есть еще немного о движке js в Fx и то, почему он уступает конкурентам.

      P.S. Владимир, пора уже новую статью о браузерах писать, ибо людям интересно )))

    • Serator

      + немного будущего 🙂

      • Будущее, как всегда, выглядит очень светлым 🙂
        Думаю, через какое-то время возможности браузеров более-менее сравняются. Хотя, насчет IE не уверен 🙂

        P.S. Идея хорошая, но я не эксперт в браузерах, а просто пересказывать какой-нибудь пресс-релиз не хочется 🙂

  • Хотелось бы высказать свои наблюдения насчет скорости браузеров. Железо HP dv5, AMD Turion x2 2.2 GHz, 256 Mb ATI, 3 Gb оперативки, машина мощная, но FF с парой плагинов для Web разработки очень медленно работает, а тот же Хром летает как истребитель (по сравнению с FF), — это все очень хорошо видно не вооруженным глазом, спец.тестов не делал.
    К чему я это все? В данный момент Хром более оптимизирован и более шустро работает, не только за счет железа, но и своих программных решений. ИМХО.

    Статья интересная, захотелось применить это где нибудь, только пока не знаю где 🙂

    • Serator

      На hacks.mozilla.org есть статья про новый движок js в Fx — J?gerMonkey. Работа над ним еще идет, но в будущем скорость Chrom'а и Fx будет соизмерима. На хабре в комментариях есть еще немного о движке js в Fx и то, почему он уступает конкурентам.

      P.S. Владимир, пора уже новую статью о браузерах писать, ибо людям интересно )))

    • Serator

      + немного будущего 🙂

      • Будущее, как всегда, выглядит очень светлым 🙂
        Думаю, через какое-то время возможности браузеров более-менее сравняются. Хотя, насчет IE не уверен 🙂

        P.S. Идея хорошая, но я не эксперт в браузерах, а просто пересказывать какой-нибудь пресс-релиз не хочется 🙂

  • Ты прям на самом острие. Статейка очень порадовала и HTML 5 тоже

    ЗЫ: нытики всегда про скорость потеют

  • Ты прям на самом острие. Статейка очень порадовала и HTML 5 тоже

    ЗЫ: нытики всегда про скорость потеют

  • Возможности HTML5 впечатляют! Вот только когда ним можно будет пользоваться в полной мере? Если до сих пор лиди сидят на ИЕ6!

    • Вопрос риторический. Тем не менее, люди пользуются ими уже сейчас. Например, есть web редактор для рисование макетов http://gomockingbird.com/mockingbird/ , IE он, конечно, не поддерживает.

      • Serator

        Да сразу на chromeexperiments.com ) IE вообще сие работы поддерживать не будут (ну, не считая 9-ки пре альфа), ибо канвас…

    • Serator

      Ну сидят и сидят. HTML5 от части и на нем работает, к примеру contenteditable. 🙂

  • Возможности HTML5 впечатляют! Вот только когда ним можно будет пользоваться в полной мере? Если до сих пор лиди сидят на ИЕ6!

    • Вопрос риторический. Тем не менее, люди пользуются ими уже сейчас. Например, есть web редактор для рисование макетов http://gomockingbird.com/mockingbird/ , IE он, конечно, не поддерживает.

      • Serator

        Да сразу на chromeexperiments.com ) IE вообще сие работы поддерживать не будут (ну, не считая 9-ки пре альфа), ибо канвас…

    • Serator

      Ну сидят и сидят. HTML5 от части и на нем работает, к примеру contenteditable. 🙂

  • Ну как перейдет большинство сайтов на HTML5, так и попереходят пользователи на новые браузерами! Прогрес не остановить!!!

  • Ну как перейдет большинство сайтов на HTML5, так и попереходят пользователи на новые браузерами! Прогрес не остановить!!!

  • Max

    добавил статью в поиск о html5 (html5.flexum.ru)

  • Дмитрий Кадочников

    Впишите свой комментарий.

  • den1n

    Самая большая проблема в этом способе, то что во время перемещения объекта невозможно скролить страницу колесом мыши. Если список большой, то это очень напрягает.

    • Согласен. Но если список не помещается на экране, то работать с ним в любом случае будет не удобно. Можно попробовать переделать структуру списка, например, вывести в несколько колонок…

  • Alexander Plutov

    Хорошая статья по Drag & Drop http://plutov.by/post/html5_drag_and_drop

  • Alexander Plutov

    Спасибо за статью. Вот еще немного про drag&drop в html5: http://plutov.by/post/html5_drag_and_drop

  • Александр

    Как же сделать так, чтобы при переносе картинки в одну область, я мог её из этой области вернуть в исходную позицию?

  • Всё бы супер, но contenteditable еще очень сырой, вот один фикс со вставкой в моем блоге — http://plutov.by/post/contenteditable_remove_styles