БлогNot. Как поменять местами блоки на странице

Как поменять местами блоки на странице

Почти традиционной для этого дня числовой или календарной загадки сегодня ещё не было в связи с занятостью :)

Сделаем её сейчас, заодно опубликовав полезный образец по обмену местами (свопингу) блоков на странице с помощью перетаскивания их мышью. Всё реализовано на объекте DragManager, который становится обработчиком событий dragstart, dragend и функции DragContainer, которая добавляет в менеджер последовательно переданные ей через аргумент элементы стилевого класса dragContainer (в нашем случае класс назначается обычному списку <ul>, а перетаскиваемые блоки будут его элементами <li> с HTML-атрибутом draggable). Метод checkContainers, проверяющий, достигнута ли цель перетаскивания блоков, предполагает, что нужный контент содержится в потомках элементов из массива dragContainers (это всё те же элементы <li>, вложенные в список <ul class="dragContainer">). Если цель достигнута, обработку можно и прекратить, соответствующий код в исходнике закомментирован. В браузере должен быть включен JavaScript, чтобы всё работало.

Итак, перетаскивая блоки с цифрами, собери день и месяц рождения нашего дорогого Одмина, то есть, меня (кстати, а ещё хоть какую-нибудь дату ДД.ММ можно из этого собрать?):

  • 5
  • 2
  • 0
  • 3

В старину, а точней, лет 10 назад, такое уже тоже можно было делать (ниже прилагается старый исходник), но телодвижений требовалось примерно вдвое больше. Применение JQuery и новых стандартов JS заметно упрощает задачу. Исходный текст старого скрипта можно увидеть в коде страницы (кодировка Юникода UTF-8).

 Обмен блоков на странице средствами HTML5, старый код, открыть в текущем окне/вкладке (10 Кб)

Ниже публикуется исходник показанного в начале статьи нового примера на swap blocks (без стандартного обрамления HTML).

<style>
 /* основной контейнер */
 .dragContainer {
   list-style-type: none;
   margin: 0 auto;
   text-align: center;
   width: 40em;
   padding: 1em;
   border: 1px solid transparent;
 }
 .dragContainer:hover {
   border: 1px solid #999;
 }
 /* перетаскиваемый элемент */
 .dragContainer li {
   display: inline;
   border: 1px solid #ccc;
   margin: 0.5em;
   line-height: 2em;
   padding: 0 2em;
   cursor: move;
 }
 .dragContainer li:before { /* в начале */
 }
 .dragContainer li:last-of-type { /*в конце */
  margin-bottom: 0;
 }
 .dragContainer li:hover { /* поверх */
  background-color: #eee;
 }
 .dragContainer li.my_drag_class { /* при размещении */
  border: 1px dashed #999;
  background-color: #cfc;
 }
</style>

<ul class="dragContainer">
  <li draggable="true">5</li>
  <li draggable="true">2</li>
  <li draggable="true">0</li>
  <li draggable="true">3</li>
</ul>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
let DragManager = {
 dragContainers: [],
 currentContainer: null,
  
 add: function(dragContainer) {
  this.dragContainers.push(dragContainer);
 },
  
 handleEvent: function(event) {
  if (event.type == 'dragstart') {
   let containers = this.dragContainers.filter(function(container) {
    return container.contains(event.target);
   });
   if (containers.length > 0) {
    this.currentContainer = containers[0];
    this.currentContainer.activate();
   }
  }
  if (this.currentContainer !== null) {
   this.currentContainer.handleEvent(event);
   if (event.type == 'dragend') {
    this.currentContainer.deactivate();
    this.currentContainer = null;
   }
  }
 }
};

window.addEventListener('dragstart', DragManager);
window.addEventListener('dragend', DragManager);

function DragContainer (container) {
 this.element = container;
 this.items = $('> li', this.element);
 this.draggingItem = null;
 DragManager.add(this);
}

DragContainer.prototype.contains = function(target) {
 return $(this.element).find(target).length;
}

DragContainer.prototype.handleEvent = function(event) {
 //Связываем this с объектом DragContainer, а не с элементом, на котором было запущено событие
 let $t = $(event.target);
 if (event.type == 'dragstart') {
  this.draggingItem = event.target;
  event.dataTransfer.setData('text/html', this.draggingItem.innerHTML);
 }
 if (event.type == 'dragover' && this.draggingItem != event.target) {
  $t.addClass('my_drag_class');
  if (event.preventDefault) {
   event.preventDefault(); //не выполнять действий по умолчанию!
  }
  event.dataTransfer.dropEffect = 'move';
 }
 if (event.type == 'dragleave') {
  $t.removeClass('my_drag_class');
 }
 if (event.type == 'drop' && this.draggingItem != null) { //Собственно, обмен блоков
  this.draggingItem.innerHTML = event.target.innerHTML;
  event.target.innerHTML = event.dataTransfer.getData('text/html');
 }
 if (event.type == 'dragend' || event.type == 'drop') {
  this.items.removeClass('my_drag_class');
  this.draggingItem = null;
  checkContainers(); //проверка на окончание
 }
}

DragContainer.prototype.activate = function() {
 for (let i = 0, j=this.items.length; i < j; i++) {
  this.items[i].addEventListener('dragenter', this.handleEvent.bind(this));
  this.items[i].addEventListener('dragover', this.handleEvent.bind(this));
  this.items[i].addEventListener('dragleave', this.handleEvent.bind(this));
  this.items[i].addEventListener('drop', this.handleEvent.bind(this));
 }
}

DragContainer.prototype.deactivate = function() {
 this.draggingItem = null;
 for (let i = 0, j=this.items.length; i < j; i++) {
  this.items[i].removeEventListener('dragenter', this.handleEvent);
  this.items[i].removeEventListener('dragover', this.handleEvent);
  this.items[i].removeEventListener('dragleave', this.handleEvent);
  this.items[i].removeEventListener('drop', this.handleEvent);
 }
}

let dragContainers = document.getElementsByClassName('dragContainer');

for(let i =0, j=dragContainers.length; i < j; i++) {
 new DragContainer(dragContainers[i]);
}

let checkContainers = function() {
 let s = '';
 for (let i =0, j=dragContainers.length; i < j; i++) {
  s += $(dragContainers[i]).children().text();
 }
 let good = (s == '2305');
 for (let i =0, j=dragContainers.length; i < j; i++) { //если код правильный - подсветить
  $(dragContainers[i]).children().css('background-color',(good ? '#fcc' : 'transparent'));
 }
 if (good) { //Убрать комментарии, чтобы прекратить перетаскивание
  //window.removeEventListener('dragstart', DragManager);
  //window.removeEventListener('dragend', DragManager);
 }
}
</script>

теги: javascript jquery программирование список дата

23.05.2020, 21:49; рейтинг: 27