Upgrade to ExtJS 3.3.1 - Released 11/30/2010
[extjs.git] / examples / ux / ToolbarDroppable.js
1 /*!
2  * Ext JS Library 3.3.1
3  * Copyright(c) 2006-2010 Sencha Inc.
4  * licensing@sencha.com
5  * http://www.sencha.com/license
6  */
7 /**
8  * @class Ext.ux.ToolbarDroppable
9  * @extends Object
10  * Plugin which allows items to be dropped onto a toolbar and be turned into new Toolbar items.
11  * To use the plugin, you just need to provide a createItem implementation that takes the drop
12  * data as an argument and returns an object that can be placed onto the toolbar. Example:
13  * <pre>
14  * new Ext.ux.ToolbarDroppable({
15  *   createItem: function(data) {
16  *     return new Ext.Button({text: data.text});
17  *   }
18  * });
19  * </pre>
20  * The afterLayout function can also be overridden, and is called after a new item has been 
21  * created and inserted into the Toolbar. Use this for any logic that needs to be run after
22  * the item has been created.
23  */
24 Ext.ux.ToolbarDroppable = Ext.extend(Object, {
25     /**
26      * @constructor
27      */
28     constructor: function(config) {
29       Ext.apply(this, config, {
30           
31       });
32     },
33     
34     /**
35      * Initializes the plugin and saves a reference to the toolbar
36      * @param {Ext.Toolbar} toolbar The toolbar instance
37      */
38     init: function(toolbar) {
39       /**
40        * @property toolbar
41        * @type Ext.Toolbar
42        * The toolbar instance that this plugin is tied to
43        */
44       this.toolbar = toolbar;
45       
46       this.toolbar.on({
47           scope : this,
48           render: this.createDropTarget
49       });
50     },
51     
52     /**
53      * Creates a drop target on the toolbar
54      */
55     createDropTarget: function() {
56         /**
57          * @property dropTarget
58          * @type Ext.dd.DropTarget
59          * The drop target attached to the toolbar instance
60          */
61         this.dropTarget = new Ext.dd.DropTarget(this.toolbar.getEl(), {
62             notifyOver: this.notifyOver.createDelegate(this),
63             notifyDrop: this.notifyDrop.createDelegate(this)
64         });
65     },
66     
67     /**
68      * Adds the given DD Group to the drop target
69      * @param {String} ddGroup The DD Group
70      */
71     addDDGroup: function(ddGroup) {
72         this.dropTarget.addToGroup(ddGroup);
73     },
74     
75     /**
76      * Calculates the location on the toolbar to create the new sorter button based on the XY of the
77      * drag event
78      * @param {Ext.EventObject} e The event object
79      * @return {Number} The index at which to insert the new button
80      */
81     calculateEntryIndex: function(e) {
82         var entryIndex = 0,
83             toolbar    = this.toolbar,
84             items      = toolbar.items.items,
85             count      = items.length,
86             xTotal     = toolbar.getEl().getXY()[0],
87             xHover     = e.getXY()[0] - xTotal;
88         
89         for (var index = 0; index < count; index++) {
90             var item     = items[index],
91                 width    = item.getEl().getWidth(),
92                 midpoint = xTotal + width / 2;
93             
94             xTotal += width;
95             
96             if (xHover < midpoint) {
97                 entryIndex = index;       
98
99                 break;
100             } else {
101                 entryIndex = index + 1;
102             }
103         }
104         
105         return entryIndex;
106     },
107     
108     /**
109      * Returns true if the drop is allowed on the drop target. This function can be overridden
110      * and defaults to simply return true
111      * @param {Object} data Arbitrary data from the drag source
112      * @return {Boolean} True if the drop is allowed
113      */
114     canDrop: function(data) {
115         return true;
116     },
117     
118     /**
119      * Custom notifyOver method which will be used in the plugin's internal DropTarget
120      * @return {String} The CSS class to add
121      */
122     notifyOver: function(dragSource, event, data) {
123         return this.canDrop.apply(this, arguments) ? this.dropTarget.dropAllowed : this.dropTarget.dropNotAllowed;
124     },
125     
126     /**
127      * Called when the drop has been made. Creates the new toolbar item, places it at the correct location
128      * and calls the afterLayout callback.
129      */
130     notifyDrop: function(dragSource, event, data) {
131         var canAdd = this.canDrop(dragSource, event, data),
132             tbar   = this.toolbar;
133         
134         if (canAdd) {
135             var entryIndex = this.calculateEntryIndex(event);
136             
137             tbar.insert(entryIndex, this.createItem(data));
138             tbar.doLayout();
139             
140             this.afterLayout();
141         }
142         
143         return canAdd;
144     },
145     
146     /**
147      * Creates the new toolbar item based on drop data. This method must be implemented by the plugin instance
148      * @param {Object} data Arbitrary data from the drop
149      * @return {Mixed} An item that can be added to a toolbar
150      */
151     createItem: function(data) {
152         throw new Error("The createItem method must be implemented in the ToolbarDroppable plugin");
153     },
154     
155     /**
156      * Called after a new button has been created and added to the toolbar. Add any required cleanup logic here
157      */
158     afterLayout: Ext.emptyFn
159 });