[Ext JS 4] 拖放[drag and drop]

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/oscar999/article/details/9561883

定义拖放

一个拖动操作,就是在某个页面元素上按下鼠标并移动。一个放下操作,就是在拖动动作之后放开鼠标。可以从下图来看:

Ext Drag and Drop

Ext JS 的Ext.dd 类中定义了基本的拖放操作。


拖放类的组织

所有的拖放类基本上都归类到Drag or  Drop 组中

Ext Drag and Drop



手头的任务

这里的例子是一个租车公司,把轿车和卡车有三种状态: 闲置,租用和修理。该应用就是可以在这三个状态格之间拖动车辆。

Ext Drag and Drop

使用DD,让可选轿车和卡车可以拖动; 而后,使用 DDTarget,让租车和修理的容器可以接受拖放;最后使用不同的拖放组让轿车和卡车只能拖到指定的区块。

Step 1: 开始拖动

让以上可选的轿车和卡车可以拖动:

Ext.onReady(function() {
    // Create an object that we'll use to implement and override drag behaviors a little later
    var overrides = {};

    // Configure the cars to be draggable
    var carElements = Ext.get('cars').select('div');
    Ext.each(carElements.elements, function(el) {
        var dd = Ext.create('Ext.dd.DD', el, 'carsDDGroup', {
            isTarget  : false
        });
        //Apply the overrides object to the newly created instance of DD
        Ext.apply(dd, overrides);
    });

    var truckElements = Ext.get('trucks').select('div');
    Ext.each(truckElements.elements, function(el) {
        var dd = Ext.create('Ext.dd.DD', el, 'trucksDDGroup', {
            isTarget  : false
        });
        Ext.apply(dd, overrides);
    });
}); 

以上使用DomQuery的方式找到需要拖动的区块,并针对里面的子元素创建了DD的实例。

对于轿车和卡车用了不同的分组。(可以拖放的位置不同)

这里定义了一个空的对象 overrides, 并且把这个对象通过Ext.apply应用到创建的 DD 的对象上。


看一下拖动效果的实质

Ext Drag and Drop

从以上可以看出, 一个元素有三个CSS的属性; position, top 和 left;


Step 2: 修复无效的拖放

最简单的修复方式就是,拖动失败之后让样式恢复到拖动前的状况,这样的处理看起来有点枯燥,所以,可以用Ext.Fx 添加动画的效果。还记得拖放类的设计有overridden 的方法,要实现这个效果,需要覆写b4StartDrag, onInvalidDrop 和endDrag这些方法。看下例:

var overrides = {
    // Called the instance the element is dragged.
    b4StartDrag : function() {
        // Cache the drag element
        if (!this.el) {
            this.el = Ext.get(this.getEl());
        }

        //Cache the original XY Coordinates of the element, we'll use this later.
        this.originalXY = this.el.getXY();
    },
    // Called when element is dropped not anything other than a dropzone with the same ddgroup
    onInvalidDrop : function() {
        // Set a flag to invoke the animated repair
        this.invalidDrop = true;
    },
    // Called when the drag operation completes
    endDrag : function() {
        // Invoke the animation if the invalidDrop flag is set to true
        if (this.invalidDrop === true) {
            // Remove the drop invitation
            this.el.removeCls('dropOK');

            // Create the animation configuration object
            var animCfgObj = {
                easing   : 'elasticOut',
                duration : 1,
                scope    : this,
                callback : function() {
                    // Remove the position attribute
                    this.el.dom.style.position = '';
                }
            };

            // Apply the repair animation
            this.el.moveTo(this.originalXY[0], this.originalXY[1], animCfgObj);
            delete this.invalidDrop;
        }
    },

效果:

Ext Drag and Drop


step 3: 配置放下的目标(drop targets)

// Instantiate instances of Ext.dd.DDTarget for the cars and trucks container
var carsDDTarget = Ext.create('Ext.dd.DDTarget', 'cars','carsDDGroup');
var trucksDDTarget = Ext.create('Ext.dd.DDTarget', 'trucks', 'trucksDDGroup');

// Instantiate instnaces of DDTarget for the rented and repair drop target elements
var rentedDDTarget = Ext.create('Ext.dd.DDTarget', 'rented', 'carsDDGroup');
var repairDDTarget = Ext.create('Ext.dd.DDTarget', 'repair', 'carsDDGroup');

// Ensure that the rented and repair DDTargets will participate in the trucksDDGroup
rentedDDTarget.addToGroup('trucksDDGroup');
repairDDTarget.addToGroup('trucksDDGroup');

这里代码为 轿车,卡车,租赁和修理的区块添加了drop targets. 轿车容器仅接收"carsDDGroup" 的drag, 卡车容器仅接收“trucksDDGroup”;
接着定义了rentedDDTarget 和repairDDTarget并且只接收 “carsDDGroup”, 为了让“trucksDDGroup”也可以,通过 addToGroup  方式进行添加。

效果:

Ext Drag and Drop

以上的拖放可以拖放到指定位置,可能出现重叠等问题。

 Step 4: 继续 完成Drop

var overrides = {
    ...
    // Called upon successful drop of an element on a DDTarget with the same
    onDragDrop : function(evtObj, targetElId) {
        // Wrap the drop target element with Ext.Element
        var dropEl = Ext.get(targetElId);

        // Perform the node move only if the drag element's
        // parent is not the same as the drop target
        if (this.el.dom.parentNode.id != targetElId) {

            // Move the element
            dropEl.appendChild(this.el);

            // Remove the drag invitation
            this.onDragOut(evtObj, targetElId);

            // Clear the styles
            this.el.dom.style.position ='';
            this.el.dom.style.top = '';
            this.el.dom.style.left = '';
        }
        else {
            // This was an invalid drop, initiate a repair
            this.onInvalidDrop();
        }
    },
Ext Drag and Drop


Step 5 : 添加放下邀请(Drop Invitation)
当拖放操作完成时,添加一些反馈信息给用户。

重写onDragEnter 和onDragOut 方法。

var overrides = {
    ...
    // Only called when the drag element is dragged over the a drop target with the same ddgroup
    onDragEnter : function(evtObj, targetElId) {
        // Colorize the drag target if the drag node's parent is not the same as the drop target
        if (targetElId != this.el.dom.parentNode.id) {
            this.el.addCls('dropOK');
        }
        else {
            // Remove the invitation
            this.onDragOut();
        }
    },
    // Only called when element is dragged out of a dropzone with the same ddgroup
    onDragOut : function(evtObj, targetElId) {
        this.el.removeCls('dropOK');
    }
};
Ext Drag and Drop



阅读更多

没有更多推荐了,返回首页