- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
我遇到以下情况,我需要允许用户从列表中选择对象并将它们拖/放到某个插槽中:
对象的大小可以是插槽的一到三倍。所以如果用户将 Object 1 拖到 Slot 0,那么它只占用 Slot 0(startSlot = 0 和 endSlot = 0)。但是,如果用户将对象 3 拖动到插槽 3,则它会占用插槽 3、4 和 5(startSlot = 3 和 endSlot = 5)。
将对象放入槽中后,用户可以通过在槽中单击并上下拖动对象来重新排序对象。对象不能相互重叠:
我正在使用 Angular,所以我正在从数据库中读取对象列表,并且我有一个槽数变量。我尝试了几种解决方案。我相信使用 jQuery 和 jQueryUI 可拖动、可放置和可排序是解决方案的一部分,这里是演示拖放和可排序的第一个 fiddle :
http://jsfiddle.net/mduvall216/6hfuzvws/4/
这个 fiddle 的问题是我需要一定数量的插槽。一旦一个对象被放置在插槽中,它会根据对象的大小替换 1 到 3 个插槽。下面的第二个 fiddle 集成了 AngularJS:
http://jsfiddle.net/mduvall216/zg5x4b6k/4/
这里的问题是我知道我需要某种类型的网格来捕捉从对象列表中拖出的对象。我正在寻找的结果是一个 json 列表,其中包含对象在其分配的插槽中:
[{id:obj1,startSlot:0,endSlot:0},{id:obj3,startSlot:3,endSlot:5}]
我也确信该解决方案需要位于此处的 codf0rmer 的 Angular 拖放:
https://github.com/codef0rmer/angular-dragdrop
但是我在尝试将它集成到我的 fiddle 中进行测试时遇到了问题。这是一个有趣的挑战,我已经思考了一段时间,如果有人可以提供帮助,我们将不胜感激。感谢您的宝贵时间。
最佳答案
我开始使用 HTML5 拖放 API 和 jQuery 基本实现您的要求。 API 是轻量级的,不需要任何第 3 方脚本。代码应该易于定制。提供的示例只是一个起点,绝不是生产就绪,应该进行优化,并可能在使用前将其转换为 jQuery 插件模块。这将增加模块的可重用性。
在评论中留下关于代码的任何进一步问题。
JSFiddle Example without sortable:
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:
(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:
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;
}
编辑:以下脚本还添加了排序。我没有对这个示例进行压力测试,它在某些条件下可能无法执行。
(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));
关于javascript - 结合 AngularJS、jQueryUI、Angular-Drag-Drop 排序列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33504511/
是否有在非 AngularJS 页面内初始化 AngularJS 应用程序的最佳实践方法?我正在向现有网页添加新功能,需要传入一个参数。具体来说,有一组选项卡,一个新选项卡将启动一个 Angular
找不到这两者之间的区别。 保留其中任何一个来引导我的 Angular 应用程序是否有意义? angular.bootstrap(document,['myApp']); 或者 angularAMD.b
我试图理解 Packpub 的书附带的示例 AngularJS 应用程序。 app.js文件在 client/src/app 下定义文件夹,它的模块定义看起来像 angular.module('app
Angularjs 具有用于表单验证和显示错误消息的强大基础设施。但是,我处于必须在特定场景中向用户显示警告消息的情况。这是我的简单表格的图表 该表单在两个字段上都应用了必需和模式验证。除了此验证之外
我在重试功能正常工作时遇到了一些麻烦,希望能获得一些帮助。我有一个要调用的$ resource,直到出现成功情况或超过最大重试次数为止。 我似乎遇到的问题是,在我的重试函数中,我正在调用另一个prom
我目前正在开发一个 AngularJS 应用程序,我遇到了以下障碍。 当用户提交时,我们有一个 login 页面,我们调用一个 web api 并对用户进行身份验证,我们目前正在使用 claims 身
当范围更新时,指令的属性不会改变,它们仍然保持初始值。我在这里缺少什么? HTML works great works: {{foo}} Javascript (基于首页上的 A
我正在使用 Zurb 的 Foundation 框架修改应用程序以实现响应性和 AngularJS。存在数据显示在带有 ... 的表中的错误有 是根据 Foundation 的响应规则隐藏/显示的。不
在过去的三天里,我一直在搜寻互联网,试图弄清楚当angular注意到div的宽度发生变化时如何使指令运行。 我不断看到相同的示例,说明如何实现此目标,但是它们对我不起作用,我也不知道为什么。 我回到一
我正在使用以下代码尝试汇总 在 Angular ,这在整个作品中,但是小于 0.5 的数字四舍五入为 0。我想 向上取整 每个数字到下一个整数。例如 0.02 应四舍五入为 1 {{((data.Vi
我目前正在尝试以一种能够适当扩展到企业级别的方式来组织我的 Angular 应用程序。但是我发现似乎过度依赖框架内的命名约定,并且试图避免命名冲突是一个真正的问题。 例如,当定义任何 constant
我正在阅读 AngularJS 基础知识,并且喜欢在我的页面中使用它的绑定(bind)功能。所以我可以定义可以在 View 中显示的数据,可以对数据进行更改,以便在 View 中更改它而无需担心。 在
在父 Controller 范围内,我定义了 selectedItem设置为“x”。然后在子范围内,我定义了selectedItem使用 ngModel:
关闭。这个问题需要更多 focused .它目前不接受答案。 想改进这个问题?更新问题,使其仅关注一个问题 editing this post . 5年前关闭。 Improve this questi
如果2个条件为真,我试图将一个特定的类应用于li元素,因此我编写了以下代码,但似乎无法正常工作 ng-class="{current:isActive('/'), loginStatus: false
请看看朋克。 http://plnkr.co/edit/DuTFYbLVbPkCIvRznYjG?p=preview ng-pattern regEx不适用于输入文本字段。 仅在需要验证的情况下才能正
我正在为iOS + Android构建AngularJS(1.x)和Ionic/Cordova移动应用程序。我想在登录页面上添加/创建“深层链接”,以便在我向新用户发送“确认您的电子邮件”电子邮件时,
angularjs 中服务(或工厂)的生命周期是什么,何时重新初始化? 最佳答案 当 Angular 启动时,它会将服务的构造函数附加到关联的模块上。这种情况发生一次。 angular .modu
我对 Angular 很陌生,所以希望我知道的足够多,可以问什么似乎是合理的设计问题。 我正在通过 Angular 绘制一些数据,并且正在使用 $resource。在将 Angular 引入项目之前,
我需要在我的 angular-breeze 应用程序中使用国家/地区下拉菜单,我尝试了以下操作: https://github.com/banafederico/angularjs-country-s
我是一名优秀的程序员,十分优秀!