将AngularJS、jQueryUI、Angular-Drag-Drop合并为排序列表
I have the following situation where I need to allow a user to select objects from a list and drag/drop them into a certain slot:
我有以下情况,我需要允许用户从列表中选择对象,并将它们拖放到一个特定的位置:
The objects can be one to three times the size of a slot. So if a user drags Object 1 to Slot 0, then it only occupies Slot 0 (startSlot = 0 and endSlot = 0). However if a user drags Object 3 to Slot 3, then it occupies Slots 3, 4, and 5 (startSlot = 3 and endSlot = 5).
对象的大小可以是一个槽的一到三倍。因此,如果用户将对象1拖动到槽0,那么它只占用槽0 (startSlot = 0, endSlot = 0),但是如果用户将对象3拖动到槽3,那么它将占用槽3、4和5 (startSlot = 3, endSlot = 5)。
Once the objects are dropped into the slots, a user can reorder the objects by clicking and dragging the objects up and down in the slots. Objects cannot overlap each other:
一旦对象被放入槽中,用户就可以通过单击并在槽中上下拖动对象来重新排序对象。物体之间不能重叠:
I am using Angular, so I'm reading a list of objects from a database and I have a variable for the number of slots. I have attempted a couple of solutions. I believe the use of jQuery and jQueryUI draggable, droppable, and sortable is part of the solution, here is the first fiddle demonstrating drag/drop and sortable:
我用的是角,所以我从数据库中读取一个对象列表我有一个槽数的变量。我尝试了一些解决方案。我认为使用jQuery和jQueryUI可拖放、可拖放和可排序是解决方案的一部分,这里是演示拖放和可排序的第一根小提琴:
http://jsfiddle.net/mduvall216/6hfuzvws/4/
The problem with this fiddle is that I need a set number of slots. Once an object is placed in the slots, it replaces 1 to 3 slots depending on the size of the object. The second fiddle below integrates AngularJS:
这个小提琴的问题是我需要一组插槽。一旦一个对象被放在槽中,它将根据对象的大小替换1到3个槽。第二小提琴整合了AngularJS:
http://jsfiddle.net/mduvall216/zg5x4b6k/4/
The problem here is that I know I need some type of grid to snap the objects to once dragged from the object list. The result that I'm looking for is a json list of objects in their assigned slots:
这里的问题是,我知道我需要某种类型的网格来将对象从对象列表中拖出。我正在寻找的结果是一个json列表,其中列出了分配的槽中的对象:
[{id:obj1,startSlot:0,endSlot:0},{id:obj3,startSlot:3,endSlot:5}]
[{ id:其中obj1 startSlot:0,endSlot:0 },{ id:obj3 startSlot:3,endSlot:5 }]
I'm also sure the solution would need codf0rmer's Angular Drag-Drop located here:
我也确定解决方案需要codf0rmer的角拖拽位于这里:
https://github.com/codef0rmer/angular-dragdrop
But I'm having problems trying to get that integrated into my fiddle to test. This is an interesting challenge I've been spinning on for a while, if anyone can be of assistance it would be greatly appreciated. Thanks for your time.
但是我在把它整合到我的提琴上测试时遇到了问题。这是一个很有趣的挑战,我已经进行了一段时间了,如果有人能帮忙的话,我会非常感激。谢谢你的时间。
1 个解决方案
#1
5
I started a basic implementation of your requirements using the HTML5 Drag & Drop API and jQuery. The API is lightweight and doesn't require any 3rd party scripts. The code should be easy to customize. The provided example is only a starting point and by no means production ready and should be optimized and possibly turned into a jQuery plugin module before use. This would increase the re-usability of the module.
我使用HTML5拖放API和jQuery开始了您的需求的基本实现。该API是轻量级的,不需要任何第三方脚本。代码应该很容易自定义。所提供的示例只是一个起点,并不意味着已经准备好了产品,应该在使用之前进行优化,并可能将其转换为jQuery插件模块。这将增加模块的可重用性。
Leave any further questions about the code in the comments.
在评论中留下任何关于代码的问题。
JSFiddle Example without sortable:
JSFiddle没有合适的例子:
JSFiddle with sortable
JSFiddle与合适的
html:
html:
<ul class="select-list">
<li class="header">Object List</li>
<li data-slots="1" class="s1">Object 1</li>
<li data-slots="2" class="s2">Object 2</li>
<li data-slots="3" class="s3">Object 3</li>
</ul>
<ul class="drop-list" id="sortable">
<li>Slot 1</li>
<li>Slot 2</li>
<li>Slot 3</li>
<li>Slot 4</li>
<li>Slot 5</li>
<li>Slot 6</li>
<li>Slot 7</li>
<li>Slot 8</li>
<li>Slot 9</li>
<li>Slot 10</li>
<li>Slot 11</li>
<li>Slot 12</li>
<li>Slot 13</li>
</ul>
javascript without sortable:
javascript没有合适的:
(function ($, undefined) {
// document ready function
$(function () {
init();
$('ul.select-list').on({
'dragstart': dragstart,
'dragend': dragend
}, 'li');
$('ul.drop-list').on({
'dragenter dragover': dragover,
'dragleave': dragleave,
'drop': drop
}, 'li.dropzone');
});
// Initializes the lists
function init() {
$('ul.select-list').find('li').not('[class="header"]').each(function () {
var height = getSlotHeight() * $(this).data('slots');
$(this).height(height);
}).attr('draggable', true);
$('ul.drop-list').find('li').each(function () {
$(this).height(getSlotHeight());
}).addClass('dropzone');
}
// Get the height of grid slots
function getSlotHeight() {
return 20;
}
/**
* Checks whether target is a kompatible dropzone
* A dropzone needs the dropzone class
* and needs to have enough consequent slots to drop the object into
*/
function isDropZone(target, draggedObj) {
var isDropZone = true;
var slots = draggedObj.data('slots');
for (var i = 1; i < slots; i++) {
target = target.next();
if (target.size() == 0 || !target.hasClass('dropzone')) {
isDropZone = false;
break;
}
}
return isDropZone;
}
/*
* The following events are executed in the order the handlers are declared
* dragstart being first and dragend being last
*/
// dragstart event handler
function dragstart(e) {
e.stopPropagation();
var dt = e.originalEvent.dataTransfer;
dt.effectAllowed = 'move';
dt.setData('text/html', '');
$('ul.select-list').data({
draggedObj: $(this)
});
}
// dragover event handler
function dragover(e) {
e.preventDefault();
e.stopPropagation();
var data = $('ul.select-list').data();
if (!data.draggedObj || !isDropZone($(this), data.draggedObj)) {
e.originalEvent.dataTransfer.dropEffect = 'none';
return;
}
e.originalEvent.dataTransfer.dropEffect = 'move';
var item = $(this).addClass('dragover');
var slots = data.draggedObj.data('slots');
for (var i = 1; i < slots; i++) {
item = item.next('li').addClass('dragover');
}
return false;
}
// dragleave event handler
function dragleave(e) {
e.preventDefault();
e.stopPropagation();
var data = $('ul.select-list').data();
if (!data.draggedObj || !isDropZone($(this), data.draggedObj)) {
return;
}
var item = $(this).removeClass('dragover');
var slots = data.draggedObj.data('slots');
for (var i = 1; i < slots; i++) {
item = item.next('li').removeClass('dragover');
}
return false;
}
// drop event handler
function drop(e) {
e.stopPropagation();
e.preventDefault();
var data = $('ul.select-list').data();
if (data.draggedObj || !isDropZone($(this), data.draggedObj)) {
data.target = $(this);
data.draggedObj.trigger('dragend');
}
return false;
}
// dragend event handler
function dragend(e) {
var data = $('ul.select-list').data();
if (data.draggedObj && data.target && isDropZone(data.target, data.draggedObj)) {
var item = data.target.hide();
var slots = data.draggedObj.data('slots');
for (var i = 1; i < slots; i++) {
item = item.next('li').hide();
}
data.target.before(data.draggedObj);
}
data.target = undefined;
data.draggedObj = undefined;
$('ul.drop-list').find('li').removeClass('dragover');
}
}(jQuery));
css:
css:
ul {
list-style-type: none;
margin: 0;
padding: 0;
float: left;
}
li {
width: 150px;
}
li.header {
height:20px;
font-weight:bold;
}
.select-list li {
margin-bottom: 10px;
}
.drop-list {
margin-left:20px;
}
.drop-list li {
background-color: #ccc;
border-left: 1px solid black;
border-right: 1px solid black;
border-top: 1px solid black;
}
.drop-list li.dragover {
background-color:#fff;
}
.drop-list li:last-child {
border-bottom: 1px solid black;
}
li.s1 {
background-color: #FFE5E5;
}
li.s2 {
background-color: #C6D4FF;
}
li.s3 {
background-color: #C6FFE3;
}
Edit: The following script also has sorting added to it. I have not stress tested this example and it may not perform under certain conditions.
编辑:下面的脚本还添加了排序。我还没有对这个例子进行过压力测试,它在某些条件下可能无法执行。
(function ($, undefined) {
// document ready function
$(function () {
init();
$('ul.select-list,ul.drop-list').on({
'dragstart': dragstart,
'dragend': dragend
}, 'li.object').on('dragenter dragover', listDragover);
$('ul.drop-list').on({
'dragenter dragover': dragover,
'dragleave': dragleave,
'drop': drop
}, 'li.dropzone');
});
// Initializes the lists
function init() {
$('ul.select-list').find('li').not('[class="header"]').each(function () {
var height = getSlotHeight() * $(this).data('slots');
$(this).height(height);
}).attr('draggable', true).addClass('object');
$('ul.drop-list').find('li').each(function () {
$(this).height(getSlotHeight());
}).addClass('dropzone');
}
// Get the height of the grid
function getSlotHeight() {
return 20;
}
/**
* Checks whether target is a kompatible dropzone
* A dropzone needs the dropzone class
* and needs to have enough consequent slots to drop the object into
*/
function isDropZone(target, draggedObj) {
var isDropZone = true;
var slots = draggedObj.data('slots');
for (var i = 1; i < slots; i++) {
target = target.next('li');
if (target.size() == 0 || !target.hasClass('dropzone')) {
if (!target.is(draggedObj)) {
isDropZone = false;
break;
} else {
i--;
}
}
}
return isDropZone;
}
// dragstart event handler
function dragstart(e) {
e.stopPropagation();
var dt = e.originalEvent.dataTransfer;
dt.effectAllowed = 'move';
dt.setData('text/html', '');
$('ul.select-list').data({
draggedObj: $(this)
});
}
// dragover list event handler
function listDragover(e) {
e.preventDefault();
e.stopPropagation();
e.originalEvent.dataTransfer.dropEffect = 'none';
var data = $('ul.select-list').data();
if (data.draggedObj) {
var item = data.draggedObj;
item.hide();
if (data.draggedObj.closest('ul').is('ul.drop-list')) {
var slots = item.data('slots');
for (var i = 0; i < slots; i++) {
item = item.next('li').show();
}
}
}
return false;
}
// dragover event handler
function dragover(e) {
e.preventDefault();
e.stopPropagation();
var data = $('ul.select-list').data();
if (!data.draggedObj || !isDropZone($(this), data.draggedObj)) {
e.originalEvent.dataTransfer.dropEffect = 'none';
return;
}
e.originalEvent.dataTransfer.dropEffect = 'move';
var item = $(this).addClass('dragover');
var slots = data.draggedObj.data('slots');
for (var i = 1; i < slots; i++) {
item = item.next('li');
if (!item.is(data.draggedObj)) {
item.addClass('dragover');
} else {
i--;
}
}
return false;
}
// dragleave event handler
function dragleave(e) {
e.preventDefault();
e.stopPropagation();
var data = $('ul.select-list').data();
if (!data.draggedObj || !isDropZone($(this), data.draggedObj)) {
return;
}
var item = $(this).removeClass('dragover');
var slots = data.draggedObj.data('slots');
for (var i = 1; i < slots; i++) {
item = item.next('li');
if (!item.is(data.draggedObj)) {
item.removeClass('dragover');
} else {
i--;
}
}
return false;
}
// drop event handler
function drop(e) {
e.stopPropagation();
e.preventDefault();
var data = $('ul.select-list').data();
if (data.draggedObj || !isDropZone($(this), data.draggedObj)) {
data.target = $(this);
data.draggedObj.trigger('dragend');
}
return false;
}
// dragend event handler
function dragend(e) {
var data = $('ul.select-list').data();
var target = data.target;
if (data.draggedObj && !target && data.draggedObj.closest('ul').is('ul.drop-list')) {
target = data.draggedObj.next('li');
}
if (data.draggedObj && target && isDropZone(target, data.draggedObj)) {
data.draggedObj = data.draggedObj.insertBefore(target);
var item = target.hide();
var slots = data.draggedObj.data('slots');
for (var i = 1; i < slots; i++) {
item = item.next('li').hide();
}
}
if (data.draggedObj) {
data.draggedObj.show();
}
data.target = undefined;
data.draggedObj = undefined;
$('ul.drop-list').find('li').removeClass('dragover');
}
}(jQuery));
更多相关文章
- 美元。针对简单的php, post返回对象
- 将JavaScript对象作为Dictionary 传递给C#WCF服务
- 通过],[和创建json对象来分割字符串
- 我通过jQuery-ajax创建了__PHP_Incomplete_Class对象此错误
- 如何从Python脚本向jQuery发送JSON对象?
- jQuery 事件绑定方法(bind hover toggle live.... )、删除事件方法
- jQuery:在对象内使用.remove()而不是Regex
- ajax回调json数组对象,jquery中$.each()循环解析
- 触发具有相同类的另一个对象以使用计时器淡出