首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将AngularJS、jQueryUI、角拖放相结合用于排序列表

将AngularJS、jQueryUI、角拖放相结合用于排序列表
EN

Stack Overflow用户
提问于 2015-11-03 16:39:52
回答 1查看 957关注 0票数 5

在以下情况下,我需要允许用户从列表中选择对象并将其拖放到特定的插槽中:

对象可以是插槽大小的一到三倍。因此,如果用户将对象1拖到槽0,那么它只占据槽0 (startSlot =0和endSlot = 0)。但是,如果用户将对象3拖到槽3,则占用槽3、4和5 (startSlot =3和endSlot = 5)。

一旦将对象放置到插槽中,用户就可以通过单击和拖拽插槽中的对象来重新排序对象。对象不能相互重叠:

我使用的是角度,所以我从数据库中读取了一个对象列表,并且我有一个变量来表示插槽的数量。我已经尝试了几种解决方案。我认为jQuery和jQueryUI的使用是解决方案的一部分,它是可拖动、可下垂和可排序的解决方案的一部分,这里是演示拖放和排序的第一小提琴:

代码语言:javascript
复制
http://jsfiddle.net/mduvall216/6hfuzvws/4/

这个小提琴的问题是,我需要一个固定数目的插槽。一旦将一个对象放置在插槽中,它就会根据对象的大小替换1到3个插槽。下面的第二把手集成了AngularJS:

代码语言:javascript
复制
http://jsfiddle.net/mduvall216/zg5x4b6k/4/

这里的问题是,我知道我需要某种类型的网格来抓取对象,以便一旦从对象列表中拖动。我正在寻找的结果是在它们指定的插槽中的对象的json列表:

{id:obj3 1,startSlot:0,endSlot:0},{id:obj3 3,startSlot:3,endSlot:5}

我还确信解决方案将需要cof0rmer的角拖拽位于以下位置:

代码语言:javascript
复制
https://github.com/codef0rmer/angular-dragdrop

但我很难把它整合到我的小提琴里去测试。这是一个有趣的挑战,我一直在旋转一段时间,如果有人可以帮助,这将是非常感谢。耽误您时间,实在对不起。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-11-08 03:18:39

我使用HTML5拖放API和jQuery开始了您的需求的基本实现。API是轻量级的,不需要任何第三方脚本。代码应该很容易定制。所提供的示例只是一个起点,根本没有准备好生产,应该在使用之前进行优化,并可能将其转换为jQuery插件模块。这将增加模块的可重用性。

在注释中保留有关代码的任何进一步问题。

没有可排序的JSFiddle示例:

可排序的JSFiddle

html:

代码语言:javascript
复制
<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:

代码语言: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:

代码语言:javascript
复制
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;
 }

编辑:下面的脚本还添加了排序。我没有强调测试这个例子,它可能无法在某些条件下执行。

代码语言:javascript
复制
(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));
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33504511

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档