1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | /* Copyright (c) 2006-2010 by OpenLayers Contributors (see authors.txt for * full list of contributors). Published under the Clear BSD license. * See http://svn.openlayers.org/trunk/openlayers/license.txt for the * full text of the license. */ /** * @requires OpenLayers/Popup.js */ /** * Class: OpenLayers.Popup.Anchored * * Inherits from: * - <OpenLayers.Popup> */ OpenLayers.Popup.Anchored = OpenLayers.Class(OpenLayers.Popup, { /** * Parameter: relativePosition * {String} Relative position of the popup ("br", "tr", "tl" or "bl"). */ relativePosition: null, /** * APIProperty: keepInMap * {Boolean} If panMapIfOutOfView is false, and this property is true, * contrain the popup such that it always fits in the available map * space. By default, this is set. If you are creating popups that are * near map edges and not allowing pannning, and especially if you have * a popup which has a fixedRelativePosition, setting this to false may * be a smart thing to do. * * For anchored popups, default is true, since subclasses will * usually want this functionality. */ keepInMap: true, /** * Parameter: anchor * {Object} Object to which we'll anchor the popup. Must expose a * 'size' (<OpenLayers.Size>) and 'offset' (<OpenLayers.Pixel>). */ anchor: null, /** * Constructor: OpenLayers.Popup.Anchored * * Parameters: * id - {String} * lonlat - {<OpenLayers.LonLat>} * contentSize - {<OpenLayers.Size>} * contentHTML - {String} * anchor - {Object} Object which must expose a 'size' <OpenLayers.Size> * and 'offset' <OpenLayers.Pixel> (generally an <OpenLayers.Icon>). * closeBox - {Boolean} * closeBoxCallback - {Function} Function to be called on closeBox click. */ initialize:function(id, lonlat, contentSize, contentHTML, anchor, closeBox, closeBoxCallback) { var newArguments = [ id, lonlat, contentSize, contentHTML, closeBox, closeBoxCallback ]; OpenLayers.Popup.prototype.initialize.apply(this, newArguments); this.anchor = (anchor != null) ? anchor : { size: new OpenLayers.Size(0,0), offset: new OpenLayers.Pixel(0,0)}; }, /** * APIMethod: destroy */ destroy: function() { this.anchor = null; this.relativePosition = null; OpenLayers.Popup.prototype.destroy.apply(this, arguments); }, /** * APIMethod: show * Overridden from Popup since user might hide popup and then show() it * in a new location (meaning we might want to update the relative * position on the show) */ show: function() { this.updatePosition(); OpenLayers.Popup.prototype.show.apply(this, arguments); }, /** * Method: moveTo * Since the popup is moving to a new px, it might need also to be moved * relative to where the marker is. We first calculate the new * relativePosition, and then we calculate the new px where we will * put the popup, based on the new relative position. * * If the relativePosition has changed, we must also call * updateRelativePosition() to make any visual changes to the popup * which are associated with putting it in a new relativePosition. * * Parameters: * px - {<OpenLayers.Pixel>} */ moveTo: function(px) { var oldRelativePosition = this.relativePosition; this.relativePosition = this.calculateRelativePosition(px); var newPx = this.calculateNewPx(px); var newArguments = new Array(newPx); OpenLayers.Popup.prototype.moveTo.apply(this, newArguments); //if this move has caused the popup to change its relative position, // we need to make the appropriate cosmetic changes. if (this.relativePosition != oldRelativePosition) { this.updateRelativePosition(); } }, /** * APIMethod: setSize * * Parameters: * contentSize - {<OpenLayers.Size>} the new size for the popup's * contents div (in pixels). */ setSize:function(contentSize) { OpenLayers.Popup.prototype.setSize.apply(this, arguments); if ((this.lonlat) && (this.map)) { var px = this.map.getLayerPxFromLonLat(this.lonlat); this.moveTo(px); } }, /** * Method: calculateRelativePosition * * Parameters: * px - {<OpenLayers.Pixel>} * * Returns: * {String} The relative position ("br" "tr" "tl" "bl") at which the popup * should be placed. */ calculateRelativePosition:function(px) { var lonlat = this.map.getLonLatFromLayerPx(px); var extent = this.map.getExtent(); var quadrant = extent.determineQuadrant(lonlat); return OpenLayers.Bounds.oppositeQuadrant(quadrant); }, /** * Method: updateRelativePosition * The popup has been moved to a new relative location, so we may want to * make some cosmetic adjustments to it. * * Note that in the classic Anchored popup, there is nothing to do * here, since the popup looks exactly the same in all four positions. * Subclasses such as the AnchoredBubble and Framed, however, will * want to do something special here. */ updateRelativePosition: function() { //to be overridden by subclasses }, /** * Method: calculateNewPx * * Parameters: * px - {<OpenLayers.Pixel>} * * Returns: * {<OpenLayers.Pixel>} The the new px position of the popup on the screen * relative to the passed-in px. */ calculateNewPx:function(px) { var newPx = px.offset(this.anchor.offset); //use contentSize if size is not already set var size = this.size || this.contentSize; var top = (this.relativePosition.charAt(0) == 't'); newPx.y += (top) ? -(size.h + this.anchor.size.h) : this.anchor.size.h; var left = (this.relativePosition.charAt(1) == 'l'); newPx.x += (left) ? -(size.w + this.anchor.size.w) : this.anchor.size.w; return newPx; }, CLASS_NAME: "OpenLayers.Popup.Anchored" }); |