Initial
[qwikioffice:qwikioffice.git] / public / client / GhostBar.js
1 // http://www.extjs.com/forum/showthread.php?69295-Ext.ux.GhostBar-A-space-saving-fade-in-Toolbar
2 // Example Usage: plugins: [ new Ext.ux.GhostBar({ items: [{ text: 'Click Me' }], position: 'top' }) ],
3
4 Ext.override(Ext.lib.Region, {
5     /**
6      * Returns the shortest distance between this Region and another Region.
7      * Either or both Regions may be Points.
8      * @param {Region} r The other Region
9      * @return {Number} The shortest distance in pixels between the two Regions.
10      */
11     getDistanceBetween: function(r) {
12
13 //      We may need to mutate r, so make a copy.
14         r = Ext.apply({}, r);
15
16 //      Translate r to the left of this
17         if (r.left > this.right) {
18             var rWidth = r.right - r.left;
19             r.left = this.left - (r.left - this.right) - rWidth;
20             r.right = r.left + rWidth;
21         }
22
23 //      Translate r above this
24         if (r.top > this.bottom) {
25             var rHeight = r.bottom - r.top;
26             r.top = this.top - (r.top - this.bottom) - rHeight;
27             r.bottom = r.top + rHeight;
28         }
29
30 //      If r is directly above
31         if (r.right > this.left) {
32             return this.top - r.bottom;
33         }
34
35 //      If r is directly to the left
36         if (r.bottom > this.top) {
37             return this.left - r.right;
38         }
39
40 //      r is on a diagonal path
41         return Math.round(Math.sqrt(Math.pow(this.top - r.bottom, 2) + Math.pow(this.left - r.right, 2)));
42     }
43 });
44
45 /**
46  * @class Ext.ux.GhostBar
47  * @extends Ext.Toolbar
48  * A Toolbar class which attaches as a plugin to any BoxComponent, and fades in at the configured
49  * position whenever the mouse is brought within a configurable threshold. eg: <code><pre>
50 new Ext.Panel({
51     renderTo: document.body,
52     title: 'Test',
53     width: 600,
54     height: 400,
55     plugins: [ new Ext.ux.GhostBar([{ text: 'Click Me' }]) ]
56 });
57 </pre></code>
58  */
59 Ext.ux.GhostBar = Ext.extend(Ext.Toolbar, {
60
61     listenerAdded: false,
62
63     cache: [],
64
65     /**
66      * @cfg {Number} threshold The number of pixels around the toolbar position in which
67      * fading is performed.
68      */
69     threshold: 100,
70
71     /**
72      * @cfg {String} position The alignment of this Toolbar, <code><b>top</b></code>, or <code><b>bottom</b></code>.
73      * Defaults to <code><b>bottom</b></code>.
74      */
75     /**
76      * @cfg {Array} offsets A two element Array containing the [x, y] offset from the default position
77      * in which to display the Toolbar.
78      */
79
80     initComponent: function() {
81
82 //      Only use one mousemove listener. Check the cache of GhostBars for proximity on each firing
83         if (!this.listenerAdded) {
84             Ext.getDoc().on('mousemove', Ext.ux.GhostBar.prototype.onDocMouseMove, Ext.ux.GhostBar.prototype);
85             this.listenerAdded = true;
86         }
87         this.renderTo = document.body;
88         this.hideMode = 'visibility';
89         Ext.ux.GhostBar.superclass.initComponent.apply(this, arguments);
90     },
91
92     onRender: function() {
93         Ext.ux.GhostBar.superclass.onRender.apply(this, arguments);
94         this.el.setStyle({
95             position: 'absolute'
96         });
97         this.hide();
98         this.cache.push(this);
99     },
100
101     init: function(c) {
102         this.ownerCt = c;
103         c.on({
104             render: this.onClientRender,
105             scope: this,
106             single: true
107         });
108         c.onPosition = c.onPosition.createSequence(this.onClientPosition, this);
109         c.onResize = c.onResize.createSequence(this.onClientResize, this);
110     },
111
112     onClientRender: function() {
113         this.clientEl = this.ownerCt.getLayoutTarget ? this.ownerCt.getLayoutTarget() : this.ownerCt.el;
114     },
115
116     onClientResize: function() {
117         this.setWidth(this.clientEl.getWidth(true));
118         this.syncPosition();
119     },
120
121     onClientPosition: function() {
122         this.syncPosition();
123     },
124
125     syncPosition: function() {
126         var offsets = [this.clientEl.getBorderWidth('l'), 0];
127         if (this.offsets) {
128             offsets[0] += this.offsets[0];
129             offsets[1] += this.offsets[1];
130         }
131         this.el.alignTo(this.clientEl, (this.position == 'top') ? 'tl-tl' : 'bl-bl', offsets);
132         this.region = this.el.getRegion();
133     },
134
135     onDocMouseMove: function(e) {
136         for (var i = 0; i < this.cache.length; i++) {
137             this.checkMousePosition.call(this.cache[i], e);
138         }
139     },
140
141     checkMousePosition: function(e) {
142         this.syncPosition();
143         var o = 1, d = this.region.getDistanceBetween(e.getPoint());
144         if (d > this.threshold) {
145             this.hide();
146         } else if (d > 0) {
147
148 //          Mouse is within range of this Toolbar, so show it if its not already visible
149             if (!this.isVisible()) {
150                 this.show();
151             }
152             o = 1 - (d / this.threshold);
153         }
154         var z = Ext.num(this.ownerCt.el.getStyle('zIndex'));
155         this.el.setStyle({
156             opacity: o,
157             'zIndex': (typeof z == 'number') ? z + 3 : 'auto'
158         });
159     },
160
161     onDestroy: function() {
162 //      Uncache this Toolbar when we are destroyed
163         this.cache.splice(this.cache.indexOf(this), 1);
164         Ext.ux.GhostBar.superclass.onDestroy.apply(this, arguments);
165     }
166 });