[OpenLayers-Commits] r5678 - in sandbox/rdewit/kml: examples examples/openlayers_ext examples/openlayers_ext/bubble examples/openlayers_ext/bubble/img examples/openlayers_ext/bubble/img/corners lib/OpenLayers lib/OpenLayers/Format lib/OpenLayers/Layer lib/OpenLayers/Renderer

commits at openlayers.org commits at openlayers.org
Mon Jan 7 22:46:02 EST 2008


Author: rdewit
Date: 2008-01-07 22:46:02 -0500 (Mon, 07 Jan 2008)
New Revision: 5678

Added:
   sandbox/rdewit/kml/examples/openlayers_ext/
   sandbox/rdewit/kml/examples/openlayers_ext/bubble/
   sandbox/rdewit/kml/examples/openlayers_ext/bubble/Popup.js
   sandbox/rdewit/kml/examples/openlayers_ext/bubble/Tween.js
   sandbox/rdewit/kml/examples/openlayers_ext/bubble/Util.js
   sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/
   sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/close-hover.gif
   sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/close.gif
   sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/
   sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/botl.png
   sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/botm.png
   sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/botr.png
   sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/midl.png
   sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/midr.png
   sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/topl.png
   sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/topm.png
   sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/topr.png
   sandbox/rdewit/kml/examples/openlayers_ext/bubble/style.css
Modified:
   sandbox/rdewit/kml/examples/kml_wmsc_ows5.html
   sandbox/rdewit/kml/lib/OpenLayers/Ajax.js
   sandbox/rdewit/kml/lib/OpenLayers/Format/KML.js
   sandbox/rdewit/kml/lib/OpenLayers/Layer/WFS.js
   sandbox/rdewit/kml/lib/OpenLayers/Renderer/SVG.js
Log:
updates


Modified: sandbox/rdewit/kml/examples/kml_wmsc_ows5.html
===================================================================
--- sandbox/rdewit/kml/examples/kml_wmsc_ows5.html	2008-01-08 00:49:11 UTC (rev 5677)
+++ sandbox/rdewit/kml/examples/kml_wmsc_ows5.html	2008-01-08 03:46:02 UTC (rev 5678)
@@ -84,17 +84,20 @@
     <script src="../lib/OpenLayers.js"></script>
 
     <!-- Google Style Popups -->
-    <script src="openlayers_ext/bubble/Popup.Google.js"></script>
+    <link rel="stylesheet" href="openlayers_ext/bubble/style.css" type="text/css" />
+    <script src="openlayers_ext/bubble/Util.js"></script>
+    <script src="openlayers_ext/bubble/Tween.js"></script>
+    <script src="openlayers_ext/bubble/Popup.js"></script>
     <script type="text/javascript">
-        var POPUP_WIDTH = 400;
-        var POPUP_HEIGHT = 100;
+        //var POPUP_WIDTH = 400;
+        //var POPUP_HEIGHT = 100;
         OpenLayers.Popup = OpenLayers.Util.extend(OpenLayers.Popup, OpenLayers.Popup.Google);
     </script>
-    <script src="openlayers_ext/bubble/Anchored.Google.js"></script>
+    <script src="openlayers_ext/bubble/Anchored.js"></script>
     <script type="text/javascript">
         OpenLayers.Popup.Anchored = OpenLayers.Util.extend(OpenLayers.Popup.Anchored, OpenLayers.Popup.Anchored.Google);
     </script>
-    <script src="openlayers_ext/bubble/AnchoredBubble.Google.js"></script>
+    <script src="openlayers_ext/bubble/AnchoredBubble.js"></script>
     <script type="text/javascript">
         OpenLayers.Popup.AnchoredBubble = OpenLayers.Util.extend(OpenLayers.Popup.AnchoredBubble, OpenLayers.Popup.AnchoredBubble.Google);
     </script>
@@ -122,10 +125,12 @@
                   sld: "http://artois.openplans.org/slds/population.sld",
                   //sld: "http://geo.openplans.org:8080/geoserver/www/popshade.sld",
                   exceptions: "application/vnd.ogc.se_inimage",
-                  format: "application/kml+xml",
+                  format: "application/vnd.google-earth.kmz",
+                  //format: "application/kml+xml",
+                  //format: "application/kml+xml",
                   //format: "image/jpeg",
                   remote_ows_type: "WFS",
-                  remote_ows_urL: "http://sigma.openplans.org:8080/geoserver/wfsd"
+                  remote_ows_url: "http://sigma.openplans.org:8080/geoserver/wfsd"
         };
 
         //http://geo.openplans.org:8080/geoserver/wms?bbox=-180,-90,180,90&Format=application/kml+xml&request=GetMap&&width=600&height=317&srs=EPSG:4326&sld=http://artois.openplans.org/slds/population.sld&layers=topp:tasmania_roads,topp:tasmania_state_boundaries
@@ -210,13 +215,13 @@
                 if (feature.attributes.name) {
                     content  = "<strong>" + feature.attributes.name +"</strong><br />";
                 }
-                content += feature.attributes.description;
+                content += feature.attributes.description || "";
             }
 
 
             popup = new OpenLayers.Popup.AnchoredBubble("chicken", 
                                      feature.geometry.getBounds().getCenterLonLat(),
-                                     new OpenLayers.Size(250,175),
+                                     new OpenLayers.Size(350,200),
                                      "<div style='font-size:.8em;overflow:auto;width:100%;'>" + content + "</div>",
                                      null, true, onPopupClose);
             feature.popup = popup;
@@ -275,11 +280,18 @@
                 if(features.constructor != Array) {
                     features = [features];
                 }
-                vectors.addFeatures(features);
+
+                var kmlLayer = new OpenLayers.Layer.Vector("KML " + kml_counter++, {transparent: true});
+                kmlLayer.addFeatures(features);
+
+                addLayerToMap(kmlLayer, true);
+
+                /*
                 bounds = getFeaturesBounds(features);
                 if (bounds) {
                     map.zoomToExtent(bounds);
                 }
+                */
                 var plural = (features.length != 1) ? 's' : '';
                 status.innerHTML = features.length + ' feature' + plural + ' added';
                 if (features.length == 0) {
@@ -365,6 +377,33 @@
                 }
             }
         }
