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