]> dev.renevier.net Git - syp.git/blob - openlayers/lib/OpenLayers/Popup/Framed.js
fixes notices
[syp.git] / openlayers / lib / OpenLayers / Popup / Framed.js
1 /* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
2  * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
3  * full text of the license. */
4
5 /**
6  * @requires OpenLayers/Popup/Anchored.js
7  */
8
9 /**
10  * Class: OpenLayers.Popup.Framed
11  * 
12  * Inherits from:
13  *  - <OpenLayers.Popup.Anchored>
14  */
15 OpenLayers.Popup.Framed =
16   OpenLayers.Class(OpenLayers.Popup.Anchored, {
17
18     /**
19      * Property: imageSrc
20      * {String} location of the image to be used as the popup frame
21      */
22     imageSrc: null,
23
24     /**
25      * Property: imageSize
26      * {<OpenLayers.Size>} Size (measured in pixels) of the image located
27      *     by the 'imageSrc' property.
28      */
29     imageSize: null,
30
31     /**
32      * APIProperty: isAlphaImage
33      * {Boolean} The image has some alpha and thus needs to use the alpha 
34      *     image hack. Note that setting this to true will have no noticeable
35      *     effect in FF or IE7 browsers, but will all but crush the ie6 
36      *     browser. 
37      *     Default is false.
38      */
39     isAlphaImage: false,
40
41     /**
42      * Property: positionBlocks
43      * {Object} Hash of different position blocks (Object/Hashs). Each block 
44      *     will be keyed by a two-character 'relativePosition' 
45      *     code string (ie "tl", "tr", "bl", "br"). Block properties are 
46      *     'offset', 'padding' (self-explanatory), and finally the 'blocks'
47      *     parameter, which is an array of the block objects. 
48      * 
49      *     Each block object must have 'size', 'anchor', and 'position' 
50      *     properties.
51      * 
52      *     Note that positionBlocks should never be modified at runtime.
53      */
54     positionBlocks: null,
55
56     /**
57      * Property: blocks
58      * {Array[Object]} Array of objects, each of which is one "block" of the 
59      *     popup. Each block has a 'div' and an 'image' property, both of 
60      *     which are DOMElements, and the latter of which is appended to the 
61      *     former. These are reused as the popup goes changing positions for
62      *     great economy and elegance.
63      */
64     blocks: null,
65
66     /** 
67      * APIProperty: fixedRelativePosition
68      * {Boolean} We want the framed popup to work dynamically placed relative
69      *     to its anchor but also in just one fixed position. A well designed
70      *     framed popup will have the pixels and logic to display itself in 
71      *     any of the four relative positions, but (understandably), this will
72      *     not be the case for all of them. By setting this property to 'true', 
73      *     framed popup will not recalculate for the best placement each time
74      *     it's open, but will always open the same way. 
75      *     Note that if this is set to true, it is generally advisable to also
76      *     set the 'panIntoView' property to true so that the popup can be 
77      *     scrolled into view (since it will often be offscreen on open)
78      *     Default is false.
79      */
80     fixedRelativePosition: false,
81
82     /** 
83      * Constructor: OpenLayers.Popup.Framed
84      * 
85      * Parameters:
86      * id - {String}
87      * lonlat - {<OpenLayers.LonLat>}
88      * contentSize - {<OpenLayers.Size>}
89      * contentHTML - {String}
90      * anchor - {Object} Object to which we'll anchor the popup. Must expose 
91      *     a 'size' (<OpenLayers.Size>) and 'offset' (<OpenLayers.Pixel>) 
92      *     (Note that this is generally an <OpenLayers.Icon>).
93      * closeBox - {Boolean}
94      * closeBoxCallback - {Function} Function to be called on closeBox click.
95      */
96     initialize:function(id, lonlat, contentSize, contentHTML, anchor, closeBox, 
97                         closeBoxCallback) {
98
99         OpenLayers.Popup.Anchored.prototype.initialize.apply(this, arguments);
100
101         if (this.fixedRelativePosition) {
102             //based on our decided relativePostion, set the current padding
103             // this keeps us from getting into trouble 
104             this.updateRelativePosition();
105             
106             //make calculateRelativePosition always return the specified
107             // fixed position.
108             this.calculateRelativePosition = function(px) {
109                 return this.relativePosition;
110             };
111         }
112
113         this.contentDiv.style.position = "absolute";
114         this.contentDiv.style.zIndex = 1;
115
116         if (closeBox) {
117             this.closeDiv.style.zIndex = 1;
118         }
119
120         this.groupDiv.style.position = "absolute";
121         this.groupDiv.style.top = "0px";
122         this.groupDiv.style.left = "0px";
123         this.groupDiv.style.height = "100%";
124         this.groupDiv.style.width = "100%";
125     },
126
127     /** 
128      * APIMethod: destroy
129      */
130     destroy: function() {
131         this.imageSrc = null;
132         this.imageSize = null;
133         this.isAlphaImage = null;
134
135         this.fixedRelativePosition = false;
136         this.positionBlocks = null;
137
138         //remove our blocks
139         for(var i = 0; i < this.blocks.length; i++) {
140             var block = this.blocks[i];
141
142             if (block.image) {
143                 block.div.removeChild(block.image);
144             }
145             block.image = null;
146
147             if (block.div) {
148                 this.groupDiv.removeChild(block.div);
149             }
150             block.div = null;
151         }
152         this.blocks = null;
153
154         OpenLayers.Popup.Anchored.prototype.destroy.apply(this, arguments);
155     },
156
157     /**
158      * APIMethod: setBackgroundColor
159      */
160     setBackgroundColor:function(color) {
161         //does nothing since the framed popup's entire scheme is based on a 
162         // an image -- changing the background color makes no sense. 
163     },
164
165     /**
166      * APIMethod: setBorder
167      */
168     setBorder:function() {
169         //does nothing since the framed popup's entire scheme is based on a 
170         // an image -- changing the popup's border makes no sense. 
171     },
172
173     /**
174      * Method: setOpacity
175      * Sets the opacity of the popup.
176      * 
177      * Parameters:
178      * opacity - {float} A value between 0.0 (transparent) and 1.0 (solid).   
179      */
180     setOpacity:function(opacity) {
181         //does nothing since we suppose that we'll never apply an opacity
182         // to a framed popup
183     },
184
185     /**
186      * APIMethod: setSize
187      * Overridden here, because we need to update the blocks whenever the size
188      *     of the popup has changed.
189      * 
190      * Parameters:
191      * contentSize - {<OpenLayers.Size>} the new size for the popup's 
192      *     contents div (in pixels).
193      */
194     setSize:function(contentSize) { 
195         OpenLayers.Popup.Anchored.prototype.setSize.apply(this, arguments);
196
197         this.updateBlocks();
198     },
199
200     /**
201      * Method: updateRelativePosition
202      * When the relative position changes, we need to set the new padding 
203      *     BBOX on the popup, reposition the close div, and update the blocks.
204      */
205     updateRelativePosition: function() {
206
207         //update the padding
208         this.padding = this.positionBlocks[this.relativePosition].padding;
209
210         //update the position of our close box to new padding
211         if (this.closeDiv) {
212             // use the content div's css padding to determine if we should
213             //  padd the close div
214             var contentDivPadding = this.getContentDivPadding();
215
216             this.closeDiv.style.right = contentDivPadding.right + 
217                                         this.padding.right + "px";
218             this.closeDiv.style.top = contentDivPadding.top + 
219                                       this.padding.top + "px";
220         }
221
222         this.updateBlocks();
223     },
224
225     /** 
226      * Method: calculateNewPx
227      * Besides the standard offset as determined by the Anchored class, our 
228      *     Framed popups have a special 'offset' property for each of their 
229      *     positions, which is used to offset the popup relative to its anchor.
230      * 
231      * Parameters:
232      * px - {<OpenLayers.Pixel>}
233      * 
234      * Returns:
235      * {<OpenLayers.Pixel>} The the new px position of the popup on the screen
236      *     relative to the passed-in px.
237      */
238     calculateNewPx:function(px) {
239         var newPx = OpenLayers.Popup.Anchored.prototype.calculateNewPx.apply(
240             this, arguments
241         );
242
243         newPx = newPx.offset(this.positionBlocks[this.relativePosition].offset);
244
245         return newPx;
246     },
247
248     /**
249      * Method: createBlocks
250      */
251     createBlocks: function() {
252         this.blocks = [];
253
254         //since all positions contain the same number of blocks, we can 
255         // just pick the first position and use its blocks array to create
256         // our blocks array
257         var firstPosition = null;
258         for(var key in this.positionBlocks) {
259             firstPosition = key;
260             break;
261         }
262         
263         var position = this.positionBlocks[firstPosition];
264         for (var i = 0; i < position.blocks.length; i++) {
265
266             var block = {};
267             this.blocks.push(block);
268
269             var divId = this.id + '_FrameDecorationDiv_' + i;
270             block.div = OpenLayers.Util.createDiv(divId, 
271                 null, null, null, "absolute", null, "hidden", null
272             );
273
274             var imgId = this.id + '_FrameDecorationImg_' + i;
275             var imageCreator = 
276                 (this.isAlphaImage) ? OpenLayers.Util.createAlphaImageDiv
277                                     : OpenLayers.Util.createImage;
278
279             block.image = imageCreator(imgId, 
280                 null, this.imageSize, this.imageSrc, 
281                 "absolute", null, null, null
282             );
283
284             block.div.appendChild(block.image);
285             this.groupDiv.appendChild(block.div);
286         }
287     },
288
289     /**
290      * Method: updateBlocks
291      * Internal method, called on initialize and when the popup's relative
292      *     position has changed. This function takes care of re-positioning
293      *     the popup's blocks in their appropropriate places.
294      */
295     updateBlocks: function() {
296         if (!this.blocks) {
297             this.createBlocks();
298         }
299         
300         if (this.size && this.relativePosition) {
301             var position = this.positionBlocks[this.relativePosition];
302             for (var i = 0; i < position.blocks.length; i++) {
303     
304                 var positionBlock = position.blocks[i];
305                 var block = this.blocks[i];
306     
307                 // adjust sizes
308                 var l = positionBlock.anchor.left;
309                 var b = positionBlock.anchor.bottom;
310                 var r = positionBlock.anchor.right;
311                 var t = positionBlock.anchor.top;
312     
313                 //note that we use the isNaN() test here because if the 
314                 // size object is initialized with a "auto" parameter, the 
315                 // size constructor calls parseFloat() on the string, 
316                 // which will turn it into NaN
317                 //
318                 var w = (isNaN(positionBlock.size.w)) ? this.size.w - (r + l) 
319                                                       : positionBlock.size.w;
320     
321                 var h = (isNaN(positionBlock.size.h)) ? this.size.h - (b + t) 
322                                                       : positionBlock.size.h;
323     
324                 block.div.style.width = (w < 0 ? 0 : w) + 'px';
325                 block.div.style.height = (h < 0 ? 0 : h) + 'px';
326     
327                 block.div.style.left = (l != null) ? l + 'px' : '';
328                 block.div.style.bottom = (b != null) ? b + 'px' : '';
329                 block.div.style.right = (r != null) ? r + 'px' : '';            
330                 block.div.style.top = (t != null) ? t + 'px' : '';
331     
332                 block.image.style.left = positionBlock.position.x + 'px';
333                 block.image.style.top = positionBlock.position.y + 'px';
334             }
335     
336             this.contentDiv.style.left = this.padding.left + "px";
337             this.contentDiv.style.top = this.padding.top + "px";
338         }
339     },
340
341     CLASS_NAME: "OpenLayers.Popup.Framed"
342 });