ExtJS4 拖放[drag and drop]

定义拖放

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

Ext Drag and Drop

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

 

拖放类的组织

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

Ext Drag and Drop

 

 

手头的任务

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

Ext Drag and Drop

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

Step 1: 开始拖动

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

 

[javascript][/javascript] view plaincopy

  1. Ext.onReady(function() {
  2.     // Create an object that we’ll use to implement and override drag behaviors a little later
  3.     var overrides = {};
  4.     // Configure the cars to be draggable
  5.     var carElements = Ext.get(‘cars’).select(‘div’);
  6.     Ext.each(carElements.elements, function(el) {
  7.         var dd = Ext.create(‘Ext.dd.DD’, el, ‘carsDDGroup’, {
  8.             isTarget  : false
  9.         });
  10.         //Apply the overrides object to the newly created instance of DD
  11.         Ext.apply(dd, overrides);
  12.     });
  13.     var truckElements = Ext.get(‘trucks’).select(‘div’);
  14.     Ext.each(truckElements.elements, function(el) {
  15.         var dd = Ext.create(‘Ext.dd.DD’, el, ‘trucksDDGroup’, {
  16.             isTarget  : false
  17.         });
  18.         Ext.apply(dd, overrides);
  19.     });
  20. });

 

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

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

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

 

看一下拖动效果的实质

Ext Drag and Drop

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

 

Step 2: 修复无效的拖放

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

 

[javascript][/javascript] view plaincopy

  1. var overrides = {
  2.     // Called the instance the element is dragged.
  3.     b4StartDrag : function() {
  4.         // Cache the drag element
  5.         if (!this.el) {
  6.             this.el = Ext.get(this.getEl());
  7.         }
  8.         //Cache the original XY Coordinates of the element, we’ll use this later.
  9.         this.originalXY = this.el.getXY();
  10.     },
  11.     // Called when element is dropped not anything other than a dropzone with the same ddgroup
  12.     onInvalidDrop : function() {
  13.         // Set a flag to invoke the animated repair
  14.         this.invalidDrop = true;
  15.     },
  16.     // Called when the drag operation completes
  17.     endDrag : function() {
  18.         // Invoke the animation if the invalidDrop flag is set to true
  19.         if (this.invalidDrop === true) {
  20.             // Remove the drop invitation
  21.             this.el.removeCls(‘dropOK’);
  22.             // Create the animation configuration object
  23.             var animCfgObj = {
  24.                 easing   : ‘elasticOut’,
  25.                 duration : 1,
  26.                 scope    : this,
  27.                 callback : function() {
  28.                     // Remove the position attribute
  29.                     this.el.dom.style.position = ”;
  30.                 }
  31.             };
  32.             // Apply the repair animation
  33.             this.el.moveTo(this.originalXY[0], this.originalXY[1], animCfgObj);
  34.             delete this.invalidDrop;
  35.         }
  36.     },

效果:

 

Ext Drag and Drop

 

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

 

[javascript][/javascript] view plaincopy

  1. // Instantiate instances of Ext.dd.DDTarget for the cars and trucks container
  2. var carsDDTarget = Ext.create(‘Ext.dd.DDTarget’, ‘cars’,’carsDDGroup’);
  3. var trucksDDTarget = Ext.create(‘Ext.dd.DDTarget’, ‘trucks’, ‘trucksDDGroup’);
  4. // Instantiate instnaces of DDTarget for the rented and repair drop target elements
  5. var rentedDDTarget = Ext.create(‘Ext.dd.DDTarget’, ‘rented’, ‘carsDDGroup’);
  6. var repairDDTarget = Ext.create(‘Ext.dd.DDTarget’, ‘repair’, ‘carsDDGroup’);
  7. // Ensure that the rented and repair DDTargets will participate in the trucksDDGroup
  8. rentedDDTarget.addToGroup(‘trucksDDGroup’);
  9. repairDDTarget.addToGroup(‘trucksDDGroup’);

 

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

效果:

Ext Drag and Drop

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

 Step 4: 继续 完成Drop

 

[javascript][/javascript] view plaincopy

  1. var overrides = {
  2.     …
  3.     // Called upon successful drop of an element on a DDTarget with the same
  4.     onDragDrop : function(evtObj, targetElId) {
  5.         // Wrap the drop target element with Ext.Element
  6.         var dropEl = Ext.get(targetElId);
  7.         // Perform the node move only if the drag element’s
  8.         // parent is not the same as the drop target
  9.         if (this.el.dom.parentNode.id != targetElId) {
  10.             // Move the element
  11.             dropEl.appendChild(this.el);
  12.             // Remove the drag invitation
  13.             this.onDragOut(evtObj, targetElId);
  14.             // Clear the styles
  15.             this.el.dom.style.position =”;
  16.             this.el.dom.style.top = ”;
  17.             this.el.dom.style.left = ”;
  18.         }
  19.         else {
  20.             // This was an invalid drop, initiate a repair
  21.             this.onInvalidDrop();
  22.         }
  23.     },

Ext Drag and Drop

 

 

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

重写onDragEnter 和onDragOut 方法。

 

[javascript][/javascript] view plaincopy

  1. var overrides = {
  2.     …
  3.     // Only called when the drag element is dragged over the a drop target with the same ddgroup
  4.     onDragEnter : function(evtObj, targetElId) {
  5.         // Colorize the drag target if the drag node’s parent is not the same as the drop target
  6.         if (targetElId != this.el.dom.parentNode.id) {
  7.             this.el.addCls(‘dropOK’);
  8.         }
  9.         else {
  10.             // Remove the invitation
  11.             this.onDragOut();
  12.         }
  13.     },
  14.     // Only called when element is dragged out of a dropzone with the same ddgroup
  15.     onDragOut : function(evtObj, targetElId) {
  16.         this.el.removeCls(‘dropOK’);
  17.     }
  18. };

Ext Drag and Drop

标签