Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / examples / ux / Spotlight.js
1 /**
2  * @class Ext.ux.Spotlight
3  * UX used to provide a spotlight around a specified component/element.
4  */
5 Ext.define('Ext.ux.Spotlight', {
6     extend: 'Object',
7
8     /**
9      * @private
10      * The baseCls for the spotlight elements
11      */
12     baseCls: 'x-spotlight',
13
14     /**
15      * @cfg animate {Boolean} True to animate the spotlight change
16      * (defaults to true)
17      */
18     animate: true,
19
20     /**
21      * @cfg duration {Integer} The duration of the animation, in milliseconds
22      * (defaults to 250)
23      */
24     duration: 250,
25
26     /**
27      * @cfg easing {String} The type of easing for the spotlight animatation
28      * (defaults to null)
29      */
30     easing: null,
31
32     /**
33      * @private
34      * True if the spotlight is active on the element
35      */
36     active: false,
37
38     /**
39      * Create all the elements for the spotlight
40      */
41     createElements: function() {
42         var body = Ext.getBody();
43
44         this.right = body.createChild({
45             cls: this.baseCls
46         });
47         this.left = body.createChild({
48             cls: this.baseCls
49         });
50         this.top = body.createChild({
51             cls: this.baseCls
52         });
53         this.bottom = body.createChild({
54             cls: this.baseCls
55         });
56
57         this.all = Ext.create('Ext.CompositeElement', [this.right, this.left, this.top, this.bottom]);
58     },
59
60     /**
61      * Show the spotlight
62      */
63     show: function(el, callback, scope) {
64         //get the target element
65         this.el = Ext.get(el);
66
67         //create the elements if they don't already exist
68         if (!this.right) {
69             this.createElements();
70         }
71
72         if (!this.active) {
73             //if the spotlight is not active, show it
74             this.all.setDisplayed('');
75             this.active = true;
76             Ext.EventManager.onWindowResize(this.syncSize, this);
77             this.applyBounds(this.animate, false);
78         } else {
79             //if the spotlight is currently active, just move it
80             this.applyBounds(false, false);
81         }
82     },
83
84     /**
85      * Hide the spotlight
86      */
87     hide: function(callback, scope) {
88         Ext.EventManager.removeResizeListener(this.syncSize, this);
89
90         this.applyBounds(this.animate, true);
91     },
92
93     /**
94      * Resizes the spotlight with the window size.
95      */
96     syncSize: function() {
97         this.applyBounds(false, false);
98     },
99
100     /**
101      * Resizes the spotlight depending on the arguments
102      * @param {Boolean} animate True to animate the changing of the bounds
103      * @param {Boolean} animate True to reverse the animation
104      */
105     applyBounds: function(animate, reverse) {
106         var me = this,
107             box = me.el.getBox();
108
109         //get the current view width and height
110         var viewWidth = Ext.core.Element.getViewWidth(true);
111         var viewHeight = Ext.core.Element.getViewHeight(true);
112
113         var i = 0,
114             config = false,
115             from, to;
116
117         //where the element should start (if animation)
118         from = {
119             right: {
120                 x: box.right,
121                 y: viewHeight,
122                 width: (viewWidth - box.right),
123                 height: 0
124             },
125             left: {
126                 x: 0,
127                 y: 0,
128                 width: box.x,
129                 height: 0
130             },
131             top: {
132                 x: viewWidth,
133                 y: 0,
134                 width: 0,
135                 height: box.y
136             },
137             bottom: {
138                 x: 0,
139                 y: (box.y + box.height),
140                 width: 0,
141                 height: (viewHeight - (box.y + box.height)) + 'px'
142             }
143         };
144
145         //where the element needs to finish
146         to = {
147             right: {
148                 x: box.right,
149                 y: box.y,
150                 width: (viewWidth - box.right) + 'px',
151                 height: (viewHeight - box.y) + 'px'
152             },
153             left: {
154                 x: 0,
155                 y: 0,
156                 width: box.x + 'px',
157                 height: (box.y + box.height) + 'px'
158             },
159             top: {
160                 x: box.x,
161                 y: 0,
162                 width: (viewWidth - box.x) + 'px',
163                 height: box.y + 'px'
164             },
165             bottom: {
166                 x: 0,
167                 y: (box.y + box.height),
168                 width: (box.x + box.width) + 'px',
169                 height: (viewHeight - (box.y + box.height)) + 'px'
170             }
171         };
172
173         //reverse the objects
174         if (reverse) {
175             var clone = Ext.clone(from);
176             from = to;
177             to = clone;
178
179             delete clone;
180         }
181
182         if (animate) {
183             Ext.each(['right', 'left', 'top', 'bottom'], function(side) {
184                 me[side].setBox(from[side]);
185                 me[side].animate({
186                     duration: me.duration,
187                     easing: me.easing,
188                     to: to[side]
189                 });
190             },
191             this);
192         } else {
193             Ext.each(['right', 'left', 'top', 'bottom'], function(side) {
194                 me[side].setBox(Ext.apply(from[side], to[side]));
195             },
196             this);
197         }
198     },
199
200     /**
201      * Removes all the elements for the spotlight
202      */
203     destroy: function() {
204         Ext.destroy(this.right, this.left, this.top, this.bottom);
205         delete this.el;
206         delete this.all;
207     }
208 });