+
+        function addLayerToMap(layer, zoomToBounds) {
+
+            // register load events
+            layer.events.register('loadstart', layer, increaseLoadingLayers);
+            layer.events.register('loadend', layer, decreaseLoadingLayers);
+
+            // add layer to map
+            map.addLayer(layer);
+
+            // add onclick events
+            var selectControl = new OpenLayers.Control.SelectFeature(layer, {
+                onSelect: onFeatureSelect, 
+                onUnselect: onFeatureUnselect
+            });
+            map.addControl(selectControl);
+            selectControl.activate();
+
+            // zoom to extent of layer if asked for
+            if (zoomToBounds && layer.features) {
+                bounds = getFeaturesBounds(layer.features);
+                if (bounds) {
+                    map.zoomToExtent(bounds);
+                }
+            }
+        }
+
         function addWmscLayer() {
             refreshWmscParams();
             imageSize = vectors.getImageSize();
@@ -381,6 +420,8 @@
             switch (wmscParams.FORMAT) {
                 case "kml":
                 case "application/kml+xml":
+                case "application/vnd.google-earth.kml+xml":
+                case "application/vnd.google-earth.kmz":
                     wmscLayer = new OpenLayers.Layer.WFS( "Component WMS " + wmsc_counter++, 
                             wmscURL, wmscParams, {format: OpenLayers.Format.KML, extractAttributes: true} );
                     break;
@@ -395,16 +436,9 @@
                 default:
                     alert("Sorry, format '" + wmscParams.FORMAT + "' is unknown to me");
                     return false;
-                }
-            //console.info(wmscLayer);
-            wmscLayer.events.register('loadstart', wmscLayer, increaseLoadingLayers);
-            wmscLayer.events.register('loadend', wmscLayer, decreaseLoadingLayers);
-            map.addLayer(wmscLayer);
+            }
 
