OpenLayers OpenLayers

Changeset 6718

Show
Ignore:
Timestamp:
03/31/08 00:43:36 (9 months ago)
Author:
euzuro
Message:

Adding support for new generation 'framed' popups. This patch includes numerous improvements to the main popups, including the addition of autoSizing, panIntoView, and full support for overflow:auto of the contents div. Thanks go out to the CloudAmber folks, to Pierre in la belle France, to the guys at TOPP and of course, to senior cr5 for his patience and help in the last and final stretch. this is a huge improvement in the popup arena and couldn't have been done without the broad help of everyone out there in the community. Thank you everyone for making this possible. Big step for OpenLayers. (Closes #926)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/openlayers/examples/popups.html

    r6497 r6718  
    7373         
    7474        function mousedown(evt) { 
    75              // check to see if the popup was hidden by the close box 
    76              // if so, then destroy it before continuing 
    77             if (popup != null) { 
    78                 if (!popup.visible()) { 
    79                     markers.map.removePopup(popup); 
    80                     popup.destroy(); 
    81                     popup = null; 
    82                 } 
    83             } 
    8475            if (popup == null) { 
    8576                popup = feature.createPopup(true); 
    86                 popup.setContentHTML("<a href='http://www.somethingconstructive.net' target='_blank'>click me</a>"); 
     77                popup.setContentHTML("<div style='background-color:red; width:150;height:100'><a href='http://www.somethingconstructive.net' target='_blank'>click me</a></div>"); 
    8778                popup.setBackgroundColor("yellow"); 
    8879                popup.setOpacity(0.7); 
    8980                markers.map.addPopup(popup); 
    9081            } else { 
    91                 markers.map.removePopup(popup); 
    92                 popup.destroy(); 
    93                 popup = null; 
    94             } 
     82                popup.toggle(); 
     83               } 
    9584            OpenLayers.Event.stop(evt); 
    9685        }         
  • trunk/openlayers/lib/OpenLayers.js

    r6645 r6718  
    121121            "OpenLayers/Popup/Anchored.js", 
    122122            "OpenLayers/Popup/AnchoredBubble.js", 
     123            "OpenLayers/Popup/Framed.js", 
     124            "OpenLayers/Popup/FramedCloud.js", 
    123125            "OpenLayers/Feature.js", 
    124126            "OpenLayers/Feature/Vector.js", 
  • trunk/openlayers/lib/OpenLayers/Control.js

    r6711 r6718  
    8080 
    8181    /**  
    82      * Property: allowSelection 
    83      * {Boolean} By deafault, controls do not allow selection, because 
    84      * it may interfere with map dragging. If this is true, OpenLayers 
    85      * will not prevent selection of the control. 
    86      * Default is false. 
    87      */ 
    88     allowSelection: false,   
    89  
    90     /**  
    9182     * Property: displayClass  
    9283     * {string}  This property is used for CSS related to the drawing of the 
     
    250241            this.div = OpenLayers.Util.createDiv(this.id); 
    251242            this.div.className = this.displayClass; 
    252             if (!this.allowSelection) { 
    253                 this.div.className += " olControlNoSelect"; 
    254                 this.div.setAttribute("unselectable", "on", 0); 
    255                 this.div.onselectstart = function() { return(false); };  
    256             }     
    257243            if (this.title != "") { 
    258244                this.div.title = this.title; 
  • trunk/openlayers/lib/OpenLayers/Map.js

    r6661 r6718  
    355355     
    356356    /** 
     357     * Property: paddingForPopups 
     358     * {<OpenLayers.Bounds>} Outside margin of the popup. Used to prevent  
     359     *     the popup from getting too close to the map border. 
     360     */ 
     361    paddingForPopups : null, 
     362     
     363    /** 
    357364     * Constructor: OpenLayers.Map 
    358365     * Constructor for a new OpenLayers.Map instance. 
     
    385392         
    386393        this.maxExtent = new OpenLayers.Bounds(-180, -90, 180, 90); 
     394         
     395        this.paddingForPopups = new OpenLayers.Bounds(15, 15, 15, 15); 
    387396 
    388397        this.theme = OpenLayers._getScriptLocation() +  
     
    526535            this.events.unregister("resize", this, this.updateSize); 
    527536        }     
     537         
     538        this.paddingForPopups = null;     
    528539 
    529540        if (this.controls != null) { 
  • trunk/openlayers/lib/OpenLayers/Popup.js

    r6430 r6718  
    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, 
     
    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. 
    102      */ 
    103     padding: 5, 
    104  
    105  
     121     * {int or <OpenLayers.Bounds>} An extra opportunity to specify internal  
     122     *     padding of the content div inside the popup. This was originally 
     123     *     confused with the css padding as specified in style.css's  
     124     *     'olPopupContent' class. We would like to get rid of this altogether, 
     125     *     except that it does come in handy for the framed and anchoredbubble 
     126     *     popups, who need to maintain yet another barrier between their  
     127     *     content and the outer border of the popup itself.  
     128     *  
     129     *     Note that in order to not break API, we must continue to support  
     130     *     this property being set as an integer. Really, though, we'd like to  
     131     *     have this specified as a Bounds object so that user can specify 
     132     *     distinct left, top, right, bottom paddings. With the 3.0 release 
     133     *     we can make this only a bounds. 
     134     */ 
     135    padding: 0, 
     136 
     137    /**  
     138     * Method: fixPadding 
     139     * To be removed in 3.0, this function merely helps us to deal with the  
     140     *     case where the user may have set an integer value for padding,  
     141     *     instead of an <OpenLayers.Bounds> object. 
     142     */ 
     143    fixPadding: function() { 
     144        if (typeof this.padding == "number") { 
     145            this.padding = new OpenLayers.Bounds( 
     146                this.padding, this.padding, this.padding, this.padding 
     147            ); 
     148        } 
     149    }, 
     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  
     
    148201        this.div.className = 'olPopup'; 
    149202         
    150         this.groupDiv = OpenLayers.Util.createDiv(null, null, null,  
     203        var groupDivId = this.id + "_GroupDiv"; 
     204        this.groupDiv = OpenLayers.Util.createDiv(groupDivId, null, null,  
    151205                                                    null, "relative", null, 
    152206                                                    "hidden"); 
     
    154208        var id = this.div.id + "_contentDiv"; 
    155209        this.contentDiv = OpenLayers.Util.createDiv(id, null, this.size.clone(),  
    156                                                     null, "relative", null, 
    157                                                     "hidden"); 
     210                                                    null, "relative"); 
    158211        this.contentDiv.className = 'olPopupContent';                                             
    159212        this.groupDiv.appendChild(this.contentDiv); 
     
    161214 
    162215        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); 
    172  
    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         } 
     216            this.addCloseBox(closeBoxCallback); 
     217        }  
    181218 
    182219        this.registerEvents(); 
     
    188225     */ 
    189226    destroy: function() { 
     227 
     228        this.id = null; 
     229        this.lonlat = null; 
     230        this.size = null; 
     231        this.contentHTML = null; 
     232         
     233        this.backgroundColor = null; 
     234        this.opacity = null; 
     235        this.border = null; 
     236         
     237        this.events.destroy(); 
     238        this.events = null; 
     239         
     240        if (this.closeDiv) { 
     241            OpenLayers.Event.stopObservingElement(this.closeDiv);  
     242            this.groupDiv.removeChild(this.closeDiv); 
     243        } 
     244        this.closeDiv = null; 
     245         
     246        this.div.removeChild(this.groupDiv); 
     247        this.groupDiv = null; 
     248 
    190249        if (this.map != null) { 
    191250            this.map.removePopup(this); 
    192             this.map = null; 
    193         } 
    194         this.events.destroy(); 
    195         this.events = null; 
     251        } 
     252        this.map = null; 
    196253        this.div = null; 
     254         
     255        this.autoSize = null; 
     256        this.minSize = null; 
     257        this.maxSize = null; 
     258        this.padding = null; 
     259        this.panMapIfOutOfView = null; 
    197260    }, 
    198261 
     
    214277        } 
    215278         
    216         this.setSize(); 
     279        //listen to movestart, moveend to disable overflow (FF bug) 
     280        if (OpenLayers.Util.getBrowserName() == 'firefox') { 
     281            this.map.events.register("movestart", this, function() { 
     282                var style = document.defaultView.getComputedStyle( 
     283                    this.contentDiv, null 
     284                ); 
     285                var currentOverflow = style.getPropertyValue("overflow"); 
     286                if (currentOverflow != "hidden") { 
     287                    this.contentDiv._oldOverflow = currentOverflow; 
     288                    this.contentDiv.style.overflow = "hidden"; 
     289                } 
     290            }); 
     291            this.map.events.register("moveend", this, function() { 
     292                var oldOverflow = this.contentDiv._oldOverflow; 
     293                if (oldOverflow) { 
     294                    this.contentDiv.style.overflow = oldOverflow; 
     295                    this.contentDiv._oldOverflow = null; 
     296                } 
     297            }); 
     298        } 
     299 
     300        this.moveTo(px); 
     301        if (!this.autoSize) { 
     302            this.setSize(this.size); 
     303        } 
    217304        this.setBackgroundColor(); 
    218305        this.setOpacity(); 
    219306        this.setBorder(); 
    220307        this.setContentHTML(); 
    221         this.moveTo(px); 
     308         
     309        if (this.panMapIfOutOfView) { 
     310            this.panIntoView(); 
     311        }     
    222312 
    223313        return this.div; 
     
    266356     */ 
    267357    toggle: function() { 
    268         OpenLayers.Element.toggle(this.div); 
     358        if (this.visible()) { 
     359            this.hide(); 
     360        } else { 
     361            this.show(); 
     362        } 
    269363    }, 
    270364 
     
    275369    show: function() { 
    276370        OpenLayers.Element.show(this.div); 
     371 
     372        if (this.panMapIfOutOfView) { 
     373            this.panIntoView(); 
     374        }     
    277375    }, 
    278376 
     
    290388     * 
    291389     * Parameters: 
    292      * size - {<OpenLayers.Size>} the new size of the popup in pixels. 
     390     * size - {<OpenLayers.Size>} the new size of the popup's contents div 
     391     *     (in pixels). 
    293392     */ 
    294393    setSize:function(size) {  
    295         if (size != undefined) { 
    296             this.size = size;  
    297         } 
    298          
     394        this.size = size;  
     395 
     396        var contentSize = this.size.clone(); 
     397         
     398        // if our contentDiv has a css 'padding' set on it by a stylesheet, we  
     399        //  must add that to the desired "size".  
     400        var contentDivPadding = this.getContentDivPadding(); 
     401        var wPadding = contentDivPadding.left + contentDivPadding.right; 
     402        var hPadding = contentDivPadding.top + contentDivPadding.bottom; 
     403 
     404        // take into account the popup's 'padding' property 
     405        this.fixPadding(); 
     406        wPadding += this.padding.left + this.padding.right; 
     407        hPadding += this.padding.top + this.padding.bottom; 
     408 
     409        // make extra space for the close div 
     410        if (this.closeDiv) { 
     411            var closeDivWidth = parseInt(this.closeDiv.style.width); 
     412            wPadding += closeDivWidth + contentDivPadding.right; 
     413        } 
     414 
     415        //increase size of the main popup div to take into account the  
     416        // users's desired padding and close div.         
     417        this.size.w += wPadding; 
     418        this.size.h += hPadding; 
     419 
     420        //now if our browser is IE, we need to actually make the contents  
     421        // div itself bigger to take its own padding into effect. this makes  
     422        // me want to shoot someone, but so it goes. 
     423        if (OpenLayers.Util.getBrowserName() == "msie") { 
     424            contentSize.w += contentDivPadding.left + contentDivPadding.right; 
     425            contentSize.h += contentDivPadding.bottom + contentDivPadding.top; 
     426        } 
     427 
    299428        if (this.div != null) { 
    300429            this.div.style.width = this.size.w + "px"; 
     
    302431        } 
    303432        if (this.contentDiv != null){ 
    304             this.contentDiv.style.width = this.size.w + "px"; 
    305             this.contentDiv.style.height = this.size.h + "px"; 
     433            this.contentDiv.style.width = contentSize.w + "px"; 
     434            this.contentDiv.style.height = contentSize.h + "px"; 
    306435        } 
    307436    },   
    308437 
    309438    /** 
    310     * Method: setBackgroundColor 
    311     * Sets the background color of the popup. 
    312    
    313     * Parameters: 
    314     * color - {String} the background color.  eg "#FFBBBB" 
    315     */ 
     439    * Method: setBackgroundColor 
     440    * Sets the background color of the popup. 
     441   
     442    * Parameters: 
     443    * color - {String} the background color.  eg "#FFBBBB" 
     444    */ 
    316445    setBackgroundColor:function(color) {  
    317446        if (color != undefined) { 
     
    374503        } 
    375504         
     505        if (this.autoSize) { 
     506 
     507            // determine actual render dimensions of the contents 
     508            var realSize =  
     509                 OpenLayers.Util.getRenderedDimensions(this.contentHTML); 
     510 
     511            // is the "real" size of the div is safe to display in our map? 
     512            var safeSize = this.getSafeContentSize(realSize); 
     513 
     514            var newSize = null; 
     515              
     516            if (safeSize.equals(realSize)) { 
     517                //real size of content is small enough to fit on the map,  
     518                // so we use real size. 
     519                newSize = realSize; 
     520 
     521            } else { 
     522 
     523                //make a new OL.Size object with the clipped dimensions  
     524                // set or null if not clipped. 
     525                var fixedSize = new OpenLayers.Size(); 
     526                fixedSize.w = (safeSize.w < realSize.w) ? safeSize.w : null; 
     527                fixedSize.h = (safeSize.h < realSize.h) ? safeSize.h : null; 
     528             
     529                if (fixedSize.w && fixedSize.h) { 
     530                    //content is too big in both directions, so we will use  
     531                    // max popup size (safeSize), knowing well that it will  
     532                    // overflow both ways.                 
     533                    newSize = safeSize; 
     534                } else { 
     535                    //content is clipped in only one direction, so we need to  
     536                    // run getRenderedDimensions() again with a fixed dimension 
     537                    var clippedSize = OpenLayers.Util.getRenderedDimensions( 
     538                        this.contentHTML, fixedSize 
     539                    ); 
     540                     
     541                    //if the clipped size is still the same as the safeSize,  
     542                    // that means that our content must be fixed in the  
     543                    // offending direction. If overflow is 'auto', this means  
     544                    // we are going to have a scrollbar for sure, so we must  
     545                    // adjust for that. 
     546                    // 
     547                    var currentOverflow = OpenLayers.Element.getStyle( 
     548                        this.contentDiv, "overflow" 
     549                    ); 
     550                    if ( (currentOverflow != "hidden") &&  
     551                         (clippedSize.equals(safeSize)) ) { 
     552                        var scrollBar = OpenLayers.Util.getScrollbarWidth(); 
     553                        if (fixedSize.w) { 
     554                            clippedSize.h += scrollBar; 
     555                        } else { 
     556                            clippedSize.w += scrollBar; 
     557                        } 
     558                    } 
     559                     
     560                    newSize = this.getSafeContentSize(clippedSize); 
     561                } 
     562            }                         
     563            this.setSize(newSize);      
     564        }         
     565 
    376566        if (this.contentDiv != null) { 
    377567            this.contentDiv.innerHTML = this.contentHTML; 
     
    380570     
    381571 
    382      
     572    /** 
     573     * APIMethod: getSafeContentSize 
     574     *  
     575     * Parameters: 
     576     * size - {<OpenLayers.Size>} Desired size to make the popup. 
     577     *  
     578     * Returns: 
     579     * {<OpenLayers.Size>} A size to make the popup which is neither smaller 
     580     *     than the specified minimum size, nor bigger than the maximum  
     581     *     size (which is calculated relative to the size of the viewport). 
     582     */ 
     583    getSafeContentSize: function(size) { 
     584 
     585        var safeContentSize = size.clone(); 
     586 
     587        // if our contentDiv has a css 'padding' set on it by a stylesheet, we  
     588        //  must add that to the desired "size".  
     589        var contentDivPadding = this.getContentDivPadding(); 
     590        var wPadding = contentDivPadding.left + contentDivPadding.right; 
     591        var hPadding = contentDivPadding.top + contentDivPadding.bottom; 
     592 
     593        // take into account the popup's 'padding' property 
     594        this.fixPadding(); 
     595        wPadding += this.padding.left + this.padding.right; 
     596        hPadding += this.padding.top + this.padding.bottom; 
     597 
     598        if (this.closeDiv) { 
     599            var closeDivWidth = parseInt(this.closeDiv.style.width); 
     600            wPadding += closeDivWidth + contentDivPadding.right; 
     601        } 
     602 
     603        // prevent the popup from being smaller than a specified minimal size 
     604        if (this.minSize) { 
     605            safeContentSize.w = Math.max(safeContentSize.w,  
     606                (this.minSize.w - wPadding)); 
     607            safeContentSize.h = Math.max(safeContentSize.h,  
     608                (this.minSize.h - hPadding)); 
     609        } 
     610 
     611        // prevent the popup from being bigger than a specified maximum size 
     612        if (this.maxSize) { 
     613            safeContentSize.w = Math.min(safeContentSize.w,  
     614                (this.maxSize.w - wPadding)); 
     615            safeContentSize.h = Math.min(safeContentSize.h,  
     616                (this.maxSize.h - hPadding)); 
     617        } 
     618         
     619        //make sure the desired size to set doesn't result in a popup that  
     620        // is bigger than the map's viewport. 
     621        // 
     622        if (this.map && this.map.size) { 
     623 
     624            // Note that there *was* a reference to a 
     625            // 'OpenLayers.Popup.SCROLL_BAR_WIDTH' constant here, with special 
     626            // tolerance for it and everything... but it was never defined in 
     627            // the first place, so I don't know what to think. 
     628           
     629            var maxY = this.map.size.h -  
     630                this.map.paddingForPopups.top -  
     631                this.map.paddingForPopups.bottom -  
     632                hPadding; 
     633     
     634            var maxX = this.map.size.w -  
     635                this.map.paddingForPopups.left -  
     636                this.map.paddingForPopups.right -  
     637                wPadding; 
     638     
     639            safeContentSize.w = Math.min(safeContentSize.w, maxX); 
     640            safeContentSize.h = Math.min(safeContentSize.h, maxY); 
     641        } 
     642         
     643        return safeContentSize; 
     644    }, 
     645     
     646    /** 
     647     * Method: getContentDivPadding 
     648     * Glorious, oh glorious hack in order to determine the css 'padding' of  
     649     *     the contentDiv. IE/Opera return null here unless we actually add the  
     650     *     popup's main 'div' element (which contains contentDiv) to the DOM.  
     651     *     So we make it invisible and then add it to the document temporarily.  
     652     * 
     653     *     Once we've taken the padding readings we need, we then remove it  
     654     *     from the DOM (it will actually get added to the DOM in  
     655     *     Map.js's addPopup) 
     656     * 
     657     * Returns: 
     658     * {<OpenLayers.Bounds>} 
     659     */ 
     660    getContentDivPadding: function() { 
     661 
     662        //use cached value if we have it 
     663        var contentDivPadding = this._contentDivPadding; 
     664        if (!contentDivPadding) { 
     665            //make the div invisible and add it to the page         
     666            this.div.style.display = "none"; 
     667            document.body.appendChild(this.div); 
     668     
     669            //read the padding settings from css, put them in an OL.Bounds         
     670            contentDivPadding = new OpenLayers.Bounds( 
     671                OpenLayers.Element.getStyle(this.contentDiv, "padding-left"), 
     672                OpenLayers.Element.getStyle(this.contentDiv, "padding-bottom"), 
     673                OpenLayers.Element.getStyle(this.contentDiv, "padding-right"), 
     674                OpenLayers.Element.getStyle(this.contentDiv, "padding-top") 
     675            ); 
     676     
     677            //cache the value 
     678            this._contentDivPadding = contentDivPadding; 
     679     
     680            //remove the div from the page and make it visible again 
     681            document.body.removeChild(this.div); 
     682            this.div.style.display = ""; 
     683        } 
     684        return contentDivPadding; 
     685    }, 
     686 
     687    /** 
     688     * Method: addCloseBox 
     689     *  
     690     * Parameters: 
     691     * callback - {Function} The callback to be called when the close button 
     692     *     is clicked. 
     693     */ 
     694    addCloseBox: function(callback) { 
     695 
     696        this.closeDiv = OpenLayers.Util.createDiv( 
     697            this.id + "_close", null, new OpenLayers.Size(17, 17) 
     698        ); 
     699        this.closeDiv.className = "olPopupCloseBox";  
     700         
     701        // use the content div's css padding to determine if we should 
     702        //  padd the close div 
     703        var contentDivPadding = this.getContentDivPadding(); 
     704          
     705        this.closeDiv.style.right = contentDivPadding.right + "px"; 
     706        this.closeDiv.style.top = contentDivPadding.top + "px"; 
     707        this.groupDiv.appendChild(this.closeDiv); 
     708 
     709        var closePopup = callback || function(e) { 
     710            this.hide(); 
     711            OpenLayers.Event.stop(e); 
     712        }; 
     713        OpenLayers.Event.observe(this.closeDiv, "click",  
     714                OpenLayers.Function.bindAsEventListener(closePopup, this)); 
     715    }, 
     716 
     717    /** 
     718     * Method: panIntoView 
     719     * Pans the map such that the popup is totaly viewable (if necessary) 
     720     */ 
     721    panIntoView: function() { 
     722         
     723        var mapSize = this.map.getSize(); 
     724     
     725        //start with the top left corner of the popup, in px,  
     726        // relative to the viewport 
     727        var origTL = this.map.getViewPortPxFromLayerPx( new OpenLayers.Pixel( 
     728            parseInt(this.div.style.left), 
     729            parseInt(this.div.style.top) 
     730        )); 
     731        var newTL = origTL.clone(); 
     732     
     733        //new left (compare to margins, using this.size to calculate right) 
     734        if (origTL.x < this.map.paddingForPopups.left) { 
     735            newTL.x = this.map.paddingForPopups.left; 
     736        } else  
     737        if ( (origTL.x + this.size.w) > (mapSize.w - this.map.paddingForPopups.right)) { 
     738            newTL.x = mapSize.w - this.map.paddingForPopups.right - this.size.w; 
     739        } 
     740         
     741        //new top (compare to margins, using this.size to calculate bottom) 
     742        if (origTL.y < this.map.paddingForPopups.top) { 
     743            newTL.y = this.map.paddingForPopups.top; 
     744        } else  
     745        if ( (origTL.y + this.size.h) > (mapSize.h - this.map.paddingForPopups.bottom)) { 
     746            newTL.y = mapSize.h - this.map.paddingForPopups.bottom - this.size.h; 
     747        } 
     748         
     749        var dx = origTL.x - newTL.x; 
     750        var dy = origTL.y - newTL.y; 
     751         
     752        this.map.pan(dx, dy); 
     753    }, 
     754 
    383755    /**  
    384756     * Method: registerEvents 
  • trunk/openlayers/lib/OpenLayers/Popup/Anchored.js

    r5614 r6718  
    5454    }, 
    5555 
    56     /**  
    57      * Method: draw 
     56    /** 
     57     * APIMethod: destroy 
     58     */ 
     59    destroy: function() { 
     60        this.anchor = null; 
     61        this.relativePosition = null; 
     62         
     63        OpenLayers.Popup.prototype.destroy.apply(this, arguments);         
     64    }, 
     65 
     66    /** 
     67     * APIMethod: show 
     68     * Overridden from Popup since user might hide popup and then show() it  
     69     *     in a new location (meaning we might want to update the relative 
     70     *     position on the show) 
     71     */ 
     72    show: function() { 
     73        this.updatePosition(); 
     74        OpenLayers.Popup.prototype.show.apply(this, arguments); 
     75    }, 
     76 
     77    /** 
     78     * Method: moveTo 
     79     * Since the popup is moving to a new px, it might need also to be moved 
     80     *     relative to where the marker is. We first calculate the new  
     81     *     relativePosition, and then we calculate the new px where we will  
     82     *     put the popup, based on the new relative position.  
     83     *  
     84     *     If the relativePosition has changed, we must also call  
     85     *     updateRelativePosition() to make any visual changes to the popup  
     86     *     which are associated with putting it in a new relativePosition. 
    5887     *  
    5988     * Parameters: 
    6089     * px - {<OpenLayers.Pixel>} 
    61      *  
    62      * Returns:  
    63      * {DOMElement} Reference to a div that contains the drawn popup. 
    6490     */ 
    65     draw: function(px) { 
    66         if (px == null) { 
    67             if ((this.lonlat != null) && (this.map != null)) { 
    68                 px = this.map.getLayerPxFromLonLat(this.lonlat); 
    69             } 
    70         } 
    71          
    72         //calculate relative position 
     91    moveTo: function(px) { 
     92        var oldRelativePosition = this.relativePosition; 
    7393        this.relativePosition = this.calculateRelativePosition(px); 
    7494         
    75         return OpenLayers.Popup.prototype.draw.apply(this, arguments); 
     95        var newPx = this.calculateNewPx(px); 
     96         
     97        var newArguments = new Array(newPx);         
     98        OpenLayers.Popup.prototype.moveTo.apply(this, newArguments); 
     99         
     100        //if this move has caused the popup to change its relative position,  
     101        // we need to make the appropriate cosmetic changes. 
     102        if (this.relativePosition != oldRelativePosition) { 
     103            this.updateRelativePosition(); 
     104        } 
    76105    }, 
     106 
     107    /** 
     108     * APIMethod: setSize 
     109     *  
     110     * Parameters: 
     111     * size - {<OpenLayers.Size>} 
     112     */ 
     113    setSize:function(size) {  
     114        OpenLayers.Popup.prototype.setSize.apply(this, arguments); 
     115 
     116        if ((this.lonlat) && (this.map)) { 
     117            var px = this.map.getLayerPxFromLonLat(this.lonlat); 
     118            this.moveTo(px); 
     119        } 
     120    },   
    77121     
    78122    /**  
     
    96140 
    97141    /** 
    98      * Method: moveTo 
    99      * Since the popup is moving to a new px, it might need also to be moved 
    100      *     relative to where the marker is. 
     142     * Method: updateRelativePosition 
     143     * The popup has been moved to a new relative location, so we may want to  
     144     *     make some cosmetic adjustments to it.  
    101145     *  
    102      * Parameters: 
    103      * px - {<OpenLayers.Pixel>} 
     146     *     Note that in the classic Anchored popup, there is nothing to do  
     147     *     here, since the popup looks exactly the same in all four positions. 
     148     *     Subclasses such as the AnchoredBubble and Framed, however, will  
     149     *     want to do something special here. 
    104150     */ 
    105     moveTo: function(px) { 
    106         this.relativePosition = this.calculateRelativePosition(px); 
    107          
    108         var newPx = this.calculateNewPx(px); 
    109          
    110         var newArguments = new Array(newPx);         
    111         OpenLayers.Popup.prototype.moveTo.apply(this, newArguments); 
     151    updateRelativePosition: function() { 
     152        //to be overridden by subclasses 
    112153    }, 
    113      
    114     /** 
    115      * Method: setSize 
    116      *  
    117      * Parameters: 
    118      * size - {<OpenLayers.Size>} 
    119      */ 
    120     setSize:function(size) {  
    121         OpenLayers.Popup.prototype.setSize.apply(this, arguments); 
    122154 
    123         if ((this.lonlat) && (this.map)) { 
    124             var px = this.map.getLayerPxFromLonLat(this.lonlat); 
    125             this.moveTo(px); 
    126         } 
    127     },   
    128      
    129155    /**  
    130156     * Method: calculateNewPx 
  • trunk/openlayers/lib/OpenLayers/Popup/AnchoredBubble.js

    r5614 r6718  
    3939    initialize:function(id, lonlat, size, contentHTML, anchor, closeBox, 
    4040                        closeBoxCallback) { 
     41         
     42        this.padding = new OpenLayers.Bounds( 
     43            0, OpenLayers.Popup.AnchoredBubble.CORNER_SIZE, 
     44            0, OpenLayers.Popup.AnchoredBubble.CORNER_SIZE 
     45        ); 
    4146        OpenLayers.Popup.Anchored.prototype.initialize.apply(this, arguments); 
    4247    }, 
     
    6570 
    6671    /** 
    67      * Method: moveTo 
    68      * The popup may have been moved to a new relative location, in which case 
     72     * Method: updateRelativePosition 
     73     * The popup has been moved to a new relative location, in which case 
    6974     *     we will want to re-do the rico corners. 
    70      *  
    71      * Parameters: 
    72      * px - {<OpenLayers.Pixel>} 
    7375     */ 
    74     moveTo: function(px) { 
    75         OpenLayers.Popup.Anchored.prototype.moveTo.apply(this, arguments); 
    76         this.setRicoCorners(!this.rounded); 
    77         this.rounded = true; 
     76    updateRelativePosition: function() { 
     77        this.setRicoCorners(); 
    7878    }, 
    7979 
     
    8686    setSize:function(size) {  
    8787        OpenLayers.Popup.Anchored.prototype.setSize.apply(this, arguments); 
    88          
    89         if (this.contentDiv != null) { 
    9088 
    91             var contentSize = this.size.clone(); 
    92             contentSize.h -= (2 * OpenLayers.Popup.AnchoredBubble.CORNER_SIZE); 
    93             contentSize.h -= (2 * this.padding); 
    94      
    95             this.contentDiv.style.height = contentSize.h + "px"; 
    96             this.contentDiv.style.width  = contentSize.w + "px"; 
    97              
    98             if (this.map) { 
    99                 //size has changed - must redo corners         
    100                 this.setRicoCorners(!this.rounded); 
    101                 this.rounded = true; 
    102             }     
    103         } 
     89        this.setRicoCorners(); 
    10490    },   
    10591 
     
    118104            if (this.contentDiv != null) { 
    119105                this.div.style.background = "transparent"; 
    120                 OpenLayers.Rico.Corner.changeColor(this.contentDiv,  
     106                OpenLayers.Rico.Corner.changeColor(this.groupDiv,  
    121107                                                   this.backgroundColor); 
    122108            } 
     
    155141     * Method: setRicoCorners 
    156142     * Update RICO corners according to the popup's current relative postion. 
    157      *   
    158      * Parameters: 
    159      * firstTime - {Boolean} This the first time the corners are being rounded. 
    160143     */ 
    161     setRicoCorners:function(firstTime) { 
     144    setRicoCorners:function() { 
    162145     
    163146        var corners = this.getCornersToRound(this.relativePosition); 
     
    167150                         blend: false}; 
    168151 
    169         if (firstTime) { 
     152        if (!this.rounded) { 
    170153            OpenLayers.Rico.Corner.round(this.div, options); 
     154            this.rounded = true; 
    171155        } else { 
    172156            OpenLayers.Rico.Corner.reRound(this.groupDiv, options); 
  • trunk/openlayers/lib/OpenLayers/Util.js

    r6673 r6718  
    13221322    return browserName; 
    13231323}; 
     1324 
     1325 
     1326 
     1327     
     1328/** 
     1329 * Method: getRenderedDimensions 
     1330 * Renders the contentHTML offscreen to determine actual dimensions for 
     1331 *     popup sizing. As we need layout to determine dimensions the content 
     1332 *     is rendered -9999px to the left and absolute to ensure the  
     1333 *     scrollbars do not flicker 
     1334 *      
     1335 * Parameters: 
     1336 * size - {<OpenLayers.Size>} If either the 'w' or 'h' properties is  
     1337 *     specified, we fix that dimension of the div to be measured. This is  
     1338 *     useful in the case where we have a limit in one dimension and must  
     1339 *     therefore meaure the flow in the other dimension. 
     1340 *  
     1341 * Returns: 
     1342 * {OpenLayers.Size} 
     1343 */ 
     1344OpenLayers.Util.getRenderedDimensions = function(contentHTML, size) { 
     1345     
     1346    var w = h = null; 
     1347     
     1348    // create temp container div with restricted size 
     1349    var container = document.createElement("div"); 
     1350    container.style.overflow= ""; 
     1351    container.style.position = "absolute"; 
     1352    container.style.left = "-9999px"; 
     1353         
     1354    //fix a dimension, if specified. 
     1355    if (size) { 
     1356        if (size.w) { 
     1357            w = container.style.width = size.w; 
     1358        } else if (size.h) { 
     1359            h = container.style.height = size.h; 
     1360        } 
     1361    } 
     1362     
     1363    // create temp content div and assign content 
     1364    var content = document.createElement("div"); 
     1365    content.innerHTML = contentHTML; 
     1366     
     1367    // add content to restricted container  
     1368