Upgrade to ExtJS 4.0.1 - Released 05/18/2011
[extjs.git] / docs / source / ViewDropZone2.html
diff --git a/docs/source/ViewDropZone2.html b/docs/source/ViewDropZone2.html
new file mode 100644 (file)
index 0000000..4bc8fcd
--- /dev/null
@@ -0,0 +1,297 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  <title>The source code</title>
+  <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
+  <script type="text/javascript" src="../prettify/prettify.js"></script>
+  <style type="text/css">
+    .highlight { display: block; background-color: #ddd; }
+  </style>
+  <script type="text/javascript">
+    function highlight() {
+      document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
+    }
+  </script>
+</head>
+<body onload="prettyPrint(); highlight();">
+  <pre class="prettyprint lang-js"><span id='Ext-tree-ViewDropZone'>/**
+</span> * @class Ext.tree.ViewDropZone
+ * @extends Ext.view.DropZone
+ * @private
+ */
+Ext.define('Ext.tree.ViewDropZone', {
+    extend: 'Ext.view.DropZone',
+
+<span id='Ext-tree-ViewDropZone-cfg-allowParentInsert'>    /**
+</span>     * @cfg {Boolean} allowParentInsert
+     * Allow inserting a dragged node between an expanded parent node and its first child that will become a
+     * sibling of the parent when dropped (defaults to false)
+     */
+    allowParentInserts: false,
+<span id='Ext-tree-ViewDropZone-cfg-allowContainerDrop'>    /**
+</span>     * @cfg {String} allowContainerDrop
+     * True if drops on the tree container (outside of a specific tree node) are allowed (defaults to false)
+     */
+    allowContainerDrops: false,
+
+<span id='Ext-tree-ViewDropZone-cfg-appendOnly'>    /**
+</span>     * @cfg {String} appendOnly
+     * True if the tree should only allow append drops (use for trees which are sorted, defaults to false)
+     */
+    appendOnly: false,
+
+<span id='Ext-tree-ViewDropZone-cfg-expandDelay'>    /**
+</span>     * @cfg {String} expandDelay
+     * The delay in milliseconds to wait before expanding a target tree node while dragging a droppable node
+     * over the target (defaults to 500)
+     */
+    expandDelay : 500,
+
+    indicatorCls: 'x-tree-ddindicator',
+
+    // private
+    expandNode : function(node) {
+        var view = this.view;
+        if (!node.isLeaf() &amp;&amp; !node.isExpanded()) {
+            view.expand(node);
+            this.expandProcId = false;
+        }
+    },
+
+    // private
+    queueExpand : function(node) {
+        this.expandProcId = Ext.Function.defer(this.expandNode, this.expandDelay, this, [node]);
+    },
+
+    // private
+    cancelExpand : function() {
+        if (this.expandProcId) {
+            clearTimeout(this.expandProcId);
+            this.expandProcId = false;
+        }
+    },
+
+    getPosition: function(e, node) {
+        var view = this.view,
+            record = view.getRecord(node),
+            y = e.getPageY(),
+            noAppend = record.isLeaf(),
+            noBelow = false,
+            region = Ext.fly(node).getRegion(),
+            fragment;
+
+        // If we are dragging on top of the root node of the tree, we always want to append.
+        if (record.isRoot()) {
+            return 'append';
+        }
+
+        // Return 'append' if the node we are dragging on top of is not a leaf else return false.
+        if (this.appendOnly) {
+            return noAppend ? false : 'append';
+        }
+
+        if (!this.allowParentInsert) {
+            noBelow = record.hasChildNodes() &amp;&amp; record.isExpanded();
+        }
+
+        fragment = (region.bottom - region.top) / (noAppend ? 2 : 3);
+        if (y &gt;= region.top &amp;&amp; y &lt; (region.top + fragment)) {
+            return 'before';
+        }
+        else if (!noBelow &amp;&amp; (noAppend || (y &gt;= (region.bottom - fragment) &amp;&amp; y &lt;= region.bottom))) {
+            return 'after';
+        }
+        else {
+            return 'append';
+        }
+    },
+
+    isValidDropPoint : function(node, position, dragZone, e, data) {
+        if (!node || !data.item) {
+            return false;
+        }
+
+        var view = this.view,
+            targetNode = view.getRecord(node),
+            draggedRecords = data.records,
+            dataLength = draggedRecords.length,
+            ln = draggedRecords.length,
+            i, record;
+
+        // No drop position, or dragged records: invalid drop point
+        if (!(targetNode &amp;&amp; position &amp;&amp; dataLength)) {
+            return false;
+        }
+
+        // If the targetNode is within the folder we are dragging
+        for (i = 0; i &lt; ln; i++) {
+            record = draggedRecords[i];
+            if (record.isNode &amp;&amp; record.contains(targetNode)) {
+                return false;
+            }
+        }
+        
+        // Respect the allowDrop field on Tree nodes
+        if (position === 'append' &amp;&amp; targetNode.get('allowDrop') == false) {
+            return false;
+        }
+        else if (position != 'append' &amp;&amp; targetNode.parentNode.get('allowDrop') == false) {
+            return false;
+        }
+
+        // If the target record is in the dragged dataset, then invalid drop
+        if (Ext.Array.contains(draggedRecords, targetNode)) {
+             return false;
+        }
+
+        // @TODO: fire some event to notify that there is a valid drop possible for the node you're dragging
+        // Yes: this.fireViewEvent(blah....) fires an event through the owning View.
+        return true;
+    },
+
+    onNodeOver : function(node, dragZone, e, data) {
+        var position = this.getPosition(e, node),
+            returnCls = this.dropNotAllowed,
+            view = this.view,
+            targetNode = view.getRecord(node),
+            indicator = this.getIndicator(),
+            indicatorX = 0,
+            indicatorY = 0;
+
+        // auto node expand check
+        this.cancelExpand();
+        if (position == 'append' &amp;&amp; !this.expandProcId &amp;&amp; !Ext.Array.contains(data.records, targetNode) &amp;&amp; !targetNode.isLeaf() &amp;&amp; !targetNode.isExpanded()) {
+            this.queueExpand(targetNode);
+        }
+            
+        if (this.isValidDropPoint(node, position, dragZone, e, data)) {
+            this.valid = true;
+            this.currentPosition = position;
+            this.overRecord = targetNode;
+
+            indicator.setWidth(Ext.fly(node).getWidth());
+            indicatorY = Ext.fly(node).getY() - Ext.fly(view.el).getY() - 1;
+
+            if (position == 'before') {
+                returnCls = targetNode.isFirst() ? Ext.baseCSSPrefix + 'tree-drop-ok-above' : Ext.baseCSSPrefix + 'tree-drop-ok-between';
+                indicator.showAt(0, indicatorY);
+                indicator.toFront();
+            }
+            else if (position == 'after') {
+                returnCls = targetNode.isLast() ? Ext.baseCSSPrefix + 'tree-drop-ok-below' : Ext.baseCSSPrefix + 'tree-drop-ok-between';
+                indicatorY += Ext.fly(node).getHeight();
+                indicator.showAt(0, indicatorY);
+                indicator.toFront();
+            }
+            else {
+                returnCls = Ext.baseCSSPrefix + 'tree-drop-ok-append';
+                // @TODO: set a class on the parent folder node to be able to style it
+                indicator.hide();
+            }
+        }
+        else {
+            this.valid = false;
+        }
+
+        this.currentCls = returnCls;
+        return returnCls;
+    },
+
+    onContainerOver : function(dd, e, data) {
+        return e.getTarget('.' + this.indicatorCls) ? this.currentCls : this.dropNotAllowed;
+    },
+    
+    notifyOut: function() {
+        this.callParent(arguments);
+        this.cancelExpand();
+    },
+
+    handleNodeDrop : function(data, targetNode, position) {
+        var me = this,
+            view = me.view,
+            parentNode = targetNode.parentNode,
+            store = view.getStore(),
+            recordDomNodes = [],
+            records, i, len,
+            insertionMethod, argList,
+            needTargetExpand,
+            transferData,
+            processDrop;
+
+        // If the copy flag is set, create a copy of the Models with the same IDs
+        if (data.copy) {
+            records = data.records;
+            data.records = [];
+            for (i = 0, len = records.length; i &lt; len; i++) {
+                data.records.push(Ext.apply({}, records[i].data));
+            }
+        }
+
+        // Cancel any pending expand operation
+        me.cancelExpand();
+
+        // Grab a reference to the correct node insertion method.
+        // Create an arg list array intended for the apply method of the
+        // chosen node insertion method.
+        // Ensure the target object for the method is referenced by 'targetNode'
+        if (position == 'before') {
+            insertionMethod = parentNode.insertBefore;
+            argList = [null, targetNode];
+            targetNode = parentNode;
+        }
+        else if (position == 'after') {
+            if (targetNode.nextSibling) {
+                insertionMethod = parentNode.insertBefore;
+                argList = [null, targetNode.nextSibling];
+            }
+            else {
+                insertionMethod = parentNode.appendChild;
+                argList = [null];
+            }
+            targetNode = parentNode;
+        }
+        else {
+            if (!targetNode.isExpanded()) {
+                needTargetExpand = true;
+            }
+            insertionMethod = targetNode.appendChild;
+            argList = [null];
+        }
+
+        // A function to transfer the data into the destination tree
+        transferData = function() {
+            var node;
+            for (i = 0, len = data.records.length; i &lt; len; i++) {
+                argList[0] = data.records[i];
+                node = insertionMethod.apply(targetNode, argList);
+                
+                if (Ext.enableFx &amp;&amp; me.dropHighlight) {
+                    recordDomNodes.push(view.getNode(node));
+                }
+            }
+            
+            // Kick off highlights after everything's been inserted, so they are
+            // more in sync without insertion/render overhead.
+            if (Ext.enableFx &amp;&amp; me.dropHighlight) {
+                //FIXME: the check for n.firstChild is not a great solution here. Ideally the line should simply read 
+                //Ext.fly(n.firstChild) but this yields errors in IE6 and 7. See ticket EXTJSIV-1705 for more details
+                Ext.Array.forEach(recordDomNodes, function(n) {
+                    Ext.fly(n.firstChild ? n.firstChild : n).highlight(me.dropHighlightColor);
+                });
+            }
+        };
+
+        // If dropping right on an unexpanded node, transfer the data after it is expanded.
+        if (needTargetExpand) {
+            targetNode.expand(false, transferData);
+        }
+        // Otherwise, call the data transfer function immediately
+        else {
+            transferData();
+        }
+    }
+});</pre>
+</body>
+</html>