Upgrade to ExtJS 3.2.0 - Released 03/30/2010
[extjs.git] / examples / ux / ToolbarDroppable.js
diff --git a/examples/ux/ToolbarDroppable.js b/examples/ux/ToolbarDroppable.js
new file mode 100644 (file)
index 0000000..c9ba855
--- /dev/null
@@ -0,0 +1,159 @@
+/*!
+ * Ext JS Library 3.2.0
+ * Copyright(c) 2006-2010 Ext JS, Inc.
+ * licensing@extjs.com
+ * http://www.extjs.com/license
+ */
+/**
+ * @class Ext.ux.ToolbarDroppable
+ * @extends Object
+ * Plugin which allows items to be dropped onto a toolbar and be turned into new Toolbar items.
+ * To use the plugin, you just need to provide a createItem implementation that takes the drop
+ * data as an argument and returns an object that can be placed onto the toolbar. Example:
+ * <pre>
+ * new Ext.ux.ToolbarDroppable({
+ *   createItem: function(data) {
+ *     return new Ext.Button({text: data.text});
+ *   }
+ * });
+ * </pre>
+ * The afterLayout function can also be overridden, and is called after a new item has been 
+ * created and inserted into the Toolbar. Use this for any logic that needs to be run after
+ * the item has been created.
+ */
+Ext.ux.ToolbarDroppable = Ext.extend(Object, {
+    /**
+     * @constructor
+     */
+    constructor: function(config) {
+      Ext.apply(this, config, {
+          
+      });
+    },
+    
+    /**
+     * Initializes the plugin and saves a reference to the toolbar
+     * @param {Ext.Toolbar} toolbar The toolbar instance
+     */
+    init: function(toolbar) {
+      /**
+       * @property toolbar
+       * @type Ext.Toolbar
+       * The toolbar instance that this plugin is tied to
+       */
+      this.toolbar = toolbar;
+      
+      this.toolbar.on({
+          scope : this,
+          render: this.createDropTarget
+      });
+    },
+    
+    /**
+     * Creates a drop target on the toolbar
+     */
+    createDropTarget: function() {
+        /**
+         * @property dropTarget
+         * @type Ext.dd.DropTarget
+         * The drop target attached to the toolbar instance
+         */
+        this.dropTarget = new Ext.dd.DropTarget(this.toolbar.getEl(), {
+            notifyOver: this.notifyOver.createDelegate(this),
+            notifyDrop: this.notifyDrop.createDelegate(this)
+        });
+    },
+    
+    /**
+     * Adds the given DD Group to the drop target
+     * @param {String} ddGroup The DD Group
+     */
+    addDDGroup: function(ddGroup) {
+        this.dropTarget.addToGroup(ddGroup);
+    },
+    
+    /**
+     * Calculates the location on the toolbar to create the new sorter button based on the XY of the
+     * drag event
+     * @param {Ext.EventObject} e The event object
+     * @return {Number} The index at which to insert the new button
+     */
+    calculateEntryIndex: function(e) {
+        var entryIndex = 0,
+            toolbar    = this.toolbar,
+            items      = toolbar.items.items,
+            count      = items.length,
+            xTotal     = toolbar.getEl().getXY()[0],
+            xHover     = e.getXY()[0] - xTotal;
+        
+        for (var index = 0; index < count; index++) {
+            var item     = items[index],
+                width    = item.getEl().getWidth(),
+                midpoint = xTotal + width / 2;
+            
+            xTotal += width;
+            
+            if (xHover < midpoint) {
+                entryIndex = index;       
+
+                break;
+            } else {
+                entryIndex = index + 1;
+            }
+        }
+        
+        return entryIndex;
+    },
+    
+    /**
+     * Returns true if the drop is allowed on the drop target. This function can be overridden
+     * and defaults to simply return true
+     * @param {Object} data Arbitrary data from the drag source
+     * @return {Boolean} True if the drop is allowed
+     */
+    canDrop: function(data) {
+        return true;
+    },
+    
+    /**
+     * Custom notifyOver method which will be used in the plugin's internal DropTarget
+     * @return {String} The CSS class to add
+     */
+    notifyOver: function(dragSource, event, data) {
+        return this.canDrop.apply(this, arguments) ? this.dropTarget.dropAllowed : this.dropTarget.dropNotAllowed;
+    },
+    
+    /**
+     * Called when the drop has been made. Creates the new toolbar item, places it at the correct location
+     * and calls the afterLayout callback.
+     */
+    notifyDrop: function(dragSource, event, data) {
+        var canAdd = this.canDrop(dragSource, event, data),
+            tbar   = this.toolbar;
+        
+        if (canAdd) {
+            var entryIndex = this.calculateEntryIndex(event);
+            
+            tbar.insert(entryIndex, this.createItem(data));
+            tbar.doLayout();
+            
+            this.afterLayout();
+        }
+        
+        return canAdd;
+    },
+    
+    /**
+     * Creates the new toolbar item based on drop data. This method must be implemented by the plugin instance
+     * @param {Object} data Arbitrary data from the drop
+     * @return {Mixed} An item that can be added to a toolbar
+     */
+    createItem: function(data) {
+        throw new Error("The createItem method must be implemented in the ToolbarDroppable plugin");
+    },
+    
+    /**
+     * Called after a new button has been created and added to the toolbar. Add any required cleanup logic here
+     */
+    afterLayout: Ext.emptyFn
+});
\ No newline at end of file