Draggable.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /**
  2. * @class Ext.ux.DataView.Draggable
  3. * @extends Object
  4. * @author Ed Spencer
  5. *
  6. <pre><code>
  7. Ext.create('Ext.view.View', {
  8. mixins: {
  9. draggable: 'Ext.ux.DataView.Draggable'
  10. },
  11. initComponent: function() {
  12. this.mixins.draggable.init(this, {
  13. ddConfig: {
  14. ddGroup: 'someGroup'
  15. }
  16. });
  17. this.callParent(arguments);
  18. }
  19. });
  20. </code></pre>
  21. *
  22. */
  23. Ext.define('Ext.ux.DataView.Draggable', {
  24. requires: 'Ext.dd.DragZone',
  25. /**
  26. * @cfg {String} ghostCls The CSS class added to the outermost element of the created ghost proxy
  27. * (defaults to 'x-dataview-draggable-ghost')
  28. */
  29. ghostCls: 'x-dataview-draggable-ghost',
  30. /**
  31. * @cfg {Ext.XTemplate/Array} ghostTpl The template used in the ghost DataView
  32. */
  33. ghostTpl: [
  34. '<tpl for=".">',
  35. '{title}',
  36. '</tpl>'
  37. ],
  38. /**
  39. * @cfg {Object} ddConfig Config object that is applied to the internally created DragZone
  40. */
  41. /**
  42. * @cfg {String} ghostConfig Config object that is used to configure the internally created DataView
  43. */
  44. init: function(dataview, config) {
  45. /**
  46. * @property dataview
  47. * @type Ext.view.View
  48. * The Ext.view.View instance that this DragZone is attached to
  49. */
  50. this.dataview = dataview;
  51. dataview.on('render', this.onRender, this);
  52. Ext.apply(this, {
  53. itemSelector: dataview.itemSelector,
  54. ghostConfig : {}
  55. }, config || {});
  56. Ext.applyIf(this.ghostConfig, {
  57. itemSelector: 'img',
  58. cls: this.ghostCls,
  59. tpl: this.ghostTpl
  60. });
  61. },
  62. /**
  63. * @private
  64. * Called when the attached DataView is rendered. Sets up the internal DragZone
  65. */
  66. onRender: function() {
  67. var config = Ext.apply({}, this.ddConfig || {}, {
  68. dvDraggable: this,
  69. dataview : this.dataview,
  70. getDragData: this.getDragData,
  71. getTreeNode: this.getTreeNode,
  72. afterRepair: this.afterRepair,
  73. getRepairXY: this.getRepairXY
  74. });
  75. /**
  76. * @property dragZone
  77. * @type Ext.dd.DragZone
  78. * The attached DragZone instane
  79. */
  80. this.dragZone = Ext.create('Ext.dd.DragZone', this.dataview.getEl(), config);
  81. },
  82. getDragData: function(e) {
  83. var draggable = this.dvDraggable,
  84. dataview = this.dataview,
  85. selModel = dataview.getSelectionModel(),
  86. target = e.getTarget(draggable.itemSelector),
  87. selected, dragData;
  88. if (target) {
  89. if (!dataview.isSelected(target)) {
  90. selModel.select(dataview.getRecord(target));
  91. }
  92. selected = dataview.getSelectedNodes();
  93. dragData = {
  94. copy: true,
  95. nodes: selected,
  96. records: selModel.getSelection(),
  97. item: true
  98. };
  99. if (selected.length == 1) {
  100. dragData.single = true;
  101. dragData.ddel = target;
  102. } else {
  103. dragData.multi = true;
  104. dragData.ddel = draggable.prepareGhost(selModel.getSelection()).dom;
  105. }
  106. return dragData;
  107. }
  108. return false;
  109. },
  110. getTreeNode: function() {
  111. // console.log('test');
  112. },
  113. afterRepair: function() {
  114. this.dragging = false;
  115. var nodes = this.dragData.nodes,
  116. length = nodes.length,
  117. i;
  118. //FIXME: Ext.fly does not work here for some reason, only frames the last node
  119. for (i = 0; i < length; i++) {
  120. Ext.get(nodes[i]).frame('#8db2e3', 1);
  121. }
  122. },
  123. /**
  124. * @private
  125. * Returns the x and y co-ordinates that the dragged item should be animated back to if it was dropped on an
  126. * invalid drop target. If we're dragging more than one item we don't animate back and just allow afterRepair
  127. * to frame each dropped item.
  128. */
  129. getRepairXY: function(e) {
  130. if (this.dragData.multi) {
  131. return false;
  132. } else {
  133. var repairEl = Ext.get(this.dragData.ddel),
  134. repairXY = repairEl.getXY();
  135. //take the item's margins and padding into account to make the repair animation line up perfectly
  136. repairXY[0] += repairEl.getPadding('t') + repairEl.getMargin('t');
  137. repairXY[1] += repairEl.getPadding('l') + repairEl.getMargin('l');
  138. return repairXY;
  139. }
  140. },
  141. /**
  142. * Updates the internal ghost DataView by ensuring it is rendered and contains the correct records
  143. * @param {Array} records The set of records that is currently selected in the parent DataView
  144. * @return {Ext.view.View} The Ghost DataView
  145. */
  146. prepareGhost: function(records) {
  147. var ghost = this.createGhost(records),
  148. store = ghost.store;
  149. store.removeAll();
  150. store.add(records);
  151. return ghost.getEl();
  152. },
  153. /**
  154. * @private
  155. * Creates the 'ghost' DataView that follows the mouse cursor during the drag operation. This div is usually a
  156. * lighter-weight representation of just the nodes that are selected in the parent DataView.
  157. */
  158. createGhost: function(records) {
  159. if (!this.ghost) {
  160. var ghostConfig = Ext.apply({}, this.ghostConfig, {
  161. store: Ext.create('Ext.data.Store', {
  162. model: records[0].modelName
  163. })
  164. });
  165. this.ghost = Ext.create('Ext.view.View', ghostConfig);
  166. this.ghost.render(document.createElement('div'));
  167. }
  168. return this.ghost;
  169. }
  170. });