-            bounds = getFeaturesBounds(wmscLayer.features);
-            if (bounds) {
-                map.zoomToExtent(bounds);
-            }
+            addLayerToMap(wmscLayer);
         }
 
         function increaseLoadingLayers() {
@@ -461,7 +495,6 @@
                 <option value="kml_elections/aus.kml">Elections AUS all (too big)</option>
                 <option value="kml_elections/district_names.kml">Elections district_names.kml</option>
                 <option disabled="disabled" value="">TOPP OWS-5 Demo Service KML 2.2 (states US)</option>
-                <option value=""></option>
                 -->
                 <option value="kml_elections/aus_nt.kml">Elections NT</option>
                 <option value="kml_elections/doc.kml">Elections NetworkLink</option>
@@ -473,6 +506,9 @@
                 <!--
                 <option value="http://featureserver.org/featureserver.cgi/scribble?format=KML">FeatureServer Scribble</option>
                 -->
+                <option value="http://maps.google.com/maps/ms?ie=UTF8&hl=en&om=1&msa=0&output=nl&msid=103763259662194171141.000001119b4b42bf062c2">Google - Route 66 (NetworkLink)</option>
+                <option value="http://maps.google.com/maps/ms?ie=UTF8&t=k&hl=en&msa=0&msid=103763259662194171141.000001119b4d1da52255a&output=kml">Google - Monsters</option>
+                <option value="http://press.jrc.it/NewsExplorer/kmledition/en/latest.kml">EMM World News</option>
                 <option value='http://code.google.com/apis/kml/documentation/KML_Samples.kml'>Google KML Sample</option>
                 <option value='http://geo.openplans.org:8080/geoserver/wms?bbox=-128,23,-64,51&Format=application/vnd.google-earth.kml+xml&request=GetMap&&width=600&height=317&srs=EPSG:4326&sld=http://artois.openplans.org/slds/population.sld'>TOPP OWS-5 Demo Service KML 2.2 (states US)</option>
                 <option value='http://geo.openplans.org:8080/geoserver/wms?bbox=-128,23,-64,51&Format=application/kml+xml&request=GetMap&&width=600&height=317&srs=EPSG:4326&sld=http://artois.openplans.org/slds/population.sld'>TOPP OWS-5 Demo Service KML OWS-5 (states US)</option>
@@ -503,6 +539,16 @@
     </div>
     <div id="info">
         <h3>Changelog</h3>
+        <p><strong>Version 0.2 (2008-01-08)</strong> <br />
+        <ul>
+          <li><em>Note: only tested in Firefox!</em></li>
+          <li>Few more examples</li>
+          <li>Incorporated Google style popups</li>
+          <li>Better exception reporting</li>
+          <li>Component WMS layers have popups now too</li>
+          <li>KMZ support</li>
+        </ul>
+        </p>
         <p><strong>Version 0.1 (2007-12-17)</strong> <br />
         <ul>
           <li><em>Note: only tested in Firefox!</em></li>

Added: sandbox/rdewit/kml/examples/openlayers_ext/bubble/Popup.js
===================================================================
--- sandbox/rdewit/kml/examples/openlayers_ext/bubble/Popup.js	                        (rev 0)
+++ sandbox/rdewit/kml/examples/openlayers_ext/bubble/Popup.js	2008-01-08 03:46:02 UTC (rev 5678)
@@ -0,0 +1,663 @@
+/* Copyright (c) 2006-2007 MetaCarta, Inc., published under the Clear BSD
+ * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * Class: OpenLayers.Popup
+ *
+ * A popup is a small div that can opened and closed on the map.
+ * Typically opened in response to clicking on a marker.  
+ * See <OpenLayers.Marker>.  Popup's don't require their own
+ * layer and are added the the map using the <OpenLayers.Map.addPopup>
+ * method.
+ *
+ * Example:
+ * (code)
+ * popup = new OpenLayers.Popup("chicken", 
+ *                    new OpenLayers.LonLat(5,40),
+ *                    new OpenLayers.Size(200,200),
+ *                    "example popup",
+ *                    true);
+ *       
+ * map.addPopup(popup);
+ * (end)
+ */
+
+OpenLayers.Position = {
+    TOP_LEFT: "top-left",
+    TOP_RIGHT: "top-right",
+    BOTTOM_LEFT: "bottom-left",
+    BOTTOM_RIGHT: "bottom-right"   
+};
+
+OpenLayers.Popup.Google = OpenLayers.Class({
+
+    /**
+     * Constant: SHIFT_ANIMATION_TIME
+     * {Integer} The number of milliseconds a resize animation should take.
+     */
+    RESIZE_ANIMATION_TIME: 2000,
+    
+    /**
+     * Constant: SHIFT_INTERVAL
+     * {Integer} The interval (in milliseconds) at which the popup should resize
+     * during a resize animation.
+     */
+    RESIZE_INTERVAL: 10,
+    
+    resizeTimeoutId: null,
+
+    /** 
+     * Property: events  
+     * {<OpenLayers.Events>} custom event manager 
+     */
+    events: null,
+    
+    /** Property: id
+     * {String} the unique identifier assigned to this popup.
+     */
+    id: "",
+
+    /** 
+     * Property: lonlat 
+     * {<OpenLayers.LonLat>} the position of this popup on the map
+     */
+    lonlat: null,
+
+    /** 
+     * Property: div 
+     * {DOMElement} the div that contains this popup.
+     */
+    div: null,
+
+    /** 
+     * Property: size 
+     * {<OpenLayers.Size>} the width and height of the popup.
+     */
+    size: null,    
+
+    /** 
+     * Property: contentHTML 
+     * {String} The HTML that this popup displays.
+     */
+    contentHTML: "",
+    
+    /** 
+     * Property: opacity 
+     * {float} the opacity of this popup (between 0.0 and 1.0)
+     */
+    opacity: "",
+
+    /** 
+     * Property: map 
+     * {<OpenLayers.Map>} Reference to the map.
+     */
+    map: null,
+    
+    /**
+     * Property: closeButton
+     * {Boolean} true if a closeButton should be put in this popup. 
+     * Defaults to true.
+     */
+    closeButton : true,
+    
+    /** 
+     * Property: relativePosition
+     * {<OpenLayers.Position>} Relative position of the popup in relation
+     * to its lonlat value. Defaults to TOP_LEFT.
+     */
+    relativePosition: OpenLayers.Position.TOP_LEFT,
+    
+    /**
+     * APIMethod: onLoad
+     * {Function} Optional function to be called when the popup is fully drawn.
+     */
+    onLoad : function() {},
+    
+    /**
+     * APIMethod: onClose
+     * {Function} Optional function to be called when close button is clicked.
+     */
+    onClose : function() {},
+    
+    /**
+     * Property: sizeTween
+     * 
+     * {<OpenLayers.Tween>} - animation tween
+     */
+    sizeTween: new OpenLayers.Tween(OpenLayers.Easing.Expo.easeOut),
+    
+    /** 
+     * Constructor: OpenLayers.Popup
+     * Create a popup.
+     * 
+     * Parameters: 
+     * id - {String} a unqiue identifier for this popup.  If null is passed
+     *     an identifier will be automatically generated. 
+     * lonlat - {<OpenLayers.LonLat>} The position on the map the popup will
+     *     be shown.
+     * size - {<OpenLayers.Size>} The size of the popup. If null, the popup will
+     *     try to determine the correct size on its own.
+     * content - {String or DOM element} The HTML content to display inside
+     *     the popup.  Or a DOM element.
+     * closeButton - {Boolean} Whether to display a close button inside the popup. 
+     *     Defaults to true.
+     */
+    initialize:function(id, lonlat, size, content, closeButton) {
+        if (id == null) {
+            id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
+        }
+
+        this.id = id;
+        this.lonlat = lonlat;
+        
+        if (closeButton != null) {
+            this.closeButton = closeButton;
+        }
+        
+        // Create main division. For now (until the popup receives the draw
+        // command), position the div offscreen, absolutely, so it can be
+        // rendered without being seen by the user.
+        this.div = OpenLayers.Util.createDiv(id, null, this.size, null,
+            "absolute", null);
+        this.div.className = 'olPopup';
+        this.div.style.overflow = "auto";
+        /*
+        TODO is this needed ?
+        seems to cause display bugs
+        this.div.style.left="-9999999999px";
+        this.div.style.top="0px";
+        */
+        
+        // If we were passed HTML, use that. Otherwise, treat the content as a DOM element.
+        if(typeof content == "string") {
+            this.div.innerHTML = content;
+        } else {
+            this.div.appendChild(content)
+        }
+        
+        if (size != null) {
+			this.size = size.clone();
+        }
+        
+        this.registerEvents();
+        
+        this.sizeTween = new OpenLayers.Tween(OpenLayers.Easing.Expo.easeOut);
+        
+        // Not sure if this should be here or elsewhere...
+        
+        // Although in some windowing systems there is a chance that the scroll
+        // bar may change widths while our application is running, lets assume it
+        // won't only calculate it once.
+        if (!OpenLayers.Popup.SCROLL_BAR_WIDTH) {
+            // We have to set this at a time after the document has loaded...
+            OpenLayers.Popup.SCROLL_BAR_WIDTH = OpenLayers.Util.getScrollBarWidth();
+        }
+    },
+    
+    /**
+     * TODO add doc
+     */
+    getPackedSize: function() {
+        return OpenLayers.Util.getDOMElementPackedSize(this.div);
+    },
+    
+    /**
+     * Resize the popup to the size given. If no size is passed,
+     * the popup will size to the width/height of its content.
+     * 
+     * Note: The size passed to this function refers to the size of
+     * the content, not the size of the containing div. The size of
+     * the containing div is always reactive to the size of the content.
+     */ 
+    resize: function(newSize) {
+        
+        var from = {
+            w: this.size.w,
+            h: this.size.h
+        };
+        var to = {
+            w: newSize.w,
+            h: newSize.h
+        };
+        
+        var step = function(object) {
+            var size = new OpenLayers.Size(object.w, object.h);
+            this.setSize(size, true);
+        };
+        
+        this.sizeTween.start(from, to, 50, 
+            {
+                eachStep: OpenLayers.Function.bind(step, this),
+                done: OpenLayers.Function.bind(this.shiftMapIfNotViewable, this)
+            }
+        );
+    },
+        
+    /**
+     * TODO: is this used ? in inherited classes ?
+     */
+    pack: function() {
+        this.resize(this.getPackedSize());
+    },
+    
+    /**
+     * TODO: add doc
+     */
+    shiftMapIfNotViewable : function(alternateSize) {
+        var sizeToUse = (alternateSize != null) ? alternateSize : this.size;
+        
+        var mapSize = this.map ? this.map.getSize() : null;
+        var popupPosition = this.calculateRelativePosition(this.map.getViewPortPxFromLonLat(this.lonlat), sizeToUse);
+    
+        // Get the current center before any shift.
+        var center = this.map.getViewPortPxFromLonLat(this.map.getCenter());
+        var newCenter = center.clone();
+        
+        var top = popupPosition.y;
+        var right = popupPosition.x + sizeToUse.w;
+        var bottom = popupPosition.y + sizeToUse.h;
+        var left = popupPosition.x;
+        
+        // TODO: check race condition
+        // what if left is not visible and right is not visible ?
+        
+        // If left is not visible...
+        if (left < OpenLayers.Popup.POPUP_MARGIN.left) {
+            newCenter.x += left - OpenLayers.Popup.POPUP_MARGIN.left;
+        }
+         
+        // If right is not visible...
+        if (right > mapSize.w - OpenLayers.Popup.POPUP_MARGIN.right) {
+            newCenter.x += parseInt(right - mapSize.w + OpenLayers.Popup.POPUP_MARGIN.right);
+        }
+        
+        // If top is not visible...
+        if (top < OpenLayers.Popup.POPUP_MARGIN.top) {
+            newCenter.y += top - OpenLayers.Popup.POPUP_MARGIN.top;
+        }
+        
+        // If bottom is not visible...
+        if (bottom > mapSize.h - OpenLayers.Popup.POPUP_MARGIN.bottom) {
+            newCenter.y += parseInt(bottom - mapSize.h + OpenLayers.Popup.POPUP_MARGIN.bottom);
+        }
+        
+//        this.map.shiftToViewPortPx(newCenter);
+        var dx = newCenter.x - center.x;
+        var dy = newCenter.y - center.y;
+        this.map.pan(dx, dy);
+    },
+    
+    /** 
+     * APIMethod: Set the size of the popup. This function makes
+     * sure the popup does not get sized larger than the viewport.
+     * 
+     * TODO: complete doc, is this really an APIMethod ?
+     */
+    setSize: function(size, ignoreMapBounds) {
+        if (!ignoreMapBounds) {
+            size = this.constrainSizeToView(size);
+        }
+        
+        this.size = size;
+        
+        this.div.style.width = this.size.w + "px";
+        this.div.style.height = this.size.h + "px";
+           
+        this.updatePosition();
+    },
+    
+    /*
+     * TODO: complete doc
+     */
+    constrainSizeToView: function(size) {
+        size = size.clone();
+        
+        // Restrict the size if it's greater than the map's viewport.
+        var mapSize = this.map.size;
+        
+        // Calculate the difference between the container and the content
+        // and scale the content accordingly.
+        var heightDifference = size.h - 
+            (mapSize.h - 
+             OpenLayers.Popup.POPUP_MARGIN.top - 
+             OpenLayers.Popup.POPUP_MARGIN.bottom);
+        
+        if (heightDifference > 0) {
+            size.h -= heightDifference;
+        }
+        
+        var widthDifference = size.w - 
+            (mapSize.w - 
+             OpenLayers.Popup.POPUP_MARGIN.left - 
+             OpenLayers.Popup.POPUP_MARGIN.right +
+             OpenLayers.Popup.SCROLL_BAR_WIDTH);
+        
+        if (widthDifference > 0) {
+            size.w -= widthDifference;
+        } else if (size.w + OpenLayers.Popup.SCROLL_BAR_WIDTH < mapSize.w){
+            size.w += OpenLayers.Popup.SCROLL_BAR_WIDTH;
+        }
+        
+        return size;
+    },
+    
+    /**
+     * TODO: doc
+     */
+    createCloseButton: function() {
+        var oBtnClose = document.createElement("A");
+        oBtnClose.id="olPopupCloseButton";
+        oBtnClose.className="close";
+        oBtnClose.style.position="absolute";
+        oBtnClose.title="close popup";
+        oBtnClose.href="#";
+        this.div.appendChild(oBtnClose);
+        
+        // Register close button event.
+        var closeEvents = new OpenLayers.Events(this, oBtnClose);
+        closeEvents.register("mousedown", this, this.hide);
+    },
+
+    /** 
+     * APIMethod: destroy
+     * nullify references to prevent circular references and memory leaks
+     */
+    destroy: function() {
+        if (this.map != null) {
+            this.map.removePopup(this);
+        }
+        this.div = null;
+        this.map = null;
+    },
+
+    /** 
+    * APIMethod: draw
+    * Constructs the elements that make up the popup.
+    *
+    * Parameters:
+    * px - {<OpenLayers.Pixel>} The top and left position of
+    * the popup in pixels. 
+    * 
+    * Returns:
+    * {DOMElement} Reference to a div that contains the drawn popup
+    */
+    draw: function(px) {
+        // Only append the div to the body if it's not already appended somewhere.
+        // This allows for "pre-rendering" offscreen where the user doesn't see it.
+        if (!this.div.parentNode) {
+            document.body.appendChild(this.div);
+        }
+        
+        if (this.size == null) {
+            this.setSize(this.getPackedSize());
+        } else {
+            this.setSize(this.size);
+        }
+        
+        // Add a close button if needed.
+        if (this.closeButton) {
+            this.createCloseButton();
+        }  
+        
+        this.onLoad();
+        
+        this.updatePosition();
+        
+        /*
+         * by Pierre GIRAUD: I would prefer something like if (!viewable) { .. doSomething .. }
+         */
+        this.shiftMapIfNotViewable();
+          
+        return this.div;
+    },
+    
+    /** 
+     * Method: updatePosition
+     * if the popup has a lonlat and its map members set, 
+     * then have it move itself to its proper position
+     * 
+     * TODO: doc
+     */
+    updatePosition: function(px) {
+        if (px == null && this.map) {
+            px = this.map.getLayerPxFromLonLat(this.lonlat);
+        }
+        this.moveTo(px);           
+    },
+    
+    /**
+     * Method: calculateRelativePosition
+     * 
+     * Calculate the position of the popup (or what the popup should be)
+     * given a starting pixel position and a size value.
+     * 
+     * Parameters:
+     * px - {<OpenLayers.Pixel>} The top and left position of the popup div.
+     * size - {<OpenLayers.Size>} The size of the popup div(or the size that 
+     * it should be).
+     * 
+     * Returns: 
+     * {<OpenLayers.Pixel>} The new top and left position of the popup div.
+     */
+    calculateRelativePosition: function(px, size) {
+        
+        px = px.clone();
+        
+        if (this.relativePosition == OpenLayers.Position.TOP_RIGHT ||
+            this.relativePosition == OpenLayers.Position.BOTTOM_RIGHT) {
+            px.x -= size.w;
+        }
+        
+        if (this.relativePosition == OpenLayers.Position.BOTTOM_LEFT ||
+            this.relativePosition == OpenLayers.Position.BOTTOM_RIGHT) {
+            px.y -= size.h;
+        }
+        
+        return px; 
+    },
+
+    /**
+     * Method: moveTo
+     * 
+     * Parameters:
+     * px - {<OpenLayers.Pixel>} the top and left position of the popup div. 
+     */
+    moveTo: function(px) {
+        px = this.calculateRelativePosition(px, this.size);
+        
+        this.div.style.left = px.x + "px";
+        this.div.style.top = px.y + "px";
+    },
+
+    /**
+     * Method: visible
+     *
+     * Returns:      
+     * {Boolean} Boolean indicating whether or not the popup is visible
+     */
+    visible: function() {
+        return OpenLayers.Element.visible(this.div);
+    },
+
+    /**
+     * Method: toggle
+     * Toggles visibility of the popup.
+     */
+    toggle: function() {
+        OpenLayers.Element.toggle(this.div);
+    },
+
+    /**
+     * Method: show
+     * Makes the popup visible.
+     */
+    show: function() {
+        OpenLayers.Element.show(this.div);
+    },
+
+    /**
+     * Method: hide
+     * Makes the popup invisible.
+     */
+    hide: function() {
+        if (this.map) {
+			this.map.removePopup(this);
+		}
+        OpenLayers.Element.hide(this.div);
+        this.onClose();
+    },
+    
+    /**
+     * Method: setOpacity
+     * Sets the opacity of the popup.
+     * 
+     * Parameters:
+     * opacity - {float} A value between 0.0 (transparent) and 1.0 (solid).   
+     */
+    setOpacity:function(opacity) { 
+        if (opacity != undefined) {
+            this.opacity = opacity; 
+        }
+        
+        if (this.div != null) {
+            // for Mozilla and Safari
+            this.div.style.opacity = this.opacity;
+
+            // for IE
+            this.div.style.filter = 'alpha(opacity=' + this.opacity*100 + ')';
+        }
+    },  
+
+    /** 
+     * Method: registerEvents
+     * Registers events on the popup.
+     *
+     * Do this in a separate function so that subclasses can 
+     *   choose to override it if they wish to deal differently
+     *   with mouse events
+     * 
+     *   Note in the following handler functions that some special
+     *    care is needed to deal correctly with mousing and popups. 
+     *   
+     *   Because the user might select the zoom-rectangle option and
+     *    then drag it over a popup, we need a safe way to allow the
+     *    mousemove and mouseup events to pass through the popup when
+     *    they are initiated from outside.
+     * 
+     *   Otherwise, we want to essentially kill the event propagation
+     *    for all other events, though we have to do so carefully, 
+     *    without disabling basic html functionality, like clicking on 
+     *    hyperlinks or drag-selecting text.
+     */
+    registerEvents:function() {
+        this.events = new OpenLayers.Events(this, this.div, null, true);
+        this.events.register("mousedown", this, this.onmousedown);
+        this.events.register("mousemove", this, this.onmousemove);
+        this.events.register("mouseup", this, this.onmouseup);
+        this.events.register("click", this, this.onclick);
+        this.events.register("mouseout", this, this.onmouseout);
+        this.events.register("dblclick", this, this.ondblclick);
+        this.events.register("mouseover", this, this.onmouseover);
+    },
+
+    /** 
+     * Method: onmousedown 
+     * When mouse goes down within the popup, make a note of
+     *   it locally, and then do not propagate the mousedown 
+     *   (but do so safely so that user can select text inside)
+     * 
+     * Parameters:
+     * evt - {Event} 
+     */
+    onmousedown: function (evt) {
+        this.mousedown = true;
+        OpenLayers.Event.stop(evt, true);
+    },
+
+    /** 
+     * Method: onmousemove
+     * If the drag was started within the popup, then 
+     *   do not propagate the mousemove (but do so safely
+     *   so that user can select text inside)
+     * 
+     * Parameters:
+     * evt - {Event} 
+     */
+    onmousemove: function (evt) {
+        if (this.mousedown) {
+            OpenLayers.Event.stop(evt, true);
+        }
+    },
+    
+    // Do nothing. It's here for child classes.
+    onmouseover: function(evt) {},
+
+    /** 
+     * Method: onmouseup
+     * When mouse comes up within the popup, after going down 
+     *   in it, reset the flag, and then (once again) do not 
+     *   propagate the event, but do so safely so that user can 
+     *   select text inside
+     * 
+     * Parameters:
+     * evt - {Event} 
+     */
+    onmouseup: function (evt) {
+        if (this.mousedown) {
+            this.mousedown = false;
+            OpenLayers.Event.stop(evt, true);
+        }
+    },
+
+    /**
+     * Method: onclick
+     * Ignore clicks, but allowing default browser handling
+     * 
+     * Parameters:
+     * evt - {Event} 
+     */
+    onclick: function (evt) {
+        OpenLayers.Event.stop(evt, true);
+    },
+
+    /** 
+     * Method: onmouseout
+     * When mouse goes out of the popup set the flag to false so that
+     *   if they let go and then drag back in, we won't be confused.
+     * 
+     * Parameters:
+     * evt - {Event} 
+     */
+    onmouseout: function (evt) {
+        this.mousedown = false;
+    },
+    
+    /** 
+     * Method: ondblclick
+     * Ignore double-clicks, but allowing default browser handling
+     * 
+     * Parameters:
+     * evt - {Event} 
+     */
+    ondblclick: function (evt) {
+        OpenLayers.Event.stop(evt, true);
+    },
+
+    CLASS_NAME: "OpenLayers.Popup"
+});
+
+/**
+ * APIProperty: margin
+ * {<OpenLayers.Bounds>} Left, bottom, right, and top margins constraining
+ * both a popup's size as well as where the map is shifted when shown.
+ * The data container use is an OpenLayers.Bounds instance, it is not meant
+ * to be used like a traditional OpenLayers.Bounds. For instance, to specify
+ * a margin with only a right value, one would do the following, stating
+ * that a popup should be contstrained 15 pixels left of the map's right
+ * side:
+ * 
+ * new OpenLayers.Bounds(0, 0, 15, 0);
+ */
+OpenLayers.Popup.POPUP_MARGIN = new OpenLayers.Bounds(0, 0, 0, 0);
+

Added: sandbox/rdewit/kml/examples/openlayers_ext/bubble/Tween.js
===================================================================
--- sandbox/rdewit/kml/examples/openlayers_ext/bubble/Tween.js	                        (rev 0)
+++ sandbox/rdewit/kml/examples/openlayers_ext/bubble/Tween.js	2008-01-08 03:46:02 UTC (rev 5678)
@@ -0,0 +1,197 @@
+/* Copyright (c) 2006-2007 MetaCarta, Inc., published under the Clear BSD
+ * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * Namespace: OpenLayers.Tween
+ */
+OpenLayers.Tween = OpenLayers.Class({
+    
+    /**
+     * Constant: INTERVAL
+     * Interval in milliseconds between 2 steps
+     */
+    INTERVAL: 10,
+    
+    /**
+     * 
+     * Params:
+     * easing - {<OpenLayers.Easing>(Function)} easing function method to use
+     */ 
+    initialize: function(easing) {
+        this.easing = easing;
+    },
+    
+    /**
+     * APIMethod: start
+     * Plays the Tween, and calls the callback method on each step
+     * 
+     * begin - {Object} begin value 
+     * finish - {Object} finish value (should have the same properties as begin)
+     * duration - {int} duration of the tween (number of steps)
+     * callback - {Object} callbacks (start, eachStep, done)
+     */
+    start: function(begin, finish, duration, callbacks) {
+        this.begin = begin;
+        this.finish = finish;
+        this.duration = duration;
+        this.time = 0;
+        if (this.interval) {
+            window.clearInterval(this.interval);
+            this.interval = null;
+        }
+        if (callbacks.start) {
+            callbacks.start.call(this, value);
+        }
+        this.interval = window.setInterval(
+            OpenLayers.Function.bind(this.ease, this, callbacks), this.INTERVAL);
+    },
+    
+    /**
+     * Method: ease
+     * Calls the appropriate easing method
+     * 
+     * callbacks - {Object} callbacks
+     */
+    ease: function(callbacks) {
+        if (this.time >= this.duration) {
+            if (callbacks.done) {
+                callbacks.done.call(this, value);
+            }
+            window.clearInterval(this.interval);
+            this.interval = null;
+        }
+        
+        var value = {};
+        for (var i in this.begin) {
+            var b = this.begin[i];
+            var f = this.finish[i];
+            if (b == null || f == null || isNaN(b) || isNaN(f)) {
+                OpenLayers.Console.error('invalid value for Tween');
+            }
+            
+            var c = f - b;
+            value[i] = this.easing.apply(this, [this.time, b, c, this.duration]);
+        }
+        this.time++;
+        
+        if (callbacks.eachStep) {
+            callbacks.eachStep.call(this, value);
+        }
+    },
+    
+    /**
+     * Create empty functions for all easing methods.
+     */
+    CLASS_NAME: "OpenLayers.Tween"
+});
+
+/**
+ * Namespace: OpenLayers.Easing
+ * 
+ * Credits:
+ *      Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>
+ */
+OpenLayers.Easing = {
+    /**
+     * Create empty functions for all easing methods.
+     */
+    CLASS_NAME: "OpenLayers.Easing"
+}
+
+/**
+ * Namespace: OpenLayers.Easing.Linear
+ */
+OpenLayers.Easing.Linear = {
+    
+    /**
+     * APIFunction: easeIn
+     * 
+     * Parameters:
+     * t - {Float} time
+     * b - {Float} beginning position
+     * c - {Float} total change
+     * d - {Float} duration of the transition
+     */
+    easeIn: function(t, b, c, d) {
+        return c*t/d + b;
+    },
+    
+    /**
+     * APIFunction: easeOut
+     * 
+     * Parameters:
+     * t - {Float} time
+     * b - {Float} beginning position
+     * c - {Float} total change
+     * d - {Float} duration of the transition
+     */
+	easeOut: function(t, b, c, d) {
+		return c*t/d + b;
+	},
+    
+	/**
+     * APIFunction: easeInOut
+     * 
+     * Parameters:
+     * t - {Float} time
+     * b - {Float} beginning position
+     * c - {Float} total change
+     * d - {Float} duration of the transition
+     */
+    easeInOut: function(t, b, c, d) {
+		return c*t/d + b;
+	},
+
+    CLASS_NAME: "OpenLayers.Easing.Linear"
+};
+
+/**
+ * Namespace: OpenLayers.Easing.Expo
+ */
+OpenLayers.Easing.Expo = {
+    
+    /**
+     * APIFunction: easeIn
+     * 
+     * Parameters:
+     * t - {Float} time
+     * b - {Float} beginning position
+     * c - {Float} total change
+     * d - {Float} duration of the transition
+     */
+    easeIn: function(t, b, c, d) {
+        return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
+    },
+    
+    /**
+     * APIFunction: easeOut
+     * 
+     * Parameters:
+     * t - {Float} time
+     * b - {Float} beginning position
+     * c - {Float} total change
+     * d - {Float} duration of the transition
+     */
+	easeOut: function(t, b, c, d) {
+		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
+	},
+    
+	/**
+     * APIFunction: easeInOut
+     * 
+     * Parameters:
+     * t - {Float} time
+     * b - {Float} beginning position
+     * c - {Float} total change
+     * d - {Float} duration of the transition
+     */
+    easeInOut: function(t, b, c, d) {
+		if (t==0) return b;
+		if (t==d) return b+c;
+		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
+		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
+	},
+
+    CLASS_NAME: "OpenLayers.Easing.Expo"
+};
\ No newline at end of file

Added: sandbox/rdewit/kml/examples/openlayers_ext/bubble/Util.js
===================================================================
--- sandbox/rdewit/kml/examples/openlayers_ext/bubble/Util.js	                        (rev 0)
+++ sandbox/rdewit/kml/examples/openlayers_ext/bubble/Util.js	2008-01-08 03:46:02 UTC (rev 5678)
@@ -0,0 +1,46 @@
+/* Copyright (c) 2006-2007 MetaCarta, Inc., published under the Clear BSD
+ * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+// Pilferred from here:
+// http://www.fleegix.org/articles/2006/05/30/getting-the-scrollbar-width-in-pixels
+OpenLayers.Util.getScrollBarWidth = function() {
+    var scr = null;
+    var inn = null;
+    var wNoScroll = 0;
+    var wScroll = 0;
+
+    // Outer scrolling div
+    scr = document.createElement('div');
+    scr.style.position = 'absolute';
+    scr.style.top = '-1000px';
+    scr.style.left = '-1000px';
+    scr.style.width = '100px';
+    scr.style.height = '50px';
+    // Start with no scrollbar
+    scr.style.overflow = 'hidden';
+
+    // Inner content div
+    inn = document.createElement('div');
+    inn.style.width = '100%';
+    inn.style.height = '200px';
+
+    // Put the inner div in the scrolling div
+    scr.appendChild(inn);
+    // Append the scrolling div to the doc
+    document.body.appendChild(scr);
+
+    // Width of the inner div sans scrollbar
+    wNoScroll = inn.offsetWidth;
+    // Add the scrollbar
+    scr.style.overflow = 'auto';
+    // Width of the inner div width scrollbar
+    wScroll = inn.offsetWidth;
+
+    // Remove the scrolling div from the doc
+    document.body.removeChild(
+        document.body.lastChild);
+
+    // Pixel width of the scroller
+    return (wNoScroll - wScroll);
+}

Added: sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/close-hover.gif
===================================================================
(Binary files differ)


Property changes on: sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/close-hover.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/close.gif
===================================================================
(Binary files differ)


Property changes on: sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/close.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/botl.png
===================================================================
(Binary files differ)


Property changes on: sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/botl.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/botm.png
===================================================================
(Binary files differ)


Property changes on: sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/botm.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/botr.png
===================================================================
(Binary files differ)


Property changes on: sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/botr.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/midl.png
===================================================================
(Binary files differ)


Property changes on: sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/midl.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/midr.png
===================================================================
(Binary files differ)


Property changes on: sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/midr.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/topl.png
===================================================================
(Binary files differ)


Property changes on: sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/topl.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/topm.png
===================================================================
(Binary files differ)


Property changes on: sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/topm.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/topr.png
===================================================================
(Binary files differ)


Property changes on: sandbox/rdewit/kml/examples/openlayers_ext/bubble/img/corners/topr.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: sandbox/rdewit/kml/examples/openlayers_ext/bubble/style.css
===================================================================
--- sandbox/rdewit/kml/examples/openlayers_ext/bubble/style.css	                        (rev 0)
+++ sandbox/rdewit/kml/examples/openlayers_ext/bubble/style.css	2008-01-08 03:46:02 UTC (rev 5678)
@@ -0,0 +1,356 @@
+div.olMapViewport {
+   -moz-user-select: none 
+}
+
+.olLayerGoogleCopyright {
+    left: 2px;
+    bottom: 2px;  
+}
+.olLayerGooglePoweredBy {
+    left: 2px;
+    bottom: 15px;   
+}
+.olControlAttribution {
+    font-size: smaller; 
+    right: 3px; 
+    bottom: 4.5em; 
+    position: absolute; 
+    display: block;
+}
+.olControlScale {
+    right: 3px;
+    bottom: 3em;
+    display: block;
+    position: absolute;
+    font-size: smaller;
+}
+.olControlPermalink {
+    right: 3px;
+    bottom: 1.5em;
+    display: block;
+    position: absolute;
+    font-size: smaller;
+} 
+
+div.olControlMousePosition {
+    bottom: 0em;
+    right: 3px;
+    display: block;
+    position: absolute;
+    font-family: Arial;
+    font-size: smaller;
+}
+
+.olControlOverviewMapContainer {
+    position: absolute;
+    bottom: 0px;
+    right: 0px;
+}
+
+.olControlOverviewMapElement {
+    padding: 10px 18px 10px 10px;
+    background-color: #00008B;
+    -moz-border-radius: 1em 0 0 0;
+}
+
+.olControlOverviewMapMinimizeButton {
+    right: 0px;
+    bottom: 80px;
+}    
+
+.olControlOverviewMapMaximizeButton {
+    right: 0px;
+    bottom: 80px;
+}
+
+.olControlOverviewMapExtentRectangle {
+   cursor: move;
+    border: 2px dotted red;
+}
+.olLayerGeoRSSDescription {
+    float:left;
+    width:100%;
+    overflow:auto;
+    font-size:1.0em;
+}
+.olLayerGeoRSSClose {
+    float:right;
+    color:gray;
+    font-size:1.2em;
+	margin-right:6px;
+    font-family:sans-serif;
+}
+.olLayerGeoRSSTitle {
+    float:left;font-size:1.2em;
+}
+
+.olControlNavToolbar { 
+    width:0px;
+    height:0px;
+}    
+.olControlNavToolbar div { 
+  display:block;
+  width:  28px;
+  height: 28px;
+  top: 300px;
+  left: 6px;
+  position: relative;
+}
+
+.olControlNavToolbar .olControlNavigationItemActive { 
+  background-image: url("img/panning-hand-on.png");
+  background-repeat: no-repeat;
+}
+.olControlNavToolbar .olControlNavigationItemInactive { 
+  background-image: url("img/panning-hand-off.png");
+  background-repeat: no-repeat;
+}
+.olControlNavToolbar .olControlZoomBoxItemActive { 
+  background-image: url("img/drag-rectangle-on.png");
+  background-color: orange;
+  background-repeat: no-repeat;
+}
+.olControlNavToolbar .olControlZoomBoxItemInactive { 
+  background-image: url("img/drag-rectangle-off.png");
+  background-repeat: no-repeat;
+}
+.olControlEditingToolbar  {
+    float:right;
+    right: 0px;
+    height: 30px; 
+    width: 200px;
+}
+.olControlEditingToolbar div { 
+  float:right;
+  width:  24px;
+  height: 24px;
+  margin: 5px;
+}
+.olControlEditingToolbar .olControlNavigationItemActive { 
+  background-image: url("img/pan_on.png");
+  background-repeat: no-repeat;
+}
+.olControlEditingToolbar .olControlNavigationItemInactive { 
+  background-image: url("img/pan_off.png");
+  background-repeat: no-repeat;
+}
+.olControlEditingToolbar .olControlDrawFeaturePointItemActive { 
+  background-image: url("img/draw_point_on.png");
+  background-repeat: no-repeat;
+}
+.olControlEditingToolbar .olControlDrawFeaturePointItemInactive { 
+  background-image: url("img/draw_point_off.png");
+  background-repeat: no-repeat;
+}
+.olControlEditingToolbar .olControlDrawFeaturePathItemInactive { 
+  background-image: url("img/draw_line_off.png");
+  background-repeat: no-repeat;
+}
+.olControlEditingToolbar .olControlDrawFeaturePathItemActive { 
+  background-image: url("img/draw_line_on.png");
+  background-repeat: no-repeat;
+}
+.olControlEditingToolbar .olControlDrawFeaturePolygonItemInactive { 
+  background-image: url("img/draw_polygon_off.png");
+  background-repeat: no-repeat;
+}
+.olControlEditingToolbar .olControlDrawFeaturePolygonItemActive { 
+  background-image: url("img/draw_polygon_on.png");
+  background-repeat: no-repeat;
+}
+
+.olHandlerBoxZoomBox {
+    border: 2px solid red;
+    position: absolute;
+    background-color: white;
+    opacity: 0.50;
+    font-size: 1px;
+    filter: alpha(opacity=50);
+}    
+
+.olPopup *
+{
+    margin: 0px;
+    padding: 0px;
+}
+
+a.close
+{
+    width: 14px;
+    height: 14px;
+    position: absolute;
+    top: 10px;
+    right: 10px;
+    background: url("img/close.gif") no-repeat top left;
+    margin: 0px;
+    font-size: 1px;
+    padding: 0px;
+    z-index: 751;
+}
+
+a.close:hover
+{
+    background: url("img/close-hover.gif") no-repeat top left;
+}
+
+/* Specify the default width, height, and background-color,
+   for an Openlayers popup. */ 
+.olPopup 
+{
+    width: 265px;
+    background-color: #FFFFFF;
+    margin: 0px !important;
+    padding: 2px !important;
+}
+
+.olPopup a 
+{
+    cursor: pointer;
+}
+
+.olPopup h1
+{
+    font-size: 12px;
+    font-weight:bold;
+    line-height:normal;
+}
+
+.olPopup h2
+{
+    font-size: small;
+    text-align: center;
+    padding: 2px 0px 2px 0px;
+    margin: 0px 6px 0px 6px;
+    text-transform:capitalize;
+}
+
+.olPopup .comment
+{
+    margin: 0px 0px 0px 1.5em;
+    width: 300px;
+}
+
+.olPopup table
+{
+    border-collapse:collapse;
+    padding: 0px;
+    margin-left: 1px;
+}
+
+.olPopup .discrete
+{
+    font-size: smaller;
+}
+
+.olPopup .controlDiv
+{
+    text-align:right;
+    margin-right:.5em;
+}
+
+.olPopup a.control
+{
+    text-transform: uppercase;
+}
+
+.olPopup .feeditem
+{
+    cursor: pointer;
+}
+
+.olBubbleFrame a.close
+{
+    right: 28px;
+}
+
+/* Top of the frame. */
+.olBubbleFrame #top-left {
+    background-image: url("img/corners/topl.png");
+    position: absolute;
+    top: 0px;
+    right: auto;
+    bottom: auto;
+    left: 0px;
+    width: 38px;
+    height: 28px;
+}
+
+.olBubbleFrame #top-middle {
+    position: absolute;
+    background-image: url("img/corners/topm.png");
+    top: 0px;
+    right: 38px;
+    bottom: auto;
+    left: 38px;
+    width: auto;
+    height: 28px;
+}
+
+.olBubbleFrame #top-right {
+    position: absolute;
+    background-image: url("img/corners/topr.png");
+    top: 0px;
+    right: 0px;
+    bottom: auto;
+    left: auto;
+    width: 38px;
+    height: 28px;
+}
+
+/* Middle of the frame. */
+.olBubbleFrame #middle-left {
+    position: absolute;
+    background-image: url("img/corners/midl.png");
+    top: 28px;
+    right: auto;
+    bottom: 68px;
+    left: 0px;
+    width: 38px;
+    height: auto;
+}
+
+.olBubbleFrame #middle-right {
+    position: absolute;
+    background-image: url("img/corners/midr.png");
+    top: 28px;
+    right: 0px;
+    bottom: 68px;
+    left: auto;
+    width: 38px;
+    height: auto;
+}
+
+/* Bottom of the frame. */
+.olBubbleFrame #bottom-left {
+    position: absolute;
+    background-image: url("img/corners/botl.png");
+    top: auto;
+    right: auto;
+    bottom: 30px;
+    left: 0px;
+    width: 38px;
+    height: 38px;
+}
+
+.olBubbleFrame #bottom-middle {
+    position: absolute;
+    background-image: url("img/corners/botm.png");
+    top: auto;
+    right: 97px;
+    bottom: 30px;
+    left: 38px;
+    width: auto;
+    height: 38px;
+}
+
+.olBubbleFrame #bottom-right {
+    position: absolute;
+    background-image: url("img/corners/botr.png");
+    top: auto;
+    right: 0px;
+    bottom: 0px;
+    left: auto;
+    width: 97px;
+    height: 68px;
+}
+

Modified: sandbox/rdewit/kml/lib/OpenLayers/Ajax.js
===================================================================
--- sandbox/rdewit/kml/lib/OpenLayers/Ajax.js	2008-01-08 00:49:11 UTC (rev 5677)
+++ sandbox/rdewit/kml/lib/OpenLayers/Ajax.js	2008-01-08 03:46:02 UTC (rev 5678)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2006-2007 MetaCarta, Inc., published under the Clear BSD
+/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
  * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
  * full text of the license. */
 
@@ -248,8 +248,7 @@
         this.options = {
             method:       'post',
             asynchronous: true,
-            contentType:  'application/x-www-form-urlencoded',
-            encoding:     'UTF-8',
+            contentType:  'application/xml',
             parameters:   ''
         };
         OpenLayers.Util.extend(this.options, options || {});
@@ -394,7 +393,7 @@
         if (typeof this.options.requestHeaders == 'object') {    
             var extras = this.options.requestHeaders;
             
-            if (typeof extra.push == 'function') {
+            if (typeof extras.push == 'function') {
                 for (var i = 0, length = extras.length; i < length; i += 2) {
                     headers[extras[i]] = extras[i+1];
                 }
@@ -493,14 +492,49 @@
 
     /**
      * Method: dispatchException
+     * If the optional onException function is set, execute it
+     * and then dispatch the call to any other listener registered
+     * for onException.
      * 
+     * If no optional onException function is set, we suspect that
+     * the user may have also not used
+     * OpenLayers.Ajax.Responders.register to register a listener
+     * for the onException call.  To make sure that something
+     * gets done with this exception, only dispatch the call if there
+     * are listeners.
+     *
+     * If you explicitly want to swallow exceptions, set
+     * request.options.onException to an empty function (function(){})
+     * or register an empty function with <OpenLayers.Ajax.Responders>
+     * for onException.
+     * 
      * Parameters:
      * exception - {?}
      */
     dispatchException: function(exception) {
-        (this.options.onException ||
-            OpenLayers.Ajax.emptyFunction)(this, exception);
-        OpenLayers.Ajax.Responders.dispatch('onException', this, exception);
+        var handler = this.options.onException;
+        if(handler) {
+            // call options.onException and alert any other listeners
+            handler(this, exception);
+            OpenLayers.Ajax.Responders.dispatch('onException', this, exception);
+        } else {
+            // check if there are any other listeners
+            var listener = false;
+            var responders = OpenLayers.Ajax.Responders.responders;
+            for (var i = 0; i < responders.length; i++) {
+                if(responders[i].onException) {
+                    listener = true;
+                    break;
+                }
+            }
+            if(listener) {
+                // call all listeners
+                OpenLayers.Ajax.Responders.dispatch('onException', this, exception);
+            } else {
+                // let the exception through
+                throw exception;
+            }
+        }
     }
 });
 

Modified: sandbox/rdewit/kml/lib/OpenLayers/Format/KML.js
===================================================================
--- sandbox/rdewit/kml/lib/OpenLayers/Format/KML.js	2008-01-08 00:49:11 UTC (rev 5677)
+++ sandbox/rdewit/kml/lib/OpenLayers/Format/KML.js	2008-01-08 03:46:02 UTC (rev 5678)
@@ -139,6 +139,10 @@
             //console.info(url);
             if(hrefNode) {
                 var href = OpenLayers.Util.getXmlNodeValue(hrefNode);
+                //console.info(href);
+                if (OpenLayers.ProxyHost && OpenLayers.String.startsWith(href, "http")) {
+                    href = OpenLayers.ProxyHost + escape(href);
+                }
                 var request = new OpenLayers.Ajax.Request(href, {method: 'get', asynchronous: false });
                 if (request && request.transport) {
                     this.read(request.transport.responseText);
@@ -158,6 +162,9 @@
             //console.info(link);
             if(hrefNode) {
                 var href = OpenLayers.Util.getXmlNodeValue(hrefNode);
+                if (OpenLayers.ProxyHost && OpenLayers.String.startsWith(href, "http")) {
+                    href = OpenLayers.ProxyHost + escape(href);
+                }
                 var request = new OpenLayers.Ajax.Request(href, {method: 'get', asynchronous: false });
                 if (request && request.transport) {
                     this.read(request.transport.responseText);
@@ -432,7 +439,11 @@
         var defaultStyle = OpenLayers.Feature.Vector.style["default"];
         OpenLayers.Util.extend(style, defaultStyle);
 
-            //console.info(this.styles);
+        // some KML files don't have a # for internal styles. add one
+        if (styleUrl.substring(0,4) != "http" && styleUrl.substring(0,1) != "#") {
+            styleUrl = "#" + styleUrl;
+        }
+
         var subStyle = this.styles[styleUrl];
         //console.info(subStyle);
         OpenLayers.Util.extend(style, subStyle);

Modified: sandbox/rdewit/kml/lib/OpenLayers/Layer/WFS.js
===================================================================
--- sandbox/rdewit/kml/lib/OpenLayers/Layer/WFS.js	2008-01-08 00:49:11 UTC (rev 5677)
+++ sandbox/rdewit/kml/lib/OpenLayers/Layer/WFS.js	2008-01-08 03:46:02 UTC (rev 5678)
@@ -80,6 +80,12 @@
       */
     format: null,
 
+    /* Property: parser
+     * {Object} Format object for parsing features 
+     * Non-API and only created if necessary (created from Tile/WFS.js) 
+     */ 
+    parser: null,     
+
     /**
      * Constructor: OpenLayers.Layer.WFS
      *

Modified: sandbox/rdewit/kml/lib/OpenLayers/Renderer/SVG.js
===================================================================
--- sandbox/rdewit/kml/lib/OpenLayers/Renderer/SVG.js	2008-01-08 00:49:11 UTC (rev 5677)
+++ sandbox/rdewit/kml/lib/OpenLayers/Renderer/SVG.js	2008-01-08 03:46:02 UTC (rev 5678)
@@ -344,7 +344,9 @@
             node.setAttributeNS(null, "cy", y);
             node.setAttributeNS(null, "r", radius);
         } else {
-            this.root.removeChild(node);
+            //if (node.parentNode && (node.parentNode == this.root)) {
+              this.root.removeChild(node);
+            //}
         }    
             
     },



More information about the Commits mailing list