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