Upgrade to ExtJS 3.3.1 - Released 11/30/2010
[extjs.git] / examples / docs / source / ToolbarReorderer.html
1 <html>
2 <head>
3   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    
4   <title>The source code</title>
5     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
6     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
7 </head>
8 <body  onload="prettyPrint();">
9     <pre class="prettyprint lang-js">/*!
10  * Ext JS Library 3.3.1
11  * Copyright(c) 2006-2010 Sencha Inc.
12  * licensing@sencha.com
13  * http://www.sencha.com/license
14  */
15 <div id="cls-Ext.ux.ToolbarReorderer"></div>/**
16  * @class Ext.ux.ToolbarReorderer
17  * @extends Ext.ux.Reorderer
18  * Plugin which can be attached to any Ext.Toolbar instance. Provides ability to reorder toolbar items
19  * with drag and drop. Example:
20  * <pre>
21  * new Ext.Toolbar({
22  *     plugins: [
23  *         new Ext.ux.ToolbarReorderer({
24  *             defaultReorderable: true
25  *         })
26  *     ],
27  *     items: [
28  *       {text: 'Button 1', reorderable: false},
29  *       {text: 'Button 2'},
30  *       {text: 'Button 3'}
31  *     ]
32  * });
33  * </pre>
34  * In the example above, buttons 2 and 3 will be reorderable via drag and drop. An event named 'reordered'
35  * is added to the Toolbar, and is fired whenever a reorder has been completed.
36  */
37 Ext.ux.ToolbarReorderer = Ext.extend(Ext.ux.Reorderer, {
38     <div id="method-Ext.ux.ToolbarReorderer-init"></div>/**
39      * Initializes the plugin, decorates the toolbar with additional functionality
40      */
41     init: function(toolbar) {
42         <div id="prop-Ext.ux.ToolbarReorderer-buttonXCache"></div>/**
43          * This is used to store the correct x value of each button in the array. We need to use this
44          * instead of the button's reported x co-ordinate because the buttons are animated when they move -
45          * if another onDrag is fired while the button is still moving, the comparison x value will be incorrect
46          */
47         this.buttonXCache = {};
48         
49         toolbar.on({
50             scope: this,
51             add  : function(toolbar, item) {
52                 this.createIfReorderable(item);
53             }
54         });
55         
56         //super sets a reference to the toolbar in this.target
57         Ext.ux.ToolbarReorderer.superclass.init.apply(this, arguments);
58     },
59         
60     <div id="method-Ext.ux.ToolbarReorderer-createItemDD"></div>/**
61      * Sets up the given Toolbar item as a draggable
62      * @param {Mixed} button The item to make draggable (usually an Ext.Button instance)
63      */
64     createItemDD: function(button) {
65         if (button.dd != undefined) {
66             return;
67         }
68         
69         var el   = button.getEl(),
70             id   = el.id,
71             tbar = this.target,
72             me   = this;
73         
74         button.dd = new Ext.dd.DD(el, undefined, {
75             isTarget: false
76         });
77         
78         //if a button has a menu, it is disabled while dragging with this function
79         var menuDisabler = function() {
80             return false;
81         };
82         
83         Ext.apply(button.dd, {
84             b4StartDrag: function() {       
85                 this.startPosition = el.getXY();
86                 
87                 //bump up the z index of the button being dragged but keep a reference to the original
88                 this.startZIndex = el.getStyle('zIndex');
89                 el.setStyle('zIndex', 10000);
90                 
91                 button.suspendEvents();
92                 if (button.menu) {
93                     button.menu.on('beforeshow', menuDisabler, me);
94                 }
95             },
96             
97             startDrag: function() {
98                 this.constrainTo(tbar.getEl());
99                 this.setYConstraint(0, 0, 0);
100             },
101             
102             onDrag: function(e) {
103                 //calculate the button's index within the toolbar and its current midpoint
104                 var buttonX  = el.getXY()[0],
105                     deltaX   = buttonX - this.startPosition[0],
106                     items    = tbar.items.items,
107                     oldIndex = items.indexOf(button),
108                     newIndex;
109                 
110                 //find which item in the toolbar the midpoint is currently over
111                 for (var index = 0; index < items.length; index++) {
112                     var item = items[index];
113                     
114                     if (item.reorderable && item.id != button.id) {
115                         //find the midpoint of the button
116                         var box        = item.getEl().getBox(),
117                             midpoint   = (me.buttonXCache[item.id] || box.x) + (box.width / 2),
118                             movedLeft  = oldIndex > index && deltaX < 0 && buttonX < midpoint,
119                             movedRight = oldIndex < index && deltaX > 0 && (buttonX + el.getWidth()) > midpoint;
120                         
121                         if (movedLeft || movedRight) {
122                             me[movedLeft ? 'onMovedLeft' : 'onMovedRight'](button, index, oldIndex);
123                             break;
124                         }                        
125                     }
126                 }
127             },
128             
129             <div id="method-Ext.ux.ToolbarReorderer-endDrag"></div>/**
130              * After the drag has been completed, make sure the button being dragged makes it back to
131              * the correct location and resets its z index
132              */
133             endDrag: function() {
134                 //we need to update the cache here for cases where the button was dragged but its
135                 //position in the toolbar did not change
136                 me.updateButtonXCache();
137                 
138                 el.moveTo(me.buttonXCache[button.id], el.getY(), {
139                     duration: me.animationDuration,
140                     scope   : this,
141                     callback: function() {
142                         button.resumeEvents();
143                         if (button.menu) {
144                             button.menu.un('beforeshow', menuDisabler, me);
145                         }
146                         
147                         tbar.fireEvent('reordered', button, tbar);
148                     }
149                 });
150                 
151                 el.setStyle('zIndex', this.startZIndex);
152             }
153         });
154     },
155     
156     onMovedLeft: function(item, newIndex, oldIndex) {
157         var tbar  = this.target,
158             items = tbar.items.items;
159         
160         if (newIndex != undefined && newIndex != oldIndex) {
161             //move the button currently under drag to its new location
162             tbar.remove(item, false);
163             tbar.insert(newIndex, item);
164             
165             //set the correct x location of each item in the toolbar
166             this.updateButtonXCache();
167             for (var index = 0; index < items.length; index++) {
168                 var obj  = items[index],
169                     newX = this.buttonXCache[obj.id];
170                 
171                 if (item == obj) {
172                     item.dd.startPosition[0] = newX;
173                 } else {
174                     var el = obj.getEl();
175                     
176                     el.moveTo(newX, el.getY(), {duration: this.animationDuration});
177                 }
178             }
179         }
180     },
181     
182     onMovedRight: function(item, newIndex, oldIndex) {
183         this.onMovedLeft.apply(this, arguments);
184     },
185     
186     /**
187      * @private
188      * Updates the internal cache of button X locations. 
189      */
190     updateButtonXCache: function() {
191         var tbar   = this.target,
192             items  = tbar.items,
193             totalX = tbar.getEl().getBox(true).x;
194             
195         items.each(function(item) {
196             this.buttonXCache[item.id] = totalX;
197
198             totalX += item.getEl().getWidth();
199         }, this);
200     }
201 });</pre>    
202 </body>
203 </html>