commit extjs-2.2.1
[extjs.git] / source / widgets / Shadow.js
1 /*\r
2  * Ext JS Library 2.2.1\r
3  * Copyright(c) 2006-2009, Ext JS, LLC.\r
4  * licensing@extjs.com\r
5  * \r
6  * http://extjs.com/license\r
7  */\r
8 \r
9 /**\r
10  * @class Ext.Shadow\r
11  * Simple class that can provide a shadow effect for any element.  Note that the element MUST be absolutely positioned,\r
12  * and the shadow does not provide any shimming.  This should be used only in simple cases -- for more advanced\r
13  * functionality that can also provide the same shadow effect, see the {@link Ext.Layer} class.\r
14  * @constructor\r
15  * Create a new Shadow\r
16  * @param {Object} config The config object\r
17  */\r
18 Ext.Shadow = function(config){\r
19     Ext.apply(this, config);\r
20     if(typeof this.mode != "string"){\r
21         this.mode = this.defaultMode;\r
22     }\r
23     var o = this.offset, a = {h: 0};\r
24     var rad = Math.floor(this.offset/2);\r
25     switch(this.mode.toLowerCase()){ // all this hideous nonsense calculates the various offsets for shadows\r
26         case "drop":\r
27             a.w = 0;\r
28             a.l = a.t = o;\r
29             a.t -= 1;\r
30             if(Ext.isIE){\r
31                 a.l -= this.offset + rad;\r
32                 a.t -= this.offset + rad;\r
33                 a.w -= rad;\r
34                 a.h -= rad;\r
35                 a.t += 1;\r
36             }\r
37         break;\r
38         case "sides":\r
39             a.w = (o*2);\r
40             a.l = -o;\r
41             a.t = o-1;\r
42             if(Ext.isIE){\r
43                 a.l -= (this.offset - rad);\r
44                 a.t -= this.offset + rad;\r
45                 a.l += 1;\r
46                 a.w -= (this.offset - rad)*2;\r
47                 a.w -= rad + 1;\r
48                 a.h -= 1;\r
49             }\r
50         break;\r
51         case "frame":\r
52             a.w = a.h = (o*2);\r
53             a.l = a.t = -o;\r
54             a.t += 1;\r
55             a.h -= 2;\r
56             if(Ext.isIE){\r
57                 a.l -= (this.offset - rad);\r
58                 a.t -= (this.offset - rad);\r
59                 a.l += 1;\r
60                 a.w -= (this.offset + rad + 1);\r
61                 a.h -= (this.offset + rad);\r
62                 a.h += 1;\r
63             }\r
64         break;\r
65     };\r
66 \r
67     this.adjusts = a;\r
68 };\r
69 \r
70 Ext.Shadow.prototype = {\r
71     /**\r
72      * @cfg {String} mode\r
73      * The shadow display mode.  Supports the following options:<br />\r
74      * sides: Shadow displays on both sides and bottom only<br />\r
75      * frame: Shadow displays equally on all four sides<br />\r
76      * drop: Traditional bottom-right drop shadow (default)\r
77      */\r
78     /**\r
79      * @cfg {String} offset\r
80      * The number of pixels to offset the shadow from the element (defaults to 4)\r
81      */\r
82     offset: 4,\r
83 \r
84     // private\r
85     defaultMode: "drop",\r
86 \r
87     /**\r
88      * Displays the shadow under the target element\r
89      * @param {Mixed} targetEl The id or element under which the shadow should display\r
90      */\r
91     show : function(target){\r
92         target = Ext.get(target);\r
93         if(!this.el){\r
94             this.el = Ext.Shadow.Pool.pull();\r
95             if(this.el.dom.nextSibling != target.dom){\r
96                 this.el.insertBefore(target);\r
97             }\r
98         }\r
99         this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);\r
100         if(Ext.isIE){\r
101             this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";\r
102         }\r
103         this.realign(\r
104             target.getLeft(true),\r
105             target.getTop(true),\r
106             target.getWidth(),\r
107             target.getHeight()\r
108         );\r
109         this.el.dom.style.display = "block";\r
110     },\r
111 \r
112     /**\r
113      * Returns true if the shadow is visible, else false\r
114      */\r
115     isVisible : function(){\r
116         return this.el ? true : false;  \r
117     },\r
118 \r
119     /**\r
120      * Direct alignment when values are already available. Show must be called at least once before\r
121      * calling this method to ensure it is initialized.\r
122      * @param {Number} left The target element left position\r
123      * @param {Number} top The target element top position\r
124      * @param {Number} width The target element width\r
125      * @param {Number} height The target element height\r
126      */\r
127     realign : function(l, t, w, h){\r
128         if(!this.el){\r
129             return;\r
130         }\r
131         var a = this.adjusts, d = this.el.dom, s = d.style;\r
132         var iea = 0;\r
133         s.left = (l+a.l)+"px";\r
134         s.top = (t+a.t)+"px";\r
135         var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";\r
136         if(s.width != sws || s.height != shs){\r
137             s.width = sws;\r
138             s.height = shs;\r
139             if(!Ext.isIE){\r
140                 var cn = d.childNodes;\r
141                 var sww = Math.max(0, (sw-12))+"px";\r
142                 cn[0].childNodes[1].style.width = sww;\r
143                 cn[1].childNodes[1].style.width = sww;\r
144                 cn[2].childNodes[1].style.width = sww;\r
145                 cn[1].style.height = Math.max(0, (sh-12))+"px";\r
146             }\r
147         }\r
148     },\r
149 \r
150     /**\r
151      * Hides this shadow\r
152      */\r
153     hide : function(){\r
154         if(this.el){\r
155             this.el.dom.style.display = "none";\r
156             Ext.Shadow.Pool.push(this.el);\r
157             delete this.el;\r
158         }\r
159     },\r
160 \r
161     /**\r
162      * Adjust the z-index of this shadow\r
163      * @param {Number} zindex The new z-index\r
164      */\r
165     setZIndex : function(z){\r
166         this.zIndex = z;\r
167         if(this.el){\r
168             this.el.setStyle("z-index", z);\r
169         }\r
170     }\r
171 };\r
172 \r
173 // Private utility class that manages the internal Shadow cache\r
174 Ext.Shadow.Pool = function(){\r
175     var p = [];\r
176     var markup = Ext.isIE ?\r
177                  '<div class="x-ie-shadow"></div>' :\r
178                  '<div class="x-shadow"><div class="xst"><div class="xstl"></div><div class="xstc"></div><div class="xstr"></div></div><div class="xsc"><div class="xsml"></div><div class="xsmc"></div><div class="xsmr"></div></div><div class="xsb"><div class="xsbl"></div><div class="xsbc"></div><div class="xsbr"></div></div></div>';\r
179     return {\r
180         pull : function(){\r
181             var sh = p.shift();\r
182             if(!sh){\r
183                 sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));\r
184                 sh.autoBoxAdjust = false;\r
185             }\r
186             return sh;\r
187         },\r
188 \r
189         push : function(sh){\r
190             p.push(sh);\r
191         }\r
192     };\r
193 }();