OpenLayers OpenLayers

Ticket #926: popups.patch

File popups.patch, 51.1 kB (added by euzuro, 2 years ago)

Latest patch file for new framed popups.

  • theme/default/style.css

    old new  
    113113 
    114114.olPopupContent { 
    115115    padding:5px; 
     116    overflow: hidden; 
    116117}     
    117118.olControlNavToolbar {  
    118119    width:0px; 
  • theme/default/framedCloud.css

    old new  
     1 
     2.olFramedCloudPopupContent { 
     3    padding: 5px; 
     4    overflow: auto; 
     5} 
  • lib/OpenLayers/Popup/FramedCloud.js

    old new  
     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/Framed.js 
     7 * @requires OpenLayers/Util.js 
     8 */ 
     9 
     10/** 
     11 * Class: OpenLayers.Popup.FramedCloud 
     12 *  
     13 * Inherits from:  
     14 *  - <OpenLayers.Popup.Framed> 
     15 */ 
     16OpenLayers.Popup.FramedCloud =  
     17  OpenLayers.Class(OpenLayers.Popup.Framed, { 
     18 
     19    /** 
     20     * APIProperty: autoSize 
     21     * {Boolean} Framed Cloud is autosizing by default. 
     22     */ 
     23    autoSize: true, 
     24     
     25    /** 
     26     * APIProperty: panMapIfOutOfView 
     27     * {Boolean} Framed Cloud does pan into view by default. 
     28     */ 
     29    panMapIfOutOfView: true, 
     30     
     31    /** 
     32     * Property: imageSrc 
     33     * {String} 
     34     */ 
     35    imageSrc: OpenLayers.Util.getImagesLocation() + 'cloud-popup-relative.png', 
     36     
     37    /** 
     38     * APIProperty: imageSize 
     39     * {<OpenLayers.Size>} 
     40     */ 
     41    imageSize: new OpenLayers.Size(676, 736), 
     42     
     43    /**  
     44     * APIProperty: fixedRelativePosition 
     45     * {Boolean} The Framed Cloud popup works in just one fixed position. 
     46     */ 
     47    fixedRelativePosition: false, 
     48     
     49    /** 
     50     * Property: positionBlocks 
     51     * {Object} Hash of differen position blocks, keyed by relativePosition 
     52     *     two-character code string (ie "tl", "tr", "bl", "br") 
     53     */ 
     54    positionBlocks: { 
     55        "tl": { 
     56            'offset': new OpenLayers.Pixel(55, -10), 
     57            'padding': new OpenLayers.Bounds(15, 75, 60, 15), 
     58            'blocks': [ 
     59                { // top-left 
     60                    size: new OpenLayers.Size('auto', 'auto'), 
     61                    anchor: new OpenLayers.Bounds(0, 68, 38, 0), 
     62                    position: new OpenLayers.Pixel(0, 0) 
     63                }, 
     64                { //top-right 
     65                    size: new OpenLayers.Size(38, 'auto'), 
     66                    anchor: new OpenLayers.Bounds(null, 68, 0, 0), 
     67                    position: new OpenLayers.Pixel(-638, 0) 
     68                }, 
     69                { //bottom-left 
     70                    size: new OpenLayers.Size('auto', 39), 
     71                    anchor: new OpenLayers.Bounds(0, 29, 97, null), 
     72                    position: new OpenLayers.Pixel(0, -629) 
     73                }, 
     74                { // stem 
     75                    size: new OpenLayers.Size(97, 68), 
     76                    anchor: new OpenLayers.Bounds(null, 0, 0, null), 
     77                    position: new OpenLayers.Pixel(0, -668) 
     78                } 
     79            ] 
     80        }, 
     81        "tr": { 
     82            'offset': new OpenLayers.Pixel(-35, -10), 
     83            'padding': new OpenLayers.Bounds(15, 75, 60, 15), 
     84            'blocks': [ 
     85                { // top-left 
     86                    size: new OpenLayers.Size('auto', 'auto'), 
     87                    anchor: new OpenLayers.Bounds(0, 68, 38, 0), 
     88                    position: new OpenLayers.Pixel(0, 0) 
     89                }, 
     90                { //top-right 
     91                    size: new OpenLayers.Size(38, 'auto'), 
     92                    anchor: new OpenLayers.Bounds(null, 68, 0, 0), 
     93                    position: new OpenLayers.Pixel(-638, 0) 
     94                }, 
     95                { //bottom-left 
     96                    size: new OpenLayers.Size('auto', 39), 
     97                    anchor: new OpenLayers.Bounds(0, 29, 38, null), 
     98                    position: new OpenLayers.Pixel(0, -629) 
     99                }, 
     100                { //bottom-right 
     101                    size: new OpenLayers.Size(38, 39), 
     102                    anchor: new OpenLayers.Bounds(null, 29, 0, null), 
     103                    position: new OpenLayers.Pixel(-638, -629) 
     104                }, 
     105                { // stem 
     106                    size: new OpenLayers.Size(80, 68), 
     107                    anchor: new OpenLayers.Bounds(0, 0, null, null), 
     108                    position: new OpenLayers.Pixel(-215, -668) 
     109                } 
     110            ] 
     111        }, 
     112        "bl": { 
     113            'offset': new OpenLayers.Pixel(55, 0), 
     114            'padding': new OpenLayers.Bounds(15, 45, 60, 53), 
     115            'blocks': [ 
     116                { // top-left 
     117                    size: new OpenLayers.Size('auto', 'auto'), 
     118                    anchor: new OpenLayers.Bounds(0, null, null, 38), 
     119                    position: new OpenLayers.Pixel(0, 0) 
     120                }, 
     121                { //top-right 
     122                    size: new OpenLayers.Size(38, 'auto'), 
     123                    anchor: new OpenLayers.Bounds(null, null, 0, 38), 
     124                    position: new OpenLayers.Pixel(-638, 0) 
     125                }, 
     126                { //bottom-left 
     127                    size: new OpenLayers.Size('auto', 39), 
     128                    anchor: new OpenLayers.Bounds(0, 0, null, null), 
     129                    position: new OpenLayers.Pixel(0, -629) 
     130                }, 
     131                { //bottom-right 
     132                    size: new OpenLayers.Size(38, 39), 
     133                    anchor: new OpenLayers.Bounds(null, 0, 0, null), 
     134                    position: new OpenLayers.Pixel(-638, -629) 
     135                }, 
     136                { // stem 
     137                    size: new OpenLayers.Size(97, 60), 
     138                    anchor: new OpenLayers.Bounds(null, null, 0, 0), 
     139                    position: new OpenLayers.Pixel(-101, -668) 
     140                } 
     141            ] 
     142        }, 
     143        "br": { 
     144            'offset': new OpenLayers.Pixel(-35, 0), 
     145            'padding': new OpenLayers.Bounds(15, 45, 60, 53), 
     146            'blocks': [ 
     147                { // top-left 
     148                    size: new OpenLayers.Size('auto', 'auto'), 
     149                    anchor: new OpenLayers.Bounds(0, null, null, 38), 
     150                    position: new OpenLayers.Pixel(0, 0) 
     151                }, 
     152                { //top-right 
     153                    size: new OpenLayers.Size(38, 'auto'), 
     154                    anchor: new OpenLayers.Bounds(null, null, 0, 38), 
     155                    position: new OpenLayers.Pixel(-638, 0) 
     156                }, 
     157                { //bottom-left 
     158                    size: new OpenLayers.Size('auto', 39), 
     159                    anchor: new OpenLayers.Bounds(0, 0, null, null), 
     160                    position: new OpenLayers.Pixel(0, -629) 
     161                }, 
     162                { //bottom-right 
     163                    size: new OpenLayers.Size(38, 39), 
     164                    anchor: new OpenLayers.Bounds(null, 0, 0, null), 
     165                    position: new OpenLayers.Pixel(-638, -629) 
     166                }, 
     167                { // stem 
     168                    size: new OpenLayers.Size(81, 60), 
     169                    anchor: new OpenLayers.Bounds(0, null, null, 0), 
     170                    position: new OpenLayers.Pixel(-311, -668) 
     171                } 
     172            ] 
     173        } 
     174    }, 
     175 
     176    /** 
     177     * APIProperty: minSize 
     178     * {<OpenLayers.Size>} 
     179     */ 
     180    minSize: new OpenLayers.Size(105, 10), 
     181     
     182    /** 
     183     * APIProperty: maxSize 
     184     * {<OpenLayers.Size>} 
     185     */ 
     186    maxSize: new OpenLayers.Size(600, 660), 
     187     
     188    /**  
     189     * Constructor: OpenLayers.Popup.FramedCloud 
     190     *  
     191     * Parameters: 
     192     * id - {String} 
     193     * lonlat - {<OpenLayers.LonLat>} 
     194     * size - {<OpenLayers.Size>} 
     195     * contentHTML - {String} 
     196     * anchor - {Object} Object to which we'll anchor the popup. Must expose  
     197     *     a 'size' (<OpenLayers.Size>) and 'offset' (<OpenLayers.Pixel>)  
     198     *     (Note that this is generally an <OpenLayers.Icon>). 
     199     * closeBox - {Boolean} 
     200     * closeBoxCallback - {Function} Function to be called on closeBox click. 
     201     */ 
     202    initialize:function(id, lonlat, size, contentHTML, anchor, closeBox,  
     203                        closeBoxCallback) { 
     204 
     205        OpenLayers.Popup.Framed.prototype.initialize.apply(this, arguments); 
     206        this.contentDiv.className = "olFramedCloudPopupContent"; 
     207    }, 
     208 
     209    /**  
     210     * APIMethod: destroy 
     211     */ 
     212    destroy: function() { 
     213        OpenLayers.Popup.Framed.prototype.destroy.apply(this, arguments); 
     214    }, 
     215 
     216    CLASS_NAME: "OpenLayers.Popup.FramedCloud" 
     217}); 
  • lib/OpenLayers/Popup/AmberCloud.js

    old new  
     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/Framed.js 
     7 * @requires OpenLayers/Util.js 
     8 */ 
     9 
     10/** 
     11 * Class: OpenLayers.Popup.AmberCloud 
     12 *  
     13 * Inherits from:  
     14 *  - <OpenLayers.Popup.Framed> 
     15 */ 
     16OpenLayers.Popup.AmberCloud =  
     17  OpenLayers.Class(OpenLayers.Popup.Framed, { 
     18 
     19    /** 
     20     * APIProperty: autoSize 
     21     * {Boolean} Framed Cloud is autosizing by default. 
     22     */ 
     23    autoSize: true, 
     24     
     25    /** 
     26     * APIProperty: panMapIfOutOfView 
     27     * {Boolean} Framed Cloud does pan into view by default. 
     28     */ 
     29    panMapIfOutOfView: true, 
     30     
     31    /** 
     32     * Property: imageSrc 
     33     * {String} 
     34     */ 
     35    imageSrc: OpenLayers.Util.getImagesLocation() + 'amber-cloud-popup.png', 
     36     
     37    /** 
     38     * APIProperty: imageSize 
     39     * {<OpenLayers.Size>} 
     40     */ 
     41    imageSize: new OpenLayers.Size(598,588), 
     42     
     43    /**  
     44     * APIProperty: fixedRelativePosition 
     45     * {Boolean} The Framed Cloud popup works in just one fixed position. 
     46     */ 
     47    fixedRelativePosition: true, 
     48     
     49    /** 
     50     * APIProperty: relativePosition 
     51     * {String} Framed Cloud popup always goes top right 
     52     */ 
     53    relativePosition: "tr", 
     54 
     55    /** 
     56     * Property: positionBlocks 
     57     * {Object} Hash of differen position blocks, keyed by relativePosition 
     58     *     two-character code string (ie "tl", "tr", "bl", "br") 
     59     */ 
     60    positionBlocks: { 
     61        "tr": { 
     62            'offset': new OpenLayers.Pixel(0, -10), 
     63            'padding': new OpenLayers.Bounds(40, 30, 26, 15), 
     64            'blocks': [ 
     65                { // top-left 
     66                    size: new OpenLayers.Size('auto', 'auto'), 
     67                    anchor: new OpenLayers.Bounds(0, 29, 19, 0), 
     68                    position: new OpenLayers.Pixel(0, 0) 
     69                }, 
     70                { //top-right 
     71                    size: new OpenLayers.Size(19, 'auto'), 
     72                    anchor: new OpenLayers.Bounds(null, 29, 0, 0), 
     73                    position: new OpenLayers.Pixel(-579, 0) 
     74                }, 
     75                { //bottom-right 
     76                    size: new OpenLayers.Size(19, 29), 
     77                    anchor: new OpenLayers.Bounds(null, 0, 0, null), 
     78                    position: new OpenLayers.Pixel(-579, -559) 
     79                }, 
     80                { // stem 
     81                    size: new OpenLayers.Size('auto', 29), 
     82                    anchor: new OpenLayers.Bounds(0, 0, 19, null), 
     83                    position: new OpenLayers.Pixel(0, -559) 
     84                } 
     85            ] 
     86        } 
     87    }, 
     88 
     89    /** 
     90     * APIProperty: minSize 
     91     * {<OpenLayers.Size>} 
     92     */ 
     93    minSize: new OpenLayers.Size(105, 10), 
     94 
     95    /** 
     96     * APIProperty: maxSize 
     97     * {<OpenLayers.Size>} 
     98     */ 
     99    maxSize: new OpenLayers.Size(532, 543), 
     100 
     101    /**  
     102     * Constructor: OpenLayers.Popup.AmberCloud 
     103     *  
     104     * Parameters: 
     105     * id - {String} 
     106     * lonlat - {<OpenLayers.LonLat>} 
     107     * size - {<OpenLayers.Size>} 
     108     * contentHTML - {String} 
     109     * anchor - {Object} Object to which we'll anchor the popup. Must expose  
     110     *     a 'size' (<OpenLayers.Size>) and 'offset' (<OpenLayers.Pixel>)  
     111     *     (Note that this is generally an <OpenLayers.Icon>). 
     112     * closeBox - {Boolean} 
     113     * closeBoxCallback - {Function} Function to be called on closeBox click. 
     114     */ 
     115    initialize:function(id, lonlat, size, contentHTML, anchor, closeBox,  
     116                        closeBoxCallback) { 
     117 
     118        OpenLayers.Popup.Framed.prototype.initialize.apply(this, arguments); 
     119    }, 
     120 
     121    /**  
     122     * APIMethod: destroy 
     123     */ 
     124    destroy: function() { 
     125        OpenLayers.Popup.Framed.prototype.destroy.apply(this, arguments); 
     126    }, 
     127 
     128    CLASS_NAME: "OpenLayers.Popup.AmberCloud" 
     129}); 
  • lib/OpenLayers/Popup/Framed.js

    old new  
     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 */ 
     15OpenLayers.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     * Property: positionBlocks 
     33     * {Object} Hash of different position blocks (Object/Hashs). Each block  
     34     *     will be keyed by a two-character 'relativePosition'  
     35     *     code string (ie "tl", "tr", "bl", "br"). Block properties are  
     36     *     'offset', 'padding' (self-explanatory), and finally the 'blocks' 
     37     *     parameter, which is an array of the block objects.  
     38     *  
     39     *     Each block object must have 'size', 'anchor', and 'position'  
     40     *     properties. 
     41     *  
     42     *     Note that positionBlocks should never be modified at runtime. 
     43     */ 
     44    positionBlocks: null, 
     45     
     46    /** 
     47     * Property: frames 
     48     * {Object} Hash which directly corresponds to the 'positionBlocks' hash,  
     49     *     but which contains the specific DOM instances for this popup.  
     50     *  
     51     *     The frames hash will contain up to four 'position' hashes (one for 
     52     *     each of "tl", "tr", "bl", "br"). Each positon has will have its  
     53     *     own div, and a 'blocks' property, which is an array of the  
     54     *     individual frame divs. 
     55     */ 
     56    frames: null, 
     57 
     58    /**  
     59     * APIProperty: fixedRelativePosition 
     60     * {Boolean} We want the framed popup to work dynamically placed relative 
     61     *     to its anchor but also in just one fixed position. A well designed 
     62     *     framed popup will have the pixels and logic to display itself in  
     63     *     any of the four relative positions, but (understandably), this will 
     64     *     not be the case for all of them. By setting this property to 'true',  
     65     *     framed popup will not recalculate for the best placement each time 
     66     *     it's open, but will always open the same way.  
     67     *     Note that if this is set to true, it is generally advisable to also 
     68     *     set the 'panIntoView' property to true so that the popup can be  
     69     *     scrolled into view (since it will often be offscreen on open) 
     70     *     Default is false. 
     71     */ 
     72    fixedRelativePosition: false, 
     73     
     74    /**  
     75     * Constructor: OpenLayers.Popup.Framed 
     76     *  
     77     * Parameters: 
     78     * id - {String} 
     79     * lonlat - {<OpenLayers.LonLat>} 
     80     * size - {<OpenLayers.Size>} 
     81     * contentHTML - {String} 
     82     * anchor - {Object} Object to which we'll anchor the popup. Must expose  
     83     *     a 'size' (<OpenLayers.Size>) and 'offset' (<OpenLayers.Pixel>)  
     84     *     (Note that this is generally an <OpenLayers.Icon>). 
     85     * closeBox - {Boolean} 
     86     * closeBoxCallback - {Function} Function to be called on closeBox click. 
     87     */ 
     88    initialize:function(id, lonlat, size, contentHTML, anchor, closeBox,  
     89                        closeBoxCallback) { 
     90 
     91        var newAnchor = null; 
     92        if (this.fixedRelativePosition) { 
     93            //based on our decided relativePostion, set the current padding 
     94            // this keeps us from getting into trouble  
     95            this.padding = this.positionBlocks[this.relativePosition].padding; 
     96     
     97            newAnchor = { 
     98                size: new OpenLayers.Size(0,0), 
     99                offset: this.positionBlocks[this.relativePosition].offset 
     100            }; 
     101        } 
     102         
     103        var newArgs = [ 
     104            id, lonlat, size, contentHTML, newAnchor,  
     105            closeBox, closeBoxCallback 
     106        ]; 
     107        OpenLayers.Popup.Anchored.prototype.initialize.apply(this, newArgs); 
     108 
     109        this.contentDiv.style.position = "absolute"; 
     110         
     111        this.contentDiv.style.zIndex = 1; 
     112        if (closeBox) { 
     113            this.closeDiv.style.zIndex = 1; 
     114        } 
     115         
     116        this.groupDiv.style.position = "absolute"; 
     117        this.groupDiv.style.top = "0px"; 
     118        this.groupDiv.style.left = "0px"; 
     119        this.groupDiv.style.height = "100%"; 
     120        this.groupDiv.style.width = "100%"; 
     121         
     122        this.createFrames(); 
     123    }, 
     124 
     125    /**  
     126     * APIMethod: destroy 
     127     */ 
     128    destroy: function() { 
     129        this.imageSrc = null; 
     130        this.imageSize = null; 
     131        this.fixedRelativePosition = false; 
     132     
     133 
     134        var possiblePositions = ['tl', 'tr', 'bl', 'br']; 
     135        for(var i = 0; i < possiblePositions.length; i++) { 
     136            var position = this.frames[possiblePositions[i]]; 
     137            if (position != null) { 
     138                for(var j = 0; j < position.blocks.length; j++) { 
     139                    var block = position.blocks[j]; 
     140                     
     141                    if (block.image) { 
     142                        block.div.removeChild(block.image); 
     143                    } 
     144                    block.image = null; 
     145                                         
     146                    if (block.div) { 
     147                        position.div.removeChild(block.div); 
     148                    } 
     149                    block.div = null;                                         
     150                } 
     151                if (position.div) { 
     152                    this.groupDiv.removeChild(position.div); 
     153                } 
     154                position.div = null; 
     155                delete this.frames[possiblePositions[i]]; 
     156            } 
     157        } 
     158        this.frames = null; 
     159 
     160        OpenLayers.Popup.Anchored.prototype.destroy.apply(this, arguments);         
     161    }, 
     162 
     163    /**  
     164     * APIMethod: setSize 
     165     *  
     166     * Parameters: 
     167     * size {OpenLayers.Size} - Desired size of the content of the popup. 
     168     */ 
     169    setSize: function(size) { 
     170 
     171        // Call the Popup's setSize() directly (the Anchored popup's setSize() 
     172        //  does nothing for us except call moveTo() before we're ready.  
     173        // This will take care of setting the popup's 'div' and 'contentDiv'  
     174        //  to the size specified (or the max/min popup size if extreme). 
     175        OpenLayers.Popup.prototype.setSize.apply(this, arguments); 
     176         
     177        // since the 'size' we specified as an argument here is setting the  
     178        //  size of the *content* div, we now need to go back and change  
     179        //  the popup's 'size' property and its main div's dimensions to  
     180        //  reflect the *actual* size of the whole popup (content + padding). 
     181        //  
     182        this.size = this.size.clone(); 
     183         
     184        //this is a workaround since API respect won't let us mandate  
     185        // padding be a Bounds object. This needs to be removed in 3.0 
     186        // 
     187        this.fixPadding(); 
     188             
     189        this.size.w += this.padding.left + this.padding.right; 
     190        this.size.h += this.padding.top + this.padding.bottom; 
     191 
     192        this.div.style.width = this.size.w + "px"; 
     193        this.div.style.height = this.size.h + "px"; 
     194         
     195        if ((this.lonlat) && (this.map)) { 
     196            var px = this.map.getLayerPxFromLonLat(this.lonlat); 
     197            if (px) { 
     198                this.moveTo(px);            
     199            } 
     200        } 
     201         
     202        this.updateFrames(); 
     203    }, 
     204     
     205    /**  
     206     * Method: calculateRelativePosition 
     207     * Because we want to give the Framed the ability to *not* be  
     208     *     positioned relative to its anchor (ie always "tr"), we overrride 
     209     *     this function from the Anchored popup and only actually make the  
     210     *     call to the superclass if the 'fixedRelativePosition' property is  
     211     *     false. 
     212     *  
     213     * Parameters: 
     214     * px - {<OpenLayers.Pixel>} 
     215     *  
     216     * Returns: 
     217     * {String} The relative position ("br" "tr" "tl "bl") at which the popup 
     218     *     should be placed. 
     219     */ 
     220    calculateRelativePosition: function(px) { 
     221        var relativePosition = this.relativePosition; 
     222        if (!this.fixedRelativePosition) { 
     223            relativePosition =  
     224                OpenLayers.Popup.Anchored.prototype.calculateRelativePosition.apply(this, arguments); 
     225 
     226            //update the frame's padding and offset for the new  
     227            // relative position 
     228            this.updateRelativePosition(relativePosition); 
     229        } 
     230 
     231        return relativePosition; 
     232    }, 
     233     
     234    /** 
     235     * Method: updateRelativePosition 
     236     *  
     237     * Parameters: 
     238     * relativePosition - {String}} 
     239     */ 
     240    updateRelativePosition: function(relativePosition) { 
     241        //update the anchor offset 
     242        this.anchor.offset = this.positionBlocks[relativePosition].offset; 
     243         
     244        //update the padding 
     245        this.padding = this.positionBlocks[relativePosition].padding; 
     246         
     247        //update the position of our close box to new padding 
     248        this.closeDiv.style.right = this.padding.right - 30 + "px"; 
     249        this.closeDiv.style.top = this.padding.top + "px"; 
     250         
     251    }, 
     252 
     253    /** 
     254     * Method: createFrames 
     255     */ 
     256    createFrames: function() { 
     257 
     258        this.frames = {}; 
     259         
     260        for (var pos in this.positionBlocks) { 
     261 
     262            var fPosition = { 
     263                'blocks': [] 
     264            }; 
     265            this.frames[pos] = fPosition; 
     266 
     267            fPosition.div = OpenLayers.Util.createDiv(pos + "-popup",  
     268                null, null, null, 'relative' 
     269            ); 
     270            fPosition.div.style.height = '100%'; 
     271            fPosition.div.style.width = '100%'; 
     272            this.groupDiv.appendChild(fPosition.div); 
     273 
     274            var position = this.positionBlocks[pos]; 
     275            for (var i = 0; i < position.blocks.length; i++) { 
     276     
     277                var fBlock = {}; 
     278                fPosition.blocks.push(fBlock); 
     279     
     280                var divId = this.id + '_FrameDecorationDiv_' + i; 
     281                fBlock.div = OpenLayers.Util.createDiv(divId,  
     282                    null, null, null, "absolute", null, "hidden", null 
     283                ); 
     284     
     285                var imgId = this.id + '_FrameDecorationImg_' + i; 
     286                fBlock.image = OpenLayers.Util.createAlphaImageDiv(imgId,  
     287                    null, this.imageSize, this.imageSrc,  
     288                    "absolute", null, null, null 
     289                ); 
     290     
     291                fBlock.div.appendChild(fBlock.image); 
     292                fPosition.div.appendChild(fBlock.div); 
     293            } 
     294        } 
     295    }, 
     296     
     297    /** 
     298     * Method: updateFrames 
     299     * Internal method, called on initialize and when the popup's relative 
     300     *     position has changed. This function takes care of re-positioning 
     301     *     the corresponding popups in their appropropriate places. 
     302     */ 
     303    updateFrames: function() { 
     304 
     305        for (var pos in this.positionBlocks) { 
     306            var position = this.positionBlocks[pos]; 
     307            var fPosition = this.frames[pos]; 
     308 
     309            if (pos != this.relativePosition) { 
     310                OpenLayers.Element.hide(fPosition.div); 
     311            } else { 
     312                OpenLayers.Element.show(fPosition.div); 
     313                 
     314                for (var i = 0; i < position.blocks.length; i++) { 
     315     
     316                    var block = position.blocks[i]; 
     317                    var fBlock = fPosition.blocks[i]; 
     318     
     319                    // adjust sizes 
     320                    var l = block.anchor.left; 
     321                    var b = block.anchor.bottom; 
     322                    var r = block.anchor.right; 
     323                    var t = block.anchor.top; 
     324                     
     325                    //note that we use the isNaN() test here because if the  
     326                    // size object is initialized with a "auto" parameter, the  
     327                    // size constructor calls parseFloat() on the string,  
     328                    // which will turn it into NaN 
     329                    // 
     330                    var w = (isNaN(block.size.w)) ? this.size.w - (r + l)  
     331                                                  : block.size.w; 
     332         
     333                    var h = (isNaN(block.size.h)) ? this.size.h - (b + t)  
     334                                                  : block.size.h; 
     335                          
     336                    fBlock.div.style.width = w + 'px'; 
     337                    fBlock.div.style.height = h + 'px'; 
     338         
     339                    fBlock.div.style.left = (l != null) ? l + 'px' : ''; 
     340                    fBlock.div.style.bottom = (b != null) ? b + 'px' : ''; 
     341                    fBlock.div.style.right = (r != null) ? r + 'px' : '';             
     342                    fBlock.div.style.top = (t != null) ? t + 'px' : ''; 
     343                     
     344                    fBlock.image.style.left = block.position.x + 'px'; 
     345                    fBlock.image.style.top = block.position.y + 'px'; 
     346                } 
     347                 
     348            } 
     349        } 
     350         
     351        //this is a workaround since API respect won't let us mandate  
     352        // padding be a Bounds object. This needs to be removed in 3.0 
     353        // 
     354        this.fixPadding(); 
     355             
     356        this.contentDiv.style.left = this.padding.left + "px"; 
     357        this.contentDiv.style.top = this.padding.top + "px"; 
     358 
     359    }, 
     360 
     361    /** 
     362     * APIMethod: setBackgroundColor 
     363     */ 
     364    setBackgroundColor:function(color) { 
     365        //does nothing since the framed popup's entire scheme is based on a  
     366        // an image -- changing the background color makes no sense.  
     367    }, 
     368     
     369    /** 
     370     * APIMethod: setBorder 
     371     */ 
     372    setBorder:function() { 
     373        //does nothing since the framed popup's entire scheme is based on a  
     374        // an image -- changing the popup's border makes no sense.  
     375    }, 
     376 
     377    CLASS_NAME: "OpenLayers.Popup.Framed" 
     378}); 
  • lib/OpenLayers/Popup/AnchoredBubble.js

    old new  
    9090 
    9191            var contentSize = this.size.clone(); 
    9292            contentSize.h -= (2 * OpenLayers.Popup.AnchoredBubble.CORNER_SIZE); 
    93             contentSize.h -= (2 * this.padding); 
    94      
     93             
     94            //this is a workaround since API respect won't let us mandate  
     95            // padding be a Bounds object. This needs to be removed in 3.0 
     96            // 
     97            this.fixPadding(); 
     98             
     99            contentSize.h -= this.padding.top + this.padding.bottom; 
     100 
    95101            this.contentDiv.style.height = contentSize.h + "px"; 
    96102            this.contentDiv.style.width  = contentSize.w + "px"; 
    97103             
  • lib/OpenLayers/Popup/Anchored.js

    old new  
    7272        //calculate relative position 
    7373        this.relativePosition = this.calculateRelativePosition(px); 
    7474         
    75         return OpenLayers.Popup.prototype.draw.apply(this, arguments); 
     75        return OpenLayers.Popup.prototype.draw.apply(this, [px]); 
    7676    }, 
    7777     
    7878    /**  
  • lib/OpenLayers/Popup.js

    old new  
    8686     
    8787    /**  
    8888     * Property: groupDiv  
    89      * {DOMElement} the parent of <OpenLayers.Popup.contentDiv>  
     89     * {DOMElement} First and only child of 'div'. The group Div contains the 
     90     *     'contentDiv' and the 'closeDiv'. 
    9091     */ 
    9192    groupDiv: null, 
    9293 
     
    9798    closeDiv: null, 
    9899 
    99100    /**  
     101     * APIProperty: autoSize 
     102     * {Boolean} Resize the popup to auto-fit the contents. 
     103     *     Default is false. 
     104     */ 
     105    autoSize: false, 
     106 
     107    /** 
     108     * APIProperty: minSize 
     109     * {<OpenLayers.Size>} Minimum size allowed for the popup's contents. 
     110     */ 
     111    minSize: null, 
     112 
     113    /** 
     114     * APIProperty: maxSize 
     115     * {<OpenLayers.Size>} Maximum size allowed for the popup's contents. 
     116     */ 
     117    maxSize: null, 
     118 
     119    /**  
    100120     * Property: padding  
    101      * {int} the internal padding of the content div. 
     121     * {int or <OpenLayers.Bounds>} The internal padding of the content div. 
     122     *     In order to not break API, we must continue to support this  
     123     *     property being set as an integer. Really, though, we'd like to  
     124     *     have this specified as a Bounds object so that user can specify 
     125     *     distinct left, top, right, bottom paddings. With the 3.0 release 
     126     *     we can make this only a bounds. 
    102127     */ 
    103128    padding: 5, 
    104129 
     130    /**  
     131     * Method: fixPadding 
     132     * To be removed in 3.0, this function merely helps us to deal with the  
     133     *     case where the user may have set an integer value for padding,  
     134     *     instead of an <OpenLayers.Bounds> object. 
     135     */ 
     136    fixPadding: function() { 
     137        if (typeof this.padding == "number") { 
     138            this.padding = new OpenLayers.Bounds( 
     139                this.padding, this.padding, this.padding, this.padding 
     140            ); 
     141        } 
     142    }, 
    105143 
     144    /** 
     145     * APIProperty: margin 
     146     * {<OpenLayers.Bounds>} Outside margin of the popup. Used to prevent  
     147     *     the popup from getting too close to the map border. 
     148     */ 
     149    margin: null, 
     150 
     151    /** 
     152     * APIProperty: panMapIfOutOfView 
     153     * {Boolean} When drawn, pan map such that the entire popup is visible in 
     154     *     the current viewport (if necessary). 
     155     *     Default is false. 
     156     */ 
     157    panMapIfOutOfView: false, 
     158     
    106159    /**  
    107160     * Property: map  
    108161     * {<OpenLayers.Map>} this gets set in Map.js when the popup is added to the map 
     
    136189                                  : new OpenLayers.Size( 
    137190                                                   OpenLayers.Popup.WIDTH, 
    138191                                                   OpenLayers.Popup.HEIGHT); 
     192 
     193        //set default margin 
     194        this.margin = new OpenLayers.Bounds(5, 5, 5, 5); 
     195 
    139196        if (contentHTML != null) {  
    140197             this.contentHTML = contentHTML; 
    141198        } 
     
    153210 
    154211        var id = this.div.id + "_contentDiv"; 
    155212        this.contentDiv = OpenLayers.Util.createDiv(id, null, this.size.clone(),  
    156                                                     null, "relative", null, 
    157                                                     "hidden"); 
     213                                                    null, "relative"); 
    158214        this.contentDiv.className = 'olPopupContent';                                             
    159215        this.groupDiv.appendChild(this.contentDiv); 
    160216        this.div.appendChild(this.groupDiv); 
    161217 
    162218        if (closeBox) { 
    163            // close icon 
    164             var closeSize = new OpenLayers.Size(17,17); 
    165             var img = OpenLayers.Util.getImagesLocation() + "close.gif"; 
    166             this.closeDiv = OpenLayers.Util.createAlphaImageDiv( 
    167                 this.id + "_close", null, closeSize, img 
    168             ); 
    169             this.closeDiv.style.right = this.padding + "px"; 
    170             this.closeDiv.style.top = this.padding + "px"; 
    171             this.groupDiv.appendChild(this.closeDiv); 
     219            this.addCloseBox(closeBoxCallback); 
     220        }  
    172221 
    173             var closePopup = closeBoxCallback || function(e) { 
    174                 this.hide(); 
    175                 OpenLayers.Event.stop(e); 
    176             }; 
    177             OpenLayers.Event.observe(this.closeDiv, "click",  
    178                     OpenLayers.Function.bindAsEventListener(closePopup, this)); 
    179  
    180         } 
    181  
    182222        this.registerEvents(); 
    183223    }, 
    184224 
     
    194234        this.events.destroy(); 
    195235        this.events = null; 
    196236        this.div = null; 
     237         
     238        OpenLayers.Event.stopObservingElement(this.closeDiv);  
     239        this.closeDiv = null; 
     240         
     241        this.autoSize = null; 
     242        this.minSize = null; 
     243        this.maxSize = null; 
     244        this.padding = null; 
     245        this.margin = null; 
     246        this.panMapIfOutOfView = null; 
    197247    }, 
    198248 
    199249    /**  
     
    213263            } 
    214264        } 
    215265         
    216         this.setSize(); 
     266        if (!this.autoSize) { 
     267            this.setSize(); 
     268        } 
    217269        this.setBackgroundColor(); 
    218270        this.setOpacity(); 
    219271        this.setBorder(); 
     
    248300            this.div.style.left = px.x + "px"; 
    249301            this.div.style.top = px.y + "px"; 
    250302        } 
     303         
     304        if (this.panMapIfOutOfView) { 
     305            this.panIntoView(); 
     306        }     
     307         
    251308    }, 
    252309 
    253310    /** 
     
    295352        if (size != undefined) { 
    296353            this.size = size;  
    297354        } 
     355 
     356        this.size = this.getSafeContentSize(this.size); 
    298357         
    299358        if (this.div != null) { 
    300359            this.div.style.width = this.size.w + "px"; 
     
    372431            this.contentHTML = contentHTML; 
    373432        } 
    374433         
     434        if (this.autoSize) { 
     435            // determine actual render dimensions 
     436            var realSize =  
     437                OpenLayers.Util.getRenderedDimensions(this.contentHTML); 
     438             
     439            this.setSize(realSize);             
     440        }         
     441 
    375442        if (this.contentDiv != null) { 
    376443            this.contentDiv.innerHTML = this.contentHTML; 
    377444        }     
    378445    }, 
    379446     
    380447 
     448    /** 
     449     * APIMethod: getSafeContentSize 
     450     *  
     451     * Parameters: 
     452     * size - {<OpenLayers.Size>} Desired size to make the popup. 
     453     *  
     454     * Returns: 
     455     * {<OpenLayers.Size>} A size to make the popup which is neither smaller 
     456     *     than the specified minimum size, nor bigger than the maximum  
     457     *     size (which is calculated relative to the size of the viewport). 
     458     */ 
     459    getSafeContentSize: function(size) { 
     460 
     461        var safeContentSize = size.clone(); 
     462 
     463      // prevent the popup from being smaller than a specified minimal size 
     464        if (this.minSize) { 
     465            safeContentSize.w = Math.max(safeContentSize.w, this.minSize.w); 
     466            safeContentSize.h = Math.max(safeContentSize.h, this.minSize.h); 
     467        } 
     468 
     469      // prevent the popup from being bigger than a specified maximum size 
     470        if (this.maxSize) { 
     471            safeContentSize.w = Math.min(safeContentSize.w, this.maxSize.w); 
     472            safeContentSize.h = Math.min(safeContentSize.h, this.maxSize.h); 
     473        } 
     474         
     475      //make sure the desired size to set doesn't result in a popup that  
     476      // is bigger than the map's viewport. 
     477      // 
     478        if (this.map && this.map.size) { 
     479 
     480          // Note that there *was* a reference to a  
     481          // 'OpenLayers.Popup.SCROLL_BAR_WIDTH' constant here, with special  
     482          // tolerance for it and everything... but it was never defined in the  
     483          // first place, so I don't know what to think. 
     484          // 
     485           
     486            //this is a workaround since API respect won't let us mandate  
     487            // padding be a Bounds object. This needs to be removed in 3.0 
     488            // 
     489            this.fixPadding(); 
     490 
     491            var maxY = this.map.size.h -  
     492                (this.margin.top + this.padding.top + 
     493                 this.margin.bottom + this.padding.bottom); 
    381494     
     495            var maxX = this.map.size.w -  
     496                (this.margin.left + this.padding.left +  
     497                 this.margin.right + this.padding.right); 
     498     
     499            safeContentSize.w = Math.min(safeContentSize.w, maxX); 
     500            safeContentSize.h = Math.min(safeContentSize.h, maxY); 
     501        } 
     502         
     503        return safeContentSize; 
     504    }, 
     505     
     506    /** 
     507     * Method: addCloseBox 
     508     *  
     509     * Parameters: 
     510     * callback - {Function} The callback to be called when the close button 
     511     *     is clicked. 
     512     */ 
     513    addCloseBox: function(callback) { 
     514 
     515       // close icon 
     516        var closeSize = new OpenLayers.Size(17,17); 
     517        var img = OpenLayers.Util.getImagesLocation() + "close.gif"; 
     518        this.closeDiv = OpenLayers.Util.createAlphaImageDiv( 
     519            this.id + "_close", null, closeSize, img 
     520        ); 
     521         
     522        //this is a workaround since API respect won't let us mandate  
     523        // padding be a Bounds object. This needs to be removed in 3.0 
     524        // 
     525        this.fixPadding(); 
     526         
     527        this.closeDiv.style.right = this.padding.right + "px"; 
     528        this.closeDiv.style.top = this.padding.top + "px"; 
     529        this.groupDiv.appendChild(this.closeDiv); 
     530 
     531        var closePopup = callback || function(e) { 
     532            this.hide(); 
     533            OpenLayers.Event.stop(e); 
     534        }; 
     535        OpenLayers.Event.observe(this.closeDiv, "click",  
     536                OpenLayers.Function.bindAsEventListener(closePopup, this)); 
     537    }, 
     538 
     539    /** 
     540     * Method: panIntoView 
     541     * Pans the map such that the popup is totaly viewable (if necessary) 
     542     */ 
     543    panIntoView: function() { 
     544         
     545        var mapSize = this.map.getSize(); 
     546     
     547        //start with the top left corner of the popup, in px,  
     548        // relative to the viewport 
     549        var origTL = this.map.getViewPortPxFromLayerPx( new OpenLayers.Pixel( 
     550            parseInt(this.div.style.left), 
     551            parseInt(this.div.style.top) 
     552        )); 
     553        var newTL = origTL.clone(); 
     554     
     555        //new left (compare to margins, using this.size to calculate right) 
     556        if (origTL.x < this.margin.left) { 
     557            newTL.x = this.margin.left; 
     558        } else  
     559        if ( (origTL.x + this.size.w) > (mapSize.w - this.margin.right)) { 
     560            newTL.x = mapSize.w - this.margin.right - this.size.w; 
     561        } 
     562         
     563        //new top (compare to margins, using this.size to calculate bottom) 
     564        if (origTL.y < this.margin.top) { 
     565            newTL.y = this.margin.top; 
     566        } else  
     567        if ( (origTL.y + this.size.h) > (mapSize.h - this.margin.bottom)) { 
     568            newTL.y = mapSize.h - this.margin.bottom - this.size.h; 
     569        } 
     570         
     571        var dx = origTL.x - newTL.x; 
     572        var dy = origTL.y - newTL.y; 
     573         
     574        this.map.pan(dx, dy); 
     575    }, 
     576 
    382577    /**  
    383578     * Method: registerEvents 
    384579     * Registers events on the popup. 
  • lib/OpenLayers/Util.js

    old new  
    13231323     
    13241324    return browserName; 
    13251325}; 
     1326 
     1327 
     1328 
     1329     
     1330/** 
     1331 * Method: getRenderedDimensions 
     1332 * Renders the contentHTML offscreen to determine actual dimensions for 
     1333 *     popup sizing. As we need layout to determine dimensions the content 
     1334 *     is rendered -9999px to the left and absolute to ensure the  
     1335 *     scrollbars do not flicker 
     1336 *      
     1337 * Returns: 
     1338 * {OpenLayers.Size} 
     1339 */ 
     1340OpenLayers.Util.getRenderedDimensions = function(contentHTML) { 
     1341     
     1342    // create temp container div with restricted size 
     1343    var container = document.createElement("div"); 
     1344    container.style.overflow= ""; 
     1345    container.style.position = "absolute"; 
     1346    container.style.left = "-9999px"; 
     1347         
     1348    // create temp content div and assign content 
     1349    var content = document.createElement("div"); 
     1350    content.innerHTML = contentHTML; 
     1351     
     1352    // add content to restricted container  
     1353    container.appendChild(content); 
     1354     
     1355    // append container to body for rendering 
     1356    document.body.appendChild(container); 
     1357     
     1358    // calculate scroll width of content and add corners and shadow width 
     1359    var w = parseInt(content.scrollWidth);// 
     1360     
     1361    // update container width to allow height to adjust 
     1362    container.style.width = w + "px"; 
     1363     
     1364    // capture height and add shadow and corner image widths 
     1365    var h = parseInt(content.scrollHeight); 
     1366         
     1367    // remove elements 
     1368    container.removeChild(content); 
     1369    document.body.removeChild(container); 
     1370     
     1371    return new OpenLayers.Size(w, h); 
     1372}; 
     1373     
  • lib/OpenLayers.js

    old new  
    119119            "OpenLayers/Layer/TileCache.js", 
    120120            "OpenLayers/Popup/Anchored.js", 
    121121            "OpenLayers/Popup/AnchoredBubble.js", 
     122            "OpenLayers/Popup/Framed.js", 
     123            "OpenLayers/Popup/FramedCloud.js", 
     124            "OpenLayers/Popup/AmberCloud.js", 
    122125            "OpenLayers/Feature.js", 
    123126            "OpenLayers/Feature/Vector.js", 
    124127            "OpenLayers/Feature/WFS.js", 
  • examples/framedPopups.html

    old new  
     1<html xmlns="http://www.w3.org/1999/xhtml" debug="true"> 
     2  <head> 
     3    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" /> 
     4    <style type="text/css"> 
     5        #map { 
     6            width: 800px; 
     7            height: 500px; 
     8            border: 1px solid black; 
     9        } 
     10    </style> 
     11 
     12    <link rel="stylesheet" href="../theme/default/framedCloud.css" type="text/css" /> 
     13 
     14    <script src="../lib/Firebug/firebug.js"></script> 
     15    <script src="../lib/OpenLayers.js"></script> 
     16    <script type="text/javascript"> 
     17        var map; 
     18        var layer, markers; 
     19        var cloudFeature, cloudMarker, cloudPopup; 
     20        var amberFeature, amberMarker, amberPopup; 
     21         
     22        function init(){ 
     23            map = new OpenLayers.Map('map'); 
     24 
     25            layer = new OpenLayers.Layer.WMS(  
     26                "OpenLayers WMS",  
     27                "http://labs.metacarta.com/wms/vmap0",  
     28                {layers: 'basic'}  
     29            ); 
     30            map.addLayer(layer); 
     31 
     32            markers = new OpenLayers.Layer.Markers("zibo"); 
     33            map.addLayer(markers); 
     34 
     35            map.addControl(new OpenLayers.Control.LayerSwitcher()); 
     36            map.setCenter(new OpenLayers.LonLat(0, 0), 3); 
     37 
     38            addMarkers(); 
     39        } 
     40         
     41        function addMarkers() { 
     42 
     43            var ll = new OpenLayers.LonLat(-10,-10); 
     44            cloudFeature = new OpenLayers.Feature(layer, ll);  
     45            cloudFeature.popupClass = OpenLayers.Popup.FramedCloud; 
     46//            cloudFeature.data.popupContentHTML = "Lorem Ipsum is simply dummy text of the printing and <br/>typesetting industry. Lorem <br/>Ipsum has been the <br/>industry's standard dummy text <br/>ever since the 1500s, when <br/>an unknown printer took a galley of <br/>type and scrambled it to make a type specimen book. It has <br/>survived not only five centuries, but also <br/>the leap into electronic typesetting, <br/>remaining <br/>essentially <br/>unchanged. It was popularised in <br/>the 1960s with <br/>the <br/>release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop <br/>publishing software like Aldus PageMaker including versions of Lorem Ipsum."; 
     47            cloudFeature.data.popupContentHTML = "Lorem Ipsum is simply dummy text of the printing and <br/>typesetting industry. Lorem <br/>Ipsum has been the <br/>industry's standard dummy text <br/>ever since the 1500s, when <br/>an unknown printer took a galley of <br/>type and scrambled it to make a type specimen book. It has <br/>survived not only five centuries, but also <br/>the leap into electronic typesetting, <br/>remaining <br/>essentially <br/>unchanged. It was popularised in <br/>the 1960s with <br/>the <br/>release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop <br/>publishing software like Aldus PageMaker including versions of Lorem Ipsum." + 
     48                "Lorem Ipsum is simply dummy text of the printing and <br/>typesetting industry. Lorem <br/>Ipsum has been the <br/>industry's standard dummy text <br/>ever since the 1500s, when <br/>an unknown printer took a galley of <br/>type and scrambled it to make a type specimen book. It has <br/>survived not only five centuries, but also <br/>the leap into electronic typesetting, <br/>remaining <br/>essentially <br/>unchanged. It was popularised in <br/>the 1960s with <br/>the <br/>release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop <br/>publishing software like Aldus PageMaker including versions of Lorem Ipsum." + 
     49                "Lorem Ipsum is simply dummy text of the printing and <br/>typesetting industry. Lorem <br/>Ipsum has been the <br/>industry's standard dummy text <br/>ever since the 1500s, when <br/>an unknown printer took a galley of <br/>type and scrambled it to make a type specimen book. It has <br/>survived not only five centuries, but also <br/>the leap into electronic typesetting, <br/>remaining <br/>essentially <br/>unchanged. It was popularised in <br/>the 1960s with <br/>the <br/>release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop <br/>publishing software like Aldus PageMaker including versions of Lorem Ipsum."; 
     50             
     51            cloudMarker = cloudFeature.createMarker(); 
     52            cloudMarker.events.register( 
     53                "mousedown", cloudFeature, mousedown 
     54            ); 
     55            markers.addMarker(cloudMarker); 
     56 
     57            ll = new OpenLayers.LonLat(10,10); 
     58            amberFeature = new OpenLayers.Feature(layer, ll);  
     59            amberFeature.popupClass = OpenLayers.Popup.AmberCloud; 
     60            amberFeature.data.popupContentHTML = "Message: Hi all, I would love some advice. My sister and <br/>I are planning a trip to Providenciales, but have found many of the beautiful hotels, condos, and <br/>villas to be beyond our limited price range. So, we'<br/>ve come up with a hairbrained scheme: we'<br/>ll stay at Club Med (for only $749 per person for 7 <br/>nights) but spend most of our time (and many meals) away from the summer <br/>camp campus. Do you think this is a good option? Or <br/>would we do better just to stay in the Comfort Suites? We're most interested in <br/>snorkeling and lounging on the sand in beach chairs. Would <br/>we have to walk far from Club Med to reach the best Grace <br/>Bay snorkeling spots? Is it feasible to walk to good restaurants from Club Med<br/>? We certainly don't want to be stuck there! Many thanks <br/>in advance for your help!!!"; 
     61            amberMarker = amberFeature.createMarker(); 
     62            amberMarker.events.register( 
     63                "mousedown", amberFeature, mousedown 
     64            ); 
     65            markers.addMarker(amberMarker); 
     66        } 
     67         
     68        function mousedown(evt) { 
     69 
     70            if (this.popup != null) { 
     71                map.removePopup(this.popup); 
     72                this.popup.destroy(); 
     73                this.popup = null; 
     74            } 
     75             
     76            this.popup = this.createPopup(true); 
     77            map.addPopup(this.popup); 
     78            this.popup.show(); 
     79            OpenLayers.Event.stop(evt); 
     80        }         
     81 
     82    </script> 
     83  </head> 
     84  <body onload="init()"> 
     85  <h1 id="title">Popup Mayhem</h1> 
     86 
     87  <div id="tags"> 
     88  </div> 
     89      <p id="shortdesc"> 
     90          All kinds of ways to create and interact with Popups. 
     91      </p> 
     92 
     93      <div id="map"></div> 
     94 
     95      <br/>    
     96      <br/>    
     97      Below you can find the way bubble decoration dimensions are calculated.<br />  
     98      <img src="../img/popup_orange_dimensions.png" />  
     99      <br/>    
     100       
     101   </div> 
     102  </body> 
     103</html>