Draggable.js 6.4 KB

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