Перетаскивание нескольких элементов html сразу
Есть ли способ HTML5 по умолчанию для перетаскивания-многократных элементов в другой элемент html на одной странице?
Кажется, что атрибут HTML5 draggable
, который относится к одному элементу, говорит: "Вы можете перетащить меня, но вам потребуется несколько устройств ввода для одновременного выбора другого перетаскиваемого элемента".
В качестве обхода можно добавить идентификаторы к выбранным элементам с помощью js и получить все выбранные элементы на определенном событии и делать то, что мы хотим. Но действительно ли это "правильный" способ?
При проверке события drop
существует интерфейс для нескольких файлов при обработке перетаскивания файлов. И есть свойство items
- по крайней мере, в Chrome.
В браузерах есть различия.
В Chrome
Событие drop
содержит свойство items
dataTransfer: DataTransfer
items: DataTransferItemList
length: 0
items
кажется 0, независимо от того, перетаскиваете ли вы элемент или нет.
В Firefox
Событие drop
содержит свойство mozItemCount
dataTransfer: DataTransfer
mozItemCount: 1
mozItemCount
кажется не менее 1.
Вот небольшая демонстрация
Где вы можете наблюдать за консолью инструментов разработчика:
Этот источник был взят отсюда: http://www.html5rocks.com/en/tutorials/dnd/basics/
$(function(){
// Copied from: http://www.html5rocks.com/en/tutorials/dnd/basics/
var cols_ = document.querySelectorAll('.column');
var dragSrcEl_ = null;
handleDragStart = function(e) {
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/html', this.innerHTML);
dragSrcEl_ = this;
this.style.opacity = '0.4';
// this/e.target is the source node.
$(this).addClass('moving');
};
handleDragOver = function(e) {
if (e.preventDefault) {
e.preventDefault(); // Allows us to drop.
}
e.dataTransfer.dropEffect = 'move';
return false;
};
handleDragEnter = function(e) {
$(this).addClass('over');
};
handleDragLeave = function(e) {
// this/e.target is previous target element.
$(this).removeClass('over');
};
handleDrop = function(e) {
// this/e.target is current target element.
console.log(e.dataTransfer);
if (e.stopPropagation) {
e.stopPropagation(); // stops the browser from redirecting.
}
// Don't do anything if we're dropping on the same column we're dragging.
if (dragSrcEl_ != this) {
dragSrcEl_.innerHTML = this.innerHTML;
this.innerHTML = e.dataTransfer.getData('text/html');
}
return false;
};
handleDragEnd = function(e) {
// this/e.target is the source node.
this.style.opacity = '1';
[].forEach.call(cols_, function (col) {
$(col).removeClass('over');
$(col).removeClass('moving');
});
};
[].forEach.call(cols_, function (col) {
col.setAttribute('draggable', 'true'); // Enable columns to be draggable.
col.addEventListener('dragstart', this.handleDragStart, false);
col.addEventListener('dragenter', this.handleDragEnter, false);
col.addEventListener('dragover', this.handleDragOver, false);
col.addEventListener('dragleave', this.handleDragLeave, false);
col.addEventListener('drop', this.handleDrop, false);
col.addEventListener('dragend', this.handleDragEnd, false);
});
});
.column {
height: 150px;
width: 150px;
float: left;
border: 2px solid #666666;
background-color: #ccc;
margin-right: 5px;
border-radius: 10px;
box-shadow: inset 0 0 3px #000;
text-align: center;
cursor: move;
margin-bottom: 30px;
}
.column header {
color: #fff;
text-shadow: #000 0 1px;
box-shadow: 5px;
padding: 5px;
background: linear-gradient(left center, rgb(0,0,0), rgb(79,79,79), rgb(21,21,21));
border-bottom: 1px solid #ddd;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
}
.column {
transition: transform 0.2s ease-out;
}
.column.over {
border: 2px dashed #000;
}
.column.moving {
opacity: 0.25;
transform: scale(0.8);
}
.column .count {
padding-top: 15px;
font-weight: bold;
text-shadow: #fff 0 1px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="cols">
<div class="column">
<header>C</header>
</div>
<div class="column">
<header>B</header>
</div>
<div class="column">
<header>A</header>
</div>
</div>
Ответы
Ответ 1
Прежде всего, длина текста items
, а также длина files
работает в Chrome. Вы всегда получаете длину 0, потому что информация в хранилище данных перетаскивания защищена, за исключением события drop. Поэтому, когда вы регистрируете объект и смотрите на него потом, у вас нет доступа к информации. Но если вы зарегистрируете его следующим образом:
console.log(e.dataTransfer.items.length);
Тогда у вас будет доступ к фактической длине. См. Здесь protected mode
:
https://html.spec.whatwg.org/multipage/interaction.html#the-drag-data-store
Это не означает, что он даст вам количество перетаскиваемых элементов, и есть несколько причин, почему:
Прежде всего, родной drag and drop API
также используется для перетаскивание из браузера в другие приложения и наоборот. Так многие из этих функций имеют дело с этими случаями.
Другое дело, что API перетаскивания дает вам доступ к вещам, которые по умолчанию поведение браузера в отношении перетаскивания вещей. Например, перетаскивание ссылки в вашем браузере откроет ссылку. когда вы используете API, вы получаете доступ к этим типам поведения.
Многие действия этого API являются следствием этого и в этом смысле на самом деле не предназначены для перетаскивания элементов DOM. С этой целью другие библиотеки, вероятно, более подходят или просто управляют самим контентом через различные события, которые он предлагает.
Поскольку вы можете перетаскивать элементы из других приложений, эта информация связана с большим количеством информации. Например, в dataTransferItem
у вас есть доступ к объекту fileList
. Это работает только при перетаскивании файлов из вашей ОС в браузер. Таким образом, у вас есть количество файлов, и разные файлы перетаскиваются. Но это не имеет никакого отношения к перетаскиванию DOM elements
.
Вы также можете перетащить из браузера. Очень полезно, например, если вы хотите перетащить содержимое HTML в Word. Но тогда информация для передачи сложнее, чем просто элементы DOM. В этом случае вы перетаскиваете items
, но эти items
не являются элементами DOM для каждого. Это разные типы вещей, которые можно передать.
Типы вещей, которые могут быть перенесены, сильно различаются в реализации, но в основном вы можете иметь простой текст, html-контент и ссылки. Таким образом, длина элементов будет иметь длину доступных типов. Например, в jsfiddle ниже, в Chrome вы можете перетаскивать изображения, ссылки и обычный текст (для этого вам нужно выбрать только текст). Результат:
console.log(e.dataTransfer.items.length,
e.dataTransfer.getData('text/plain'),
e.dataTransfer.getData('text/uri-list'),
e.dataTransfer.getData('text/html'));
при перетаскивании каждого элемента на серой цели:
Обычный текст с ввода:
length: 1
plain text: text
link:
html content:
Из изображения:
length: 2
plain text:
link: http://www.exiv2.org/include/img_1771.jpg
html content: <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"><img id="image1" src="http://www.exiv2.org/include/img_1771.jpg">
От ссылки:
length: 3
plain text: http://google.com/
link: http://google.com/
html content: <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"><a href="#" onclick="location.href='http://google.com/'; return false;">link 1</a>
Смотрите здесь: http://jsfiddle.net/ztj6t2ff/9/
Вы увидите, что html
не совсем то, что у вас есть на вашей странице. Это позволяет переносить другие приложения и поддерживать наилучшее форматирование.
В общем, этот API
позволяет вам вмешиваться в поведение по умолчанию при перетаскивании всего, что вы можете перетащить в свою ОС в браузере и из него. В этом смысле это довольно сложно, но большинство функций не имеют ничего общего с перетаскиванием элементов DOM внутри одной и той же страницы.
И фактически почти все манипуляции с DOM посредством перетаскивания выполняются без использования этого API. jquery-ui draggable
, например, не полагается вообще на этот API.