ViewDropZone2.html 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-tree-ViewDropZone'>/**
  19. </span> * @private
  20. */
  21. Ext.define('Ext.tree.ViewDropZone', {
  22. extend: 'Ext.view.DropZone',
  23. <span id='Ext-tree-ViewDropZone-cfg-allowParentInsert'> /**
  24. </span> * @cfg {Boolean} allowParentInsert
  25. * Allow inserting a dragged node between an expanded parent node and its first child that will become a
  26. * sibling of the parent when dropped.
  27. */
  28. allowParentInserts: false,
  29. <span id='Ext-tree-ViewDropZone-cfg-allowContainerDrop'> /**
  30. </span> * @cfg {String} allowContainerDrop
  31. * True if drops on the tree container (outside of a specific tree node) are allowed.
  32. */
  33. allowContainerDrops: false,
  34. <span id='Ext-tree-ViewDropZone-cfg-appendOnly'> /**
  35. </span> * @cfg {String} appendOnly
  36. * True if the tree should only allow append drops (use for trees which are sorted).
  37. */
  38. appendOnly: false,
  39. <span id='Ext-tree-ViewDropZone-cfg-expandDelay'> /**
  40. </span> * @cfg {String} expandDelay
  41. * The delay in milliseconds to wait before expanding a target tree node while dragging a droppable node
  42. * over the target.
  43. */
  44. expandDelay : 500,
  45. indicatorCls: Ext.baseCSSPrefix + 'tree-ddindicator',
  46. // private
  47. expandNode : function(node) {
  48. var view = this.view;
  49. if (!node.isLeaf() &amp;&amp; !node.isExpanded()) {
  50. view.expand(node);
  51. this.expandProcId = false;
  52. }
  53. },
  54. // private
  55. queueExpand : function(node) {
  56. this.expandProcId = Ext.Function.defer(this.expandNode, this.expandDelay, this, [node]);
  57. },
  58. // private
  59. cancelExpand : function() {
  60. if (this.expandProcId) {
  61. clearTimeout(this.expandProcId);
  62. this.expandProcId = false;
  63. }
  64. },
  65. getPosition: function(e, node) {
  66. var view = this.view,
  67. record = view.getRecord(node),
  68. y = e.getPageY(),
  69. noAppend = record.isLeaf(),
  70. noBelow = false,
  71. region = Ext.fly(node).getRegion(),
  72. fragment;
  73. // If we are dragging on top of the root node of the tree, we always want to append.
  74. if (record.isRoot()) {
  75. return 'append';
  76. }
  77. // Return 'append' if the node we are dragging on top of is not a leaf else return false.
  78. if (this.appendOnly) {
  79. return noAppend ? false : 'append';
  80. }
  81. if (!this.allowParentInsert) {
  82. noBelow = record.hasChildNodes() &amp;&amp; record.isExpanded();
  83. }
  84. fragment = (region.bottom - region.top) / (noAppend ? 2 : 3);
  85. if (y &gt;= region.top &amp;&amp; y &lt; (region.top + fragment)) {
  86. return 'before';
  87. }
  88. else if (!noBelow &amp;&amp; (noAppend || (y &gt;= (region.bottom - fragment) &amp;&amp; y &lt;= region.bottom))) {
  89. return 'after';
  90. }
  91. else {
  92. return 'append';
  93. }
  94. },
  95. isValidDropPoint : function(node, position, dragZone, e, data) {
  96. if (!node || !data.item) {
  97. return false;
  98. }
  99. var view = this.view,
  100. targetNode = view.getRecord(node),
  101. draggedRecords = data.records,
  102. dataLength = draggedRecords.length,
  103. ln = draggedRecords.length,
  104. i, record;
  105. // No drop position, or dragged records: invalid drop point
  106. if (!(targetNode &amp;&amp; position &amp;&amp; dataLength)) {
  107. return false;
  108. }
  109. // If the targetNode is within the folder we are dragging
  110. for (i = 0; i &lt; ln; i++) {
  111. record = draggedRecords[i];
  112. if (record.isNode &amp;&amp; record.contains(targetNode)) {
  113. return false;
  114. }
  115. }
  116. // Respect the allowDrop field on Tree nodes
  117. if (position === 'append' &amp;&amp; targetNode.get('allowDrop') === false) {
  118. return false;
  119. }
  120. else if (position != 'append' &amp;&amp; targetNode.parentNode.get('allowDrop') === false) {
  121. return false;
  122. }
  123. // If the target record is in the dragged dataset, then invalid drop
  124. if (Ext.Array.contains(draggedRecords, targetNode)) {
  125. return false;
  126. }
  127. // @TODO: fire some event to notify that there is a valid drop possible for the node you're dragging
  128. // Yes: this.fireViewEvent(blah....) fires an event through the owning View.
  129. return true;
  130. },
  131. onNodeOver : function(node, dragZone, e, data) {
  132. var position = this.getPosition(e, node),
  133. returnCls = this.dropNotAllowed,
  134. view = this.view,
  135. targetNode = view.getRecord(node),
  136. indicator = this.getIndicator(),
  137. indicatorX = 0,
  138. indicatorY = 0;
  139. // auto node expand check
  140. this.cancelExpand();
  141. if (position == 'append' &amp;&amp; !this.expandProcId &amp;&amp; !Ext.Array.contains(data.records, targetNode) &amp;&amp; !targetNode.isLeaf() &amp;&amp; !targetNode.isExpanded()) {
  142. this.queueExpand(targetNode);
  143. }
  144. if (this.isValidDropPoint(node, position, dragZone, e, data)) {
  145. this.valid = true;
  146. this.currentPosition = position;
  147. this.overRecord = targetNode;
  148. indicator.setWidth(Ext.fly(node).getWidth());
  149. indicatorY = Ext.fly(node).getY() - Ext.fly(view.el).getY() - 1;
  150. /*
  151. * In the code below we show the proxy again. The reason for doing this is showing the indicator will
  152. * call toFront, causing it to get a new z-index which can sometimes push the proxy behind it. We always
  153. * want the proxy to be above, so calling show on the proxy will call toFront and bring it forward.
  154. */
  155. if (position == 'before') {
  156. returnCls = targetNode.isFirst() ? Ext.baseCSSPrefix + 'tree-drop-ok-above' : Ext.baseCSSPrefix + 'tree-drop-ok-between';
  157. indicator.showAt(0, indicatorY);
  158. dragZone.proxy.show();
  159. } else if (position == 'after') {
  160. returnCls = targetNode.isLast() ? Ext.baseCSSPrefix + 'tree-drop-ok-below' : Ext.baseCSSPrefix + 'tree-drop-ok-between';
  161. indicatorY += Ext.fly(node).getHeight();
  162. indicator.showAt(0, indicatorY);
  163. dragZone.proxy.show();
  164. } else {
  165. returnCls = Ext.baseCSSPrefix + 'tree-drop-ok-append';
  166. // @TODO: set a class on the parent folder node to be able to style it
  167. indicator.hide();
  168. }
  169. } else {
  170. this.valid = false;
  171. }
  172. this.currentCls = returnCls;
  173. return returnCls;
  174. },
  175. onContainerOver : function(dd, e, data) {
  176. return e.getTarget('.' + this.indicatorCls) ? this.currentCls : this.dropNotAllowed;
  177. },
  178. notifyOut: function() {
  179. this.callParent(arguments);
  180. this.cancelExpand();
  181. },
  182. handleNodeDrop : function(data, targetNode, position) {
  183. var me = this,
  184. view = me.view,
  185. parentNode = targetNode.parentNode,
  186. store = view.getStore(),
  187. recordDomNodes = [],
  188. records, i, len,
  189. insertionMethod, argList,
  190. needTargetExpand,
  191. transferData,
  192. processDrop;
  193. // If the copy flag is set, create a copy of the Models with the same IDs
  194. if (data.copy) {
  195. records = data.records;
  196. data.records = [];
  197. for (i = 0, len = records.length; i &lt; len; i++) {
  198. data.records.push(Ext.apply({}, records[i].data));
  199. }
  200. }
  201. // Cancel any pending expand operation
  202. me.cancelExpand();
  203. // Grab a reference to the correct node insertion method.
  204. // Create an arg list array intended for the apply method of the
  205. // chosen node insertion method.
  206. // Ensure the target object for the method is referenced by 'targetNode'
  207. if (position == 'before') {
  208. insertionMethod = parentNode.insertBefore;
  209. argList = [null, targetNode];
  210. targetNode = parentNode;
  211. }
  212. else if (position == 'after') {
  213. if (targetNode.nextSibling) {
  214. insertionMethod = parentNode.insertBefore;
  215. argList = [null, targetNode.nextSibling];
  216. }
  217. else {
  218. insertionMethod = parentNode.appendChild;
  219. argList = [null];
  220. }
  221. targetNode = parentNode;
  222. }
  223. else {
  224. if (!targetNode.isExpanded()) {
  225. needTargetExpand = true;
  226. }
  227. insertionMethod = targetNode.appendChild;
  228. argList = [null];
  229. }
  230. // A function to transfer the data into the destination tree
  231. transferData = function() {
  232. var node,
  233. r, rLen, color, n;
  234. for (i = 0, len = data.records.length; i &lt; len; i++) {
  235. argList[0] = data.records[i];
  236. node = insertionMethod.apply(targetNode, argList);
  237. if (Ext.enableFx &amp;&amp; me.dropHighlight) {
  238. recordDomNodes.push(view.getNode(node));
  239. }
  240. }
  241. // Kick off highlights after everything's been inserted, so they are
  242. // more in sync without insertion/render overhead.
  243. if (Ext.enableFx &amp;&amp; me.dropHighlight) {
  244. //FIXME: the check for n.firstChild is not a great solution here. Ideally the line should simply read
  245. //Ext.fly(n.firstChild) but this yields errors in IE6 and 7. See ticket EXTJSIV-1705 for more details
  246. rLen = recordDomNodes.length;
  247. color = me.dropHighlightColor;
  248. for (r = 0; r &lt; rLen; r++) {
  249. n = recordDomNodes[r];
  250. if (n) {
  251. Ext.fly(n.firstChild ? n.firstChild : n).highlight(color);
  252. }
  253. }
  254. }
  255. };
  256. // If dropping right on an unexpanded node, transfer the data after it is expanded.
  257. if (needTargetExpand) {
  258. targetNode.expand(false, transferData);
  259. }
  260. // Otherwise, call the data transfer function immediately
  261. else {
  262. transferData();
  263. }
  264. }
  265. });</pre>
  266. </body>
  267. </